From da6329802b746085c3bd3f188dca273db6653fbc Mon Sep 17 00:00:00 2001 From: lucor Date: Tue, 22 May 2012 18:34:11 +0200 Subject: [PATCH] Initial import for 1.4.x branch --- COPYRIGHT | 152 + LICENSE | 339 ++ README.md | 61 +- bin/crontab.php | 26 + conf/configure_metadata_cas.php | 51 + conf/configure_metadata_install.php | 218 + conf/configure_metadata_ldap.php | 71 + conf/init.inc.php | 22 + conf/init.php | 102 + lang/en/js/js.php | 16 + .../database/check_tablespace/language.php | 11 + .../database/custom_query/language.php | 18 + .../database/custom_query_report/language.php | 11 + .../execute_sql_from_file/language.php | 5 + .../database/mysql_table_check/language.php | 4 + .../oracle_freespa_report/language.php | 12 + .../oracle_session_report/language.php | 11 + .../file/advanced_file_transfer/language.php | 24 + .../file/check_tail_status/language.php | 15 + lang/en/plugins/file/create/language.php | 13 + lang/en/plugins/file/ftp_upload/language.php | 20 + lang/en/plugins/file/read_file/language.php | 11 + lang/en/plugins/file/retention/language.php | 31 + lang/en/plugins/file/scp/language.php | 22 + lang/en/plugins/file/search/language.php | 23 + lang/en/plugins/file/size_check/language.php | 20 + lang/en/plugins/file/watch/language.php | 17 + .../general/custom_script/language.php | 16 + .../general/spreadsheet_to_db/language.php | 20 + .../general/telnet_custom_script/language.php | 19 + .../windows_remote_execution/language.php | 16 + .../plugins/notification/jabber/language.php | 22 + .../en/plugins/notification/mail/language.php | 32 + .../plugins/notification/sms_ftp/language.php | 18 + .../notification/tibco_rvd/language.php | 18 + .../notification/tivoli_postemsg/language.php | 18 + .../system/check_glance_status/language.php | 28 + lang/en/plugins/system/cpu_idle/language.php | 13 + .../system/file_system_check/language.php | 18 + lang/en/plugins/system/mem_free/language.php | 14 + lang/en/plugins/system/ping/language.php | 11 + .../plugins/system/service_check/language.php | 14 + .../solaris_metadevice_check/language.php | 12 + .../system/solaris_svc_check/language.php | 11 + .../solaris_zfs_scrub_check/language.php | 11 + .../system/solaris_zpool_check/language.php | 15 + .../www/check_uri_response_code/language.php | 12 + .../www/http_download_file/language.php | 13 + .../www/testgen4web_simpletest/language.php | 22 + .../www/webservice_soapui/language.php | 13 + .../plugins/www/webtest_selenium/language.php | 18 + .../plugins/www/webtest_slimdog/language.php | 15 + lang/en/template/action_msg.php | 105 + lang/en/template/common.php | 379 ++ .../template/configure_metadata_install.php | 60 + lang/en/template/configure_metadata_ldap.php | 19 + lang/en/template/install.php | 64 + lang/en/template/menu.php | 49 + lang/en/template/plugin_common.php | 26 + lang/fr/js/js.php | 16 + .../database/check_tablespace/language.php | 11 + .../database/custom_query/language.php | 17 + .../database/custom_query_report/language.php | 11 + .../execute_sql_from_file/language.php | 12 + .../database/mysql_table_check/language.php | 11 + .../oracle_freespa_report/language.php | 12 + .../oracle_session_report/language.php | 11 + .../file/check_tail_status/language.php | 15 + lang/fr/plugins/file/create/language.php | 13 + lang/fr/plugins/file/ftp_upload/language.php | 21 + lang/fr/plugins/file/read_file/language.php | 11 + lang/fr/plugins/file/retention/language.php | 31 + lang/fr/plugins/file/search/language.php | 23 + lang/fr/plugins/file/size_check/language.php | 20 + .../general/custom_script/language.php | 16 + .../general/spreadsheet_to_db/language.php | 20 + .../general/telnet_custom_script/language.php | 19 + .../windows_remote_execution/language.php | 16 + .../plugins/notification/jabber/language.php | 22 + .../fr/plugins/notification/mail/language.php | 32 + .../plugins/notification/sms_ftp/language.php | 18 + .../notification/tibco_rvd/language.php | 18 + .../notification/tivoli_postemsg/language.php | 18 + .../system/check_glance_status/language.php | 28 + lang/fr/plugins/system/cpu_idle/language.php | 13 + .../system/file_system_check/language.php | 18 + lang/fr/plugins/system/mem_free/language.php | 13 + lang/fr/plugins/system/ping/language.php | 11 + .../plugins/system/service_check/language.php | 14 + .../solaris_metadevice_check/language.php | 12 + .../system/solaris_svc_check/language.php | 11 + .../solaris_zfs_scrub_check/language.php | 11 + .../system/solaris_zpool_check/language.php | 15 + .../www/check_uri_response_code/language.php | 12 + .../www/http_download_file/language.php | 13 + .../www/testgen4web_simpletest/language.php | 22 + .../www/webservice_soapui/language.php | 13 + .../plugins/www/webtest_selenium/language.php | 18 + .../plugins/www/webtest_slimdog/language.php | 15 + lang/fr/template/action_msg.php | 97 + lang/fr/template/common.php | 373 ++ .../template/configure_metadata_install.php | 60 + lang/fr/template/configure_metadata_ldap.php | 18 + lang/fr/template/install.php | 64 + lang/fr/template/menu.php | 47 + lang/fr/template/plugin_common.php | 26 + lang/it/js/js.php | 16 + .../database/check_tablespace/language.php | 11 + .../database/custom_query/language.php | 10 + .../database/custom_query_report/language.php | 11 + .../execute_sql_from_file/language.php | 5 + .../database/mysql_table_check/language.php | 4 + .../oracle_freespa_report/language.php | 12 + .../oracle_session_report/language.php | 11 + .../file/advanced_file_transfer/language.php | 24 + .../file/check_tail_status/language.php | 15 + lang/it/plugins/file/create/language.php | 13 + lang/it/plugins/file/ftp_upload/language.php | 20 + lang/it/plugins/file/read_file/language.php | 11 + lang/it/plugins/file/retention/language.php | 31 + lang/it/plugins/file/scp/language.php | 22 + lang/it/plugins/file/search/language.php | 23 + lang/it/plugins/file/size_check/language.php | 20 + lang/it/plugins/file/watch/language.php | 17 + .../general/custom_script/language.php | 16 + .../general/spreadsheet_to_db/language.php | 20 + .../general/telnet_custom_script/language.php | 19 + .../windows_remote_execution/language.php | 16 + .../plugins/notification/jabber/language.php | 22 + .../it/plugins/notification/mail/language.php | 32 + .../plugins/notification/sms_ftp/language.php | 18 + .../notification/tibco_rvd/language.php | 18 + .../notification/tivoli_postemsg/language.php | 18 + .../system/check_glance_status/language.php | 28 + lang/it/plugins/system/cpu_idle/language.php | 13 + .../system/file_system_check/language.php | 18 + lang/it/plugins/system/mem_free/language.php | 6 + lang/it/plugins/system/ping/language.php | 11 + .../plugins/system/service_check/language.php | 14 + .../solaris_metadevice_check/language.php | 12 + .../system/solaris_svc_check/language.php | 11 + .../solaris_zfs_scrub_check/language.php | 11 + .../system/solaris_zpool_check/language.php | 15 + .../www/check_uri_response_code/language.php | 12 + .../www/http_download_file/language.php | 13 + .../www/testgen4web_simpletest/language.php | 22 + .../www/webservice_soapui/language.php | 13 + .../plugins/www/webtest_selenium/language.php | 18 + .../plugins/www/webtest_slimdog/language.php | 15 + lang/it/template/action_msg.php | 105 + lang/it/template/common.php | 394 ++ .../template/configure_metadata_install.php | 60 + lang/it/template/configure_metadata_ldap.php | 19 + lang/it/template/install.php | 65 + lang/it/template/menu.php | 49 + lang/it/template/plugin_common.php | 26 + lib/Pear/Archive/Tar.php | 1830 +++++++ lib/Pear/Auth.php | 1365 ++++++ lib/Pear/Auth/Auth.php | 30 + lib/Pear/Auth/Container.php | 262 + lib/Pear/Auth/Container/CAS.php | 169 + lib/Pear/Auth/Container/LDAP.php | 766 +++ lib/Pear/Auth/Container/MDB2.php | 624 +++ lib/Pear/Config.php | 231 + lib/Pear/Config/Container.php | 776 +++ lib/Pear/Config/Container/Apache.php | 169 + lib/Pear/Config/Container/GenericConf.php | 139 + lib/Pear/Config/Container/IniCommented.php | 327 ++ lib/Pear/Config/Container/IniFile.php | 165 + lib/Pear/Config/Container/PHPArray.php | 251 + lib/Pear/Config/Container/PHPConstants.php | 199 + lib/Pear/Config/Container/XML.php | 249 + lib/Pear/Console/Getopt.php | 290 ++ lib/Pear/HTML/Common.php | 464 ++ lib/Pear/HTML/QuickForm.php | 2059 ++++++++ lib/Pear/HTML/QuickForm/Renderer.php | 158 + lib/Pear/HTML/QuickForm/Renderer/Array.php | 340 ++ .../HTML/QuickForm/Renderer/ArraySmarty.php | 402 ++ lib/Pear/HTML/QuickForm/Renderer/Default.php | 485 ++ .../HTML/QuickForm/Renderer/ITDynamic.php | 300 ++ lib/Pear/HTML/QuickForm/Renderer/ITStatic.php | 504 ++ lib/Pear/HTML/QuickForm/Renderer/Object.php | 461 ++ .../HTML/QuickForm/Renderer/ObjectFlexy.php | 291 ++ .../HTML/QuickForm/Renderer/QuickHtml.php | 213 + lib/Pear/HTML/QuickForm/Rule.php | 82 + lib/Pear/HTML/QuickForm/Rule/Callback.php | 124 + lib/Pear/HTML/QuickForm/Rule/Compare.php | 105 + lib/Pear/HTML/QuickForm/Rule/Email.php | 73 + lib/Pear/HTML/QuickForm/Rule/Range.php | 75 + lib/Pear/HTML/QuickForm/Rule/Regex.php | 101 + lib/Pear/HTML/QuickForm/Rule/Required.php | 63 + lib/Pear/HTML/QuickForm/RuleRegistry.php | 349 ++ lib/Pear/HTML/QuickForm/advcheckbox.php | 286 ++ lib/Pear/HTML/QuickForm/autocomplete.php | 258 + lib/Pear/HTML/QuickForm/button.php | 80 + lib/Pear/HTML/QuickForm/checkbox.php | 277 ++ lib/Pear/HTML/QuickForm/date.php | 528 ++ lib/Pear/HTML/QuickForm/element.php | 494 ++ lib/Pear/HTML/QuickForm/file.php | 358 ++ lib/Pear/HTML/QuickForm/group.php | 588 +++ lib/Pear/HTML/QuickForm/header.php | 74 + lib/Pear/HTML/QuickForm/hidden.php | 94 + lib/Pear/HTML/QuickForm/hiddenselect.php | 118 + lib/Pear/HTML/QuickForm/hierselect.php | 593 +++ lib/Pear/HTML/QuickForm/html.php | 77 + lib/Pear/HTML/QuickForm/image.php | 127 + lib/Pear/HTML/QuickForm/input.php | 209 + lib/Pear/HTML/QuickForm/link.php | 200 + lib/Pear/HTML/QuickForm/password.php | 115 + lib/Pear/HTML/QuickForm/radio.php | 251 + lib/Pear/HTML/QuickForm/reset.php | 79 + lib/Pear/HTML/QuickForm/select.php | 614 +++ lib/Pear/HTML/QuickForm/static.php | 201 + lib/Pear/HTML/QuickForm/submit.php | 89 + lib/Pear/HTML/QuickForm/text.php | 98 + lib/Pear/HTML/QuickForm/textarea.php | 229 + lib/Pear/HTML/QuickForm/xbutton.php | 153 + lib/Pear/HTML/Table.php | 1037 ++++ lib/Pear/HTML/Table/Storage.php | 869 ++++ lib/Pear/I18Nv2/CommonList.php | 242 + lib/Pear/I18Nv2/Country.php | 61 + lib/Pear/I18Nv2/Language.php | 61 + lib/Pear/I18Nv2/Language/aa.php | 193 + lib/Pear/I18Nv2/Language/af.php | 193 + lib/Pear/I18Nv2/Language/am.php | 193 + lib/Pear/I18Nv2/Language/ar.php | 193 + lib/Pear/I18Nv2/Language/as.php | 193 + lib/Pear/I18Nv2/Language/az.php | 193 + lib/Pear/I18Nv2/Language/be.php | 193 + lib/Pear/I18Nv2/Language/bg.php | 193 + lib/Pear/I18Nv2/Language/bn.php | 193 + lib/Pear/I18Nv2/Language/ca.php | 193 + lib/Pear/I18Nv2/Language/cs.php | 193 + lib/Pear/I18Nv2/Language/cy.php | 193 + lib/Pear/I18Nv2/Language/da.php | 193 + lib/Pear/I18Nv2/Language/de.php | 193 + lib/Pear/I18Nv2/Language/dv.php | 193 + lib/Pear/I18Nv2/Language/dz.php | 193 + lib/Pear/I18Nv2/Language/el.php | 193 + lib/Pear/I18Nv2/Language/en.php | 193 + lib/Pear/I18Nv2/Language/eo.php | 193 + lib/Pear/I18Nv2/Language/es.php | 193 + lib/Pear/I18Nv2/Language/et.php | 193 + lib/Pear/I18Nv2/Language/eu.php | 193 + lib/Pear/I18Nv2/Language/fa.php | 193 + lib/Pear/I18Nv2/Language/fi.php | 193 + lib/Pear/I18Nv2/Language/fo.php | 193 + lib/Pear/I18Nv2/Language/fr.php | 193 + lib/Pear/I18Nv2/Language/ga.php | 193 + lib/Pear/I18Nv2/Language/gl.php | 193 + lib/Pear/I18Nv2/Language/gu.php | 193 + lib/Pear/I18Nv2/Language/gv.php | 193 + lib/Pear/I18Nv2/Language/he.php | 193 + lib/Pear/I18Nv2/Language/hi.php | 193 + lib/Pear/I18Nv2/Language/hr.php | 193 + lib/Pear/I18Nv2/Language/hu.php | 193 + lib/Pear/I18Nv2/Language/hy.php | 193 + lib/Pear/I18Nv2/Language/id.php | 193 + lib/Pear/I18Nv2/Language/is.php | 193 + lib/Pear/I18Nv2/Language/it.php | 193 + lib/Pear/I18Nv2/Language/iu.php | 193 + lib/Pear/I18Nv2/Language/ja.php | 193 + lib/Pear/I18Nv2/Language/ka.php | 193 + lib/Pear/I18Nv2/Language/kk.php | 193 + lib/Pear/I18Nv2/Language/kl.php | 193 + lib/Pear/I18Nv2/Language/km.php | 193 + lib/Pear/I18Nv2/Language/kn.php | 193 + lib/Pear/I18Nv2/Language/ko.php | 193 + lib/Pear/I18Nv2/Language/kw.php | 193 + lib/Pear/I18Nv2/Language/ky.php | 193 + lib/Pear/I18Nv2/Language/lo.php | 193 + lib/Pear/I18Nv2/Language/lt.php | 193 + lib/Pear/I18Nv2/Language/lv.php | 193 + lib/Pear/I18Nv2/Language/mk.php | 193 + lib/Pear/I18Nv2/Language/ml.php | 193 + lib/Pear/I18Nv2/Language/mn.php | 193 + lib/Pear/I18Nv2/Language/mr.php | 193 + lib/Pear/I18Nv2/Language/ms.php | 193 + lib/Pear/I18Nv2/Language/mt.php | 193 + lib/Pear/I18Nv2/Language/nb.php | 193 + lib/Pear/I18Nv2/Language/nl.php | 193 + lib/Pear/I18Nv2/Language/nn.php | 193 + lib/Pear/I18Nv2/Language/om.php | 193 + lib/Pear/I18Nv2/Language/or.php | 193 + lib/Pear/I18Nv2/Language/pa.php | 193 + lib/Pear/I18Nv2/Language/pl.php | 193 + lib/Pear/I18Nv2/Language/ps.php | 193 + lib/Pear/I18Nv2/Language/pt.php | 193 + lib/Pear/I18Nv2/Language/ro.php | 193 + lib/Pear/I18Nv2/Language/ru.php | 193 + lib/Pear/I18Nv2/Language/sa.php | 193 + lib/Pear/I18Nv2/Language/sh.php | 193 + lib/Pear/I18Nv2/Language/sk.php | 193 + lib/Pear/I18Nv2/Language/sl.php | 193 + lib/Pear/I18Nv2/Language/so.php | 193 + lib/Pear/I18Nv2/Language/sq.php | 193 + lib/Pear/I18Nv2/Language/sr.php | 193 + lib/Pear/I18Nv2/Language/sv.php | 193 + lib/Pear/I18Nv2/Language/sw.php | 193 + lib/Pear/I18Nv2/Language/ta.php | 193 + lib/Pear/I18Nv2/Language/te.php | 193 + lib/Pear/I18Nv2/Language/th.php | 193 + lib/Pear/I18Nv2/Language/ti.php | 193 + lib/Pear/I18Nv2/Language/tr.php | 193 + lib/Pear/I18Nv2/Language/tt.php | 193 + lib/Pear/I18Nv2/Language/uk.php | 193 + lib/Pear/I18Nv2/Language/ur.php | 193 + lib/Pear/I18Nv2/Language/uz.php | 193 + lib/Pear/I18Nv2/Language/vi.php | 193 + lib/Pear/I18Nv2/Language/zh.php | 193 + lib/Pear/I18Nv2/Negotiator.php | 377 ++ lib/Pear/Image/GraphViz.php | 877 ++++ lib/Pear/MDB2.php | 4325 +++++++++++++++++ lib/Pear/MDB2/Date.php | 183 + lib/Pear/MDB2/Driver/Datatype/Common.php | 1824 +++++++ lib/Pear/MDB2/Driver/Datatype/ibase.php | 426 ++ lib/Pear/MDB2/Driver/Datatype/mssql.php | 436 ++ lib/Pear/MDB2/Driver/Datatype/mysql.php | 553 +++ lib/Pear/MDB2/Driver/Datatype/mysqli.php | 590 +++ lib/Pear/MDB2/Driver/Datatype/oci8.php | 482 ++ lib/Pear/MDB2/Driver/Datatype/pgsql.php | 555 +++ lib/Pear/MDB2/Driver/Datatype/sqlite.php | 409 ++ lib/Pear/MDB2/Driver/Function/Common.php | 293 ++ lib/Pear/MDB2/Driver/Function/ibase.php | 108 + lib/Pear/MDB2/Driver/Function/mssql.php | 193 + lib/Pear/MDB2/Driver/Function/mysql.php | 136 + lib/Pear/MDB2/Driver/Function/mysqli.php | 144 + lib/Pear/MDB2/Driver/Function/oci8.php | 187 + lib/Pear/MDB2/Driver/Function/pgsql.php | 115 + lib/Pear/MDB2/Driver/Function/sqlite.php | 162 + lib/Pear/MDB2/Driver/Manager/Common.php | 1010 ++++ lib/Pear/MDB2/Driver/Manager/ibase.php | 1121 +++++ lib/Pear/MDB2/Driver/Manager/mssql.php | 1129 +++++ lib/Pear/MDB2/Driver/Manager/mysql.php | 1418 ++++++ lib/Pear/MDB2/Driver/Manager/mysqli.php | 1418 ++++++ lib/Pear/MDB2/Driver/Manager/oci8.php | 1338 +++++ lib/Pear/MDB2/Driver/Manager/pgsql.php | 859 ++++ lib/Pear/MDB2/Driver/Manager/sqlite.php | 1356 ++++++ lib/Pear/MDB2/Driver/Native/Common.php | 61 + lib/Pear/MDB2/Driver/Native/ibase.php | 60 + lib/Pear/MDB2/Driver/Native/mssql.php | 60 + lib/Pear/MDB2/Driver/Native/mysql.php | 60 + lib/Pear/MDB2/Driver/Native/mysqli.php | 60 + lib/Pear/MDB2/Driver/Native/oci8.php | 60 + lib/Pear/MDB2/Driver/Native/pgsql.php | 88 + lib/Pear/MDB2/Driver/Native/sqlite.php | 60 + lib/Pear/MDB2/Driver/Reverse/Common.php | 513 ++ lib/Pear/MDB2/Driver/Reverse/ibase.php | 581 +++ lib/Pear/MDB2/Driver/Reverse/mssql.php | 653 +++ lib/Pear/MDB2/Driver/Reverse/mysql.php | 514 ++ lib/Pear/MDB2/Driver/Reverse/mysqli.php | 578 +++ lib/Pear/MDB2/Driver/Reverse/oci8.php | 621 +++ lib/Pear/MDB2/Driver/Reverse/pgsql.php | 530 ++ lib/Pear/MDB2/Driver/Reverse/sqlite.php | 585 +++ lib/Pear/MDB2/Driver/ibase.php | 1522 ++++++ lib/Pear/MDB2/Driver/mssql.php | 1122 +++++ lib/Pear/MDB2/Driver/mysql.php | 1685 +++++++ lib/Pear/MDB2/Driver/mysqli.php | 1841 +++++++ lib/Pear/MDB2/Driver/oci8.php | 1625 +++++++ lib/Pear/MDB2/Driver/pgsql.php | 1512 ++++++ lib/Pear/MDB2/Driver/sqlite.php | 1103 +++++ lib/Pear/MDB2/Extended.php | 721 +++ lib/Pear/MDB2/Iterator.php | 259 + lib/Pear/MDB2/LOB.php | 264 + lib/Pear/MDB2/Schema.php | 2767 +++++++++++ lib/Pear/MDB2/Schema/Parser.php | 819 ++++ lib/Pear/MDB2/Schema/Parser2.php | 624 +++ lib/Pear/MDB2/Schema/Reserved/ibase.php | 436 ++ lib/Pear/MDB2/Schema/Reserved/mssql.php | 258 + lib/Pear/MDB2/Schema/Reserved/mysql.php | 284 ++ lib/Pear/MDB2/Schema/Reserved/oci8.php | 171 + lib/Pear/MDB2/Schema/Reserved/pgsql.php | 147 + lib/Pear/MDB2/Schema/Validate.php | 922 ++++ lib/Pear/MDB2/Schema/Writer.php | 581 +++ lib/Pear/Net/Nmap.php | 271 ++ lib/Pear/Net/Nmap/Exception.php | 63 + lib/Pear/Net/Nmap/Host.php | 242 + lib/Pear/Net/Nmap/Parser.php | 163 + lib/Pear/Net/Nmap/Service.php | 111 + lib/Pear/OS/Guess.php | 344 ++ lib/Pear/PEAR.php | 1118 +++++ lib/Pear/PEAR/Exception.php | 397 ++ lib/Pear/System.php | 606 +++ lib/Pear/XML/Parser.php | 690 +++ lib/Pear/XML/Parser/Simple.php | 297 ++ lib/Pear/XML/RPC.php | 2077 ++++++++ lib/Pear/XML/RPC/Dump.php | 187 + lib/Pear/XML/RPC/Server.php | 685 +++ lib/authUtil.php | 372 ++ lib/cronUtil.php | 1076 ++++ lib/dbUtil.php | 3293 +++++++++++++ lib/htmlUtil.php | 939 ++++ lib/installUtil.php | 158 + lib/ioUtil.php | 232 + lib/langUtil.php | 99 + lib/ldapUtil.php | 187 + lib/logUtil.php | 134 + lib/notifyUtil.php | 139 + lib/sshUtil.php | 115 + packages/deb/crontab.php | 26 + packages/deb/init.inc.php | 22 + packages/deb/init.php | 102 + packages/deb/mkdeb.sh | 91 + packages/deb/ortro-apache2.conf | 6 + packages/deb/post_install.sh | 15 + packages/deb/post_remove.sh | 9 + plugins/database/check_tablespace/CHANGELOG | 11 + plugins/database/check_tablespace/LICENSE | 339 ++ .../database/check_tablespace/configure.php | 89 + plugins/database/check_tablespace/core.php | 156 + plugins/database/custom_query/CHANGELOG | 11 + plugins/database/custom_query/LICENSE | 339 ++ plugins/database/custom_query/configure.php | 82 + plugins/database/custom_query/core.php | 115 + .../database/custom_query_report/CHANGELOG | 11 + plugins/database/custom_query_report/LICENSE | 339 ++ .../custom_query_report/configure.php | 75 + plugins/database/custom_query_report/core.php | 161 + .../database/execute_sql_from_file/CHANGELOG | 6 + .../database/execute_sql_from_file/LICENSE | 339 ++ .../execute_sql_from_file/configure.php | 45 + .../database/execute_sql_from_file/core.php | 93 + plugins/database/mysql_table_check/CHANGELOG | 3 + plugins/database/mysql_table_check/LICENSE | 339 ++ .../database/mysql_table_check/configure.php | 47 + plugins/database/mysql_table_check/core.php | 120 + .../database/oracle_freespa_report/CHANGELOG | 11 + .../database/oracle_freespa_report/LICENSE | 339 ++ .../oracle_freespa_report/configure.php | 71 + .../database/oracle_freespa_report/core.php | 192 + .../database/oracle_session_report/CHANGELOG | 11 + .../database/oracle_session_report/LICENSE | 339 ++ .../oracle_session_report/configure.php | 65 + .../database/oracle_session_report/core.php | 165 + plugins/file/advanced_file_transfer/CHANGELOG | 3 + plugins/file/advanced_file_transfer/LICENSE | 339 ++ .../file/advanced_file_transfer/configure.php | 109 + .../configure_metadata.php | 35 + plugins/file/advanced_file_transfer/core.php | 175 + plugins/file/check_tail_status/CHANGELOG | 15 + plugins/file/check_tail_status/LICENSE | 339 ++ plugins/file/check_tail_status/configure.php | 62 + plugins/file/check_tail_status/core.php | 105 + plugins/file/check_tail_status/tail.sh | 31 + plugins/file/create/CHANGELOG | 11 + plugins/file/create/LICENSE | 339 ++ plugins/file/create/configure.php | 46 + plugins/file/create/core.php | 72 + plugins/file/ftp_upload/CHANGELOG | 15 + plugins/file/ftp_upload/LICENSE | 339 ++ plugins/file/ftp_upload/configure.php | 75 + plugins/file/ftp_upload/core.php | 155 + plugins/file/read_file/CHANGELOG | 11 + plugins/file/read_file/LICENSE | 339 ++ plugins/file/read_file/configure.php | 36 + plugins/file/read_file/core.php | 85 + plugins/file/retention/CHANGELOG | 20 + plugins/file/retention/LICENSE | 339 ++ plugins/file/retention/configure.php | 111 + plugins/file/retention/core.php | 137 + plugins/file/retention/script.sh | 135 + plugins/file/scp/CHANGELOG | 16 + plugins/file/scp/LICENSE | 339 ++ plugins/file/scp/configure.php | 98 + plugins/file/scp/configure_metadata.php | 35 + plugins/file/scp/core.php | 170 + plugins/file/scp/lib/Pear/File.php | 543 +++ plugins/file/scp/lib/Pear/File/CSV.php | 628 +++ plugins/file/scp/lib/Pear/File/Util.php | 482 ++ plugins/file/scp/lib/Pear/Net/OpenSSH.php | 331 ++ .../scp/lib/Pear/Net/OpenSSH/Exception.php | 63 + plugins/file/scp/lib/Pear/Net/OpenSSH/SSH.php | 127 + .../scp/lib/Pear/Net/OpenSSH/SSHCopyId.php | 123 + .../scp/lib/Pear/Net/OpenSSH/SSHKeygen.php | 119 + plugins/file/scp/lib/Pear/Net/OpenSSH/Scp.php | 142 + plugins/file/search/CHANGELOG | 19 + plugins/file/search/LICENSE | 339 ++ plugins/file/search/configure.php | 90 + plugins/file/search/core.php | 127 + plugins/file/search/script.sh | 47 + plugins/file/size_check/CHANGELOG | 15 + plugins/file/size_check/LICENSE | 339 ++ plugins/file/size_check/configure.php | 79 + plugins/file/size_check/core.php | 114 + plugins/file/size_check/script.sh | 41 + plugins/file/watch/CHANGELOG | 7 + plugins/file/watch/LICENSE | 339 ++ plugins/file/watch/configure.php | 71 + plugins/file/watch/core.php | 145 + plugins/file/watch/script.sh | 50 + plugins/general/custom_script/CHANGELOG | 15 + plugins/general/custom_script/LICENSE | 339 ++ plugins/general/custom_script/configure.php | 70 + plugins/general/custom_script/core.php | 105 + plugins/general/spreadsheet_to_db/CHANGELOG | 16 + plugins/general/spreadsheet_to_db/COPYRIGHT | 25 + plugins/general/spreadsheet_to_db/LICENSE | 339 ++ .../general/spreadsheet_to_db/configure.php | 86 + plugins/general/spreadsheet_to_db/core.php | 211 + .../spreadsheet_to_db/lib/Excel/oleread.inc | 271 ++ .../spreadsheet_to_db/lib/Excel/reader.php | 1082 +++++ .../general/telnet_custom_script/CHANGELOG | 3 + plugins/general/telnet_custom_script/LICENSE | 339 ++ .../telnet_custom_script/configure.php | 86 + plugins/general/telnet_custom_script/core.php | 135 + .../general/telnet_custom_script/telnet.sh | 34 + .../windows_remote_execution/CHANGELOG | 7 + .../general/windows_remote_execution/LICENSE | 339 ++ .../windows_remote_execution/configure.php | 53 + .../configure_metadata.php | 35 + .../general/windows_remote_execution/core.php | 98 + plugins/init.inc.php | 22 + plugins/notification/jabber/CHANGELOG | 14 + plugins/notification/jabber/COPYRIGHT | 24 + plugins/notification/jabber/LICENSE | 339 ++ plugins/notification/jabber/configure.php | 46 + .../jabber/configure_metadata.php | 53 + plugins/notification/jabber/core.php | 100 + .../notification/jabber/lib/class.jabber2.php | 962 ++++ plugins/notification/mail/CHANGELOG | 28 + plugins/notification/mail/COPYRIGHT | 43 + plugins/notification/mail/LICENSE | 339 ++ plugins/notification/mail/configure.php | 78 + .../notification/mail/configure_metadata.php | 102 + plugins/notification/mail/core.php | 154 + plugins/notification/mail/lib/Pear/Mail.php | 238 + .../mail/lib/Pear/Mail/RFC822.php | 923 ++++ .../notification/mail/lib/Pear/Mail/mail.php | 142 + .../notification/mail/lib/Pear/Mail/mime.php | 1095 +++++ .../mail/lib/Pear/Mail/mimeDecode.php | 849 ++++ .../mail/lib/Pear/Mail/mimePart.php | 439 ++ .../notification/mail/lib/Pear/Mail/null.php | 60 + .../mail/lib/Pear/Mail/sendmail.php | 155 + .../notification/mail/lib/Pear/Mail/smtp.php | 348 ++ .../notification/mail/lib/Pear/Net/SMTP.php | 1133 +++++ .../notification/mail/lib/Pear/Net/Socket.php | 592 +++ plugins/notification/sms_ftp/CHANGELOG | 16 + plugins/notification/sms_ftp/LICENSE | 339 ++ plugins/notification/sms_ftp/configure.php | 61 + .../sms_ftp/configure_metadata.php | 39 + plugins/notification/sms_ftp/core.php | 114 + plugins/notification/tibco_rvd/CHANGELOG | 11 + plugins/notification/tibco_rvd/LICENSE | 339 ++ plugins/notification/tibco_rvd/configure.php | 66 + .../tibco_rvd/configure_metadata.php | 27 + plugins/notification/tibco_rvd/core.php | 67 + .../notification/tivoli_postemsg/CHANGELOG | 11 + plugins/notification/tivoli_postemsg/LICENSE | 339 ++ .../tivoli_postemsg/configure.php | 64 + .../tivoli_postemsg/configure_metadata.php | 33 + plugins/notification/tivoli_postemsg/core.php | 57 + plugins/system/check_glance_status/CHANGELOG | 7 + plugins/system/check_glance_status/LICENSE | 339 ++ .../system/check_glance_status/configure.php | 114 + plugins/system/check_glance_status/core.php | 114 + plugins/system/check_glance_status/glance.sh | 94 + plugins/system/cpu_idle/CHANGELOG | 19 + plugins/system/cpu_idle/LICENSE | 339 ++ plugins/system/cpu_idle/configure.php | 66 + plugins/system/cpu_idle/core.php | 99 + plugins/system/cpu_idle/cpu-idle.ksh | 22 + plugins/system/file_system_check/CHANGELOG | 19 + plugins/system/file_system_check/LICENSE | 339 ++ .../system/file_system_check/configure.php | 48 + plugins/system/file_system_check/core.php | 143 + .../file_system_check/dynamic_parameters.php | 103 + plugins/system/file_system_check/script.sh | 26 + plugins/system/mem_free/CHANGELOG | 7 + plugins/system/mem_free/LICENSE | 339 ++ plugins/system/mem_free/configure.php | 63 + plugins/system/mem_free/core.php | 98 + plugins/system/mem_free/mem-free.ksh | 13 + plugins/system/ping/CHANGELOG | 19 + plugins/system/ping/COPYRIGHT | 33 + plugins/system/ping/LICENSE | 339 ++ plugins/system/ping/configure.php | 26 + plugins/system/ping/core.php | 83 + plugins/system/ping/lib/Pear/Net/Ping.php | 1226 +++++ plugins/system/service_check/CHANGELOG | 20 + plugins/system/service_check/LICENSE | 339 ++ plugins/system/service_check/configure.php | 63 + plugins/system/service_check/core.php | 113 + plugins/system/service_check/services.php | 37 + .../system/solaris_metadevice_check/CHANGELOG | 11 + .../system/solaris_metadevice_check/LICENSE | 339 ++ .../solaris_metadevice_check/configure.php | 48 + .../system/solaris_metadevice_check/core.php | 95 + .../metadevice-check.ksh | 10 + plugins/system/solaris_svc_check/CHANGELOG | 15 + plugins/system/solaris_svc_check/LICENSE | 339 ++ .../system/solaris_svc_check/configure.php | 42 + plugins/system/solaris_svc_check/core.php | 93 + .../system/solaris_svc_check/svc-check.ksh | 9 + .../system/solaris_zfs_scrub_check/CHANGELOG | 16 + .../system/solaris_zfs_scrub_check/LICENSE | 339 ++ .../solaris_zfs_scrub_check/configure.php | 42 + .../system/solaris_zfs_scrub_check/core.php | 93 + .../zfs-scrub-check.ksh | 7 + plugins/system/solaris_zpool_check/CHANGELOG | 15 + plugins/system/solaris_zpool_check/LICENSE | 339 ++ .../system/solaris_zpool_check/configure.php | 62 + plugins/system/solaris_zpool_check/core.php | 102 + .../solaris_zpool_check/zpool-check.ksh | 20 + plugins/www/check_uri_response_code/CHANGELOG | 19 + plugins/www/check_uri_response_code/COPYRIGHT | 30 + plugins/www/check_uri_response_code/LICENSE | 339 ++ .../www/check_uri_response_code/configure.php | 47 + plugins/www/check_uri_response_code/core.php | 137 + .../lib/Pear/HTTP/Request.php | 1484 ++++++ .../lib/Pear/HTTP/Request/Listener.php | 106 + .../lib/Pear/Net/Socket.php | 592 +++ .../lib/Pear/Net/URL.php | 485 ++ plugins/www/http_download_file/CHANGELOG | 11 + plugins/www/http_download_file/COPYRIGHT | 30 + plugins/www/http_download_file/LICENSE | 339 ++ plugins/www/http_download_file/configure.php | 61 + plugins/www/http_download_file/core.php | 105 + .../lib/Pear/HTTP/Request.php | 1484 ++++++ .../lib/Pear/HTTP/Request/Listener.php | 106 + .../lib/Pear/Net/Socket.php | 592 +++ .../http_download_file/lib/Pear/Net/URL.php | 485 ++ plugins/www/testgen4web_simpletest/CHANGELOG | 30 + plugins/www/testgen4web_simpletest/COPYRIGHT | 30 + plugins/www/testgen4web_simpletest/LICENSE | 339 ++ .../www/testgen4web_simpletest/configure.php | 97 + plugins/www/testgen4web_simpletest/core.php | 180 + .../lib/php-simpletest-translator/Config.php | 33 + .../Generator/Generator.php | 196 + .../SimpleTest/SimpleTestActions.inc.php | 185 + .../SimpleTest/SimpleTestGenerator.php | 227 + .../Generator/SimpleTest/Stub/MyWebTest.php | 54 + .../SimpleTest/Stub/simpletest.inc.php | 47 + .../PHPGenerator.php | 120 + .../Parser/ActionParser.php | 81 + .../Parser/XMLParser.php | 190 + .../php-simpletest-translator/Util/Logger.php | 115 + .../php-simpletest-translator/Util/Util.php | 99 + .../HELP_MY_TESTS_DONT_WORK_ANYMORE | 348 ++ .../lib/simpletest/LICENSE | 502 ++ .../lib/simpletest/README | 108 + .../lib/simpletest/Test.php | 62 + .../lib/simpletest/VERSION | 1 + .../lib/simpletest/authentication.php | 238 + .../lib/simpletest/autorun.php | 87 + .../lib/simpletest/browser.php | 1098 +++++ .../lib/simpletest/collector.php | 122 + .../lib/simpletest/compatibility.php | 173 + .../lib/simpletest/cookies.php | 380 ++ .../lib/simpletest/default_reporter.php | 133 + .../lib/simpletest/detached.php | 96 + .../lib/simpletest/dumper.php | 360 ++ .../lib/simpletest/eclipse.php | 307 ++ .../lib/simpletest/encoding.php | 552 +++ .../lib/simpletest/errors.php | 288 ++ .../lib/simpletest/exceptions.php | 198 + .../lib/simpletest/expectation.php | 895 ++++ .../simpletest/extensions/pear_test_case.php | 198 + .../extensions/phpunit_test_case.php | 96 + .../lib/simpletest/extensions/testdox.php | 42 + .../simpletest/extensions/testdox/test.php | 108 + .../lib/simpletest/form.php | 355 ++ .../lib/simpletest/frames.php | 596 +++ .../lib/simpletest/http.php | 624 +++ .../lib/simpletest/invoker.php | 139 + .../lib/simpletest/mock_objects.php | 1581 ++++++ .../lib/simpletest/page.php | 983 ++++ .../lib/simpletest/parser.php | 764 +++ .../lib/simpletest/reflection_php4.php | 136 + .../lib/simpletest/reflection_php5.php | 380 ++ .../lib/simpletest/remote.php | 117 + .../lib/simpletest/reporter.php | 447 ++ .../lib/simpletest/scorer.php | 863 ++++ .../lib/simpletest/selector.php | 137 + .../lib/simpletest/shell_tester.php | 333 ++ .../lib/simpletest/simpletest.php | 478 ++ .../lib/simpletest/socket.php | 216 + .../lib/simpletest/tag.php | 1418 ++++++ .../lib/simpletest/test_case.php | 708 +++ .../lib/simpletest/unit_tester.php | 420 ++ .../lib/simpletest/url.php | 528 ++ .../lib/simpletest/user_agent.php | 332 ++ .../lib/simpletest/web_tester.php | 1541 ++++++ .../lib/simpletest/xml.php | 647 +++ plugins/www/webservice_soapui/CHANGELOG | 6 + plugins/www/webservice_soapui/LICENSE | 339 ++ plugins/www/webservice_soapui/configure.php | 35 + .../webservice_soapui/configure_metadata.php | 31 + plugins/www/webservice_soapui/core.php | 73 + plugins/www/webtest_selenium/CHANGELOG | 11 + plugins/www/webtest_selenium/LICENSE | 339 ++ plugins/www/webtest_selenium/configure.php | 50 + .../webtest_selenium/configure_metadata.php | 35 + plugins/www/webtest_selenium/core.php | 110 + plugins/www/webtest_slimdog/CHANGELOG | 11 + plugins/www/webtest_slimdog/LICENSE | 339 ++ plugins/www/webtest_slimdog/configure.php | 43 + .../webtest_slimdog/configure_metadata.php | 35 + plugins/www/webtest_slimdog/core.php | 100 + plugins/www/webtest_slimdog/script.sh | 25 + tools/create_package.php | 256 + tools/ortro_sync.exclude | 4 + tools/ortro_sync.sh | 23 + upgrade/upgrade.php | 125 + www/css/jquery.jqplot.css | 135 + www/css/layout.css | 30 + www/css/layout_login.css | 30 + .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 260 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 0 -> 104 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 0 -> 125 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 0 -> 3762 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 0 -> 90 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 0 -> 167 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_228ef1_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ef8c08_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes www/css/no-theme/jquery-ui-1.7.2.custom.css | 406 ++ www/css/style.css | 378 ++ www/css/style_login.css | 70 + www/img/add.png | Bin 0 -> 1141 bytes www/img/archive.png | Bin 0 -> 1477 bytes www/img/arrowdown.png | Bin 0 -> 201 bytes www/img/arrowup.png | Bin 0 -> 201 bytes www/img/back.png | Bin 0 -> 1089 bytes www/img/copy.png | Bin 0 -> 1143 bytes www/img/date.png | Bin 0 -> 1114 bytes www/img/details.png | Bin 0 -> 1466 bytes www/img/edit.png | Bin 0 -> 1680 bytes www/img/eraser.png | Bin 0 -> 1534 bytes www/img/eraser_16x16.png | Bin 0 -> 806 bytes www/img/favicon.ico | Bin 0 -> 1150 bytes www/img/filesave.png | Bin 0 -> 838 bytes www/img/filter.png | Bin 0 -> 820 bytes www/img/forward.png | Bin 0 -> 1118 bytes www/img/groups.png | Bin 0 -> 1771 bytes www/img/header-back-white.png | Bin 0 -> 221 bytes www/img/header-back.png | Bin 0 -> 1868 bytes www/img/header-login-back.png | Bin 0 -> 5451 bytes www/img/identity.png | Bin 0 -> 1002 bytes www/img/immediate.png | Bin 0 -> 778 bytes www/img/info.png | Bin 0 -> 936 bytes www/img/kill.png | Bin 0 -> 1311 bytes www/img/lock.png | Bin 0 -> 1358 bytes www/img/locked.png | Bin 0 -> 854 bytes www/img/ortro-logo-small.png | Bin 0 -> 3175 bytes www/img/ortro-logo.png | Bin 0 -> 8487 bytes www/img/page-background.png | Bin 0 -> 196 bytes www/img/reload_page.png | Bin 0 -> 1815 bytes www/img/run.png | Bin 0 -> 1595 bytes www/img/running.png | Bin 0 -> 828 bytes www/img/success.png | Bin 0 -> 588 bytes www/img/toolbar-locked.png | Bin 0 -> 954 bytes www/img/toolbar-unlocked.png | Bin 0 -> 962 bytes www/img/transparent.png | Bin 0 -> 2548 bytes www/img/undo.png | Bin 0 -> 585 bytes www/img/unlock.png | Bin 0 -> 1406 bytes www/img/valid-css.png | Bin 0 -> 1298 bytes www/img/valid-xhtml10.png | Bin 0 -> 1363 bytes www/img/wait-for-exec.png | Bin 0 -> 987 bytes www/img/wait.png | Bin 0 -> 1049 bytes www/img/warning.png | Bin 0 -> 578 bytes www/index.php | 280 ++ www/init.inc.php | 22 + .../editor/css/behaviors/disablehandles.htc | 15 + .../editor/css/behaviors/showtableborders.htc | 36 + .../FCKeditor/editor/css/fck_editorarea.css | 110 + www/js/FCKeditor/editor/css/fck_internal.css | 199 + .../editor/css/fck_showtableborders_gecko.css | 49 + .../editor/css/images/block_address.png | Bin 0 -> 288 bytes .../editor/css/images/block_blockquote.png | Bin 0 -> 293 bytes .../FCKeditor/editor/css/images/block_div.png | Bin 0 -> 229 bytes .../FCKeditor/editor/css/images/block_h1.png | Bin 0 -> 218 bytes .../FCKeditor/editor/css/images/block_h2.png | Bin 0 -> 220 bytes .../FCKeditor/editor/css/images/block_h3.png | Bin 0 -> 219 bytes .../FCKeditor/editor/css/images/block_h4.png | Bin 0 -> 229 bytes .../FCKeditor/editor/css/images/block_h5.png | Bin 0 -> 236 bytes .../FCKeditor/editor/css/images/block_h6.png | Bin 0 -> 216 bytes .../FCKeditor/editor/css/images/block_p.png | Bin 0 -> 205 bytes .../FCKeditor/editor/css/images/block_pre.png | Bin 0 -> 223 bytes .../editor/css/images/fck_anchor.gif | Bin 0 -> 184 bytes .../editor/css/images/fck_flashlogo.gif | Bin 0 -> 599 bytes .../editor/css/images/fck_hiddenfield.gif | Bin 0 -> 105 bytes .../editor/css/images/fck_pagebreak.gif | Bin 0 -> 54 bytes .../editor/css/images/fck_plugin.gif | Bin 0 -> 1709 bytes .../dialog/common/fck_dialog_common.css | 85 + .../editor/dialog/common/fck_dialog_common.js | 347 ++ .../editor/dialog/common/images/locked.gif | Bin 0 -> 74 bytes .../editor/dialog/common/images/reset.gif | Bin 0 -> 104 bytes .../editor/dialog/common/images/unlocked.gif | Bin 0 -> 75 bytes www/js/FCKeditor/editor/dialog/fck_about.html | 161 + .../dialog/fck_about/logo_fckeditor.gif | Bin 0 -> 2044 bytes .../editor/dialog/fck_about/logo_fredck.gif | Bin 0 -> 920 bytes .../fck_about/sponsors/spellchecker_net.gif | Bin 0 -> 1447 bytes .../FCKeditor/editor/dialog/fck_anchor.html | 220 + .../FCKeditor/editor/dialog/fck_button.html | 104 + .../FCKeditor/editor/dialog/fck_checkbox.html | 104 + .../editor/dialog/fck_colorselector.html | 172 + www/js/FCKeditor/editor/dialog/fck_div.html | 396 ++ .../FCKeditor/editor/dialog/fck_docprops.html | 600 +++ .../fck_docprops/fck_document_preview.html | 113 + www/js/FCKeditor/editor/dialog/fck_flash.html | 152 + .../editor/dialog/fck_flash/fck_flash.js | 300 ++ .../dialog/fck_flash/fck_flash_preview.html | 50 + www/js/FCKeditor/editor/dialog/fck_form.html | 109 + .../editor/dialog/fck_hiddenfield.html | 115 + www/js/FCKeditor/editor/dialog/fck_image.html | 258 + .../editor/dialog/fck_image/fck_image.js | 512 ++ .../dialog/fck_image/fck_image_preview.html | 72 + www/js/FCKeditor/editor/dialog/fck_link.html | 295 ++ .../editor/dialog/fck_link/fck_link.js | 893 ++++ .../FCKeditor/editor/dialog/fck_listprop.html | 120 + www/js/FCKeditor/editor/dialog/fck_paste.html | 347 ++ .../editor/dialog/fck_radiobutton.html | 104 + .../FCKeditor/editor/dialog/fck_replace.html | 650 +++ .../FCKeditor/editor/dialog/fck_select.html | 180 + .../editor/dialog/fck_select/fck_select.js | 194 + .../FCKeditor/editor/dialog/fck_smiley.html | 111 + .../FCKeditor/editor/dialog/fck_source.html | 68 + .../editor/dialog/fck_specialchar.html | 121 + .../editor/dialog/fck_spellerpages.html | 70 + .../fck_spellerpages/spellerpages/blank.html | 0 .../spellerpages/controlWindow.js | 87 + .../spellerpages/controls.html | 153 + .../spellerpages/spellChecker.js | 461 ++ .../spellerpages/spellchecker.html | 71 + .../spellerpages/spellerStyle.css | 49 + .../spellerpages/wordWindow.js | 272 ++ www/js/FCKeditor/editor/dialog/fck_table.html | 440 ++ .../editor/dialog/fck_tablecell.html | 293 ++ .../FCKeditor/editor/dialog/fck_template.html | 242 + .../dialog/fck_template/images/template1.gif | Bin 0 -> 375 bytes .../dialog/fck_template/images/template2.gif | Bin 0 -> 333 bytes .../dialog/fck_template/images/template3.gif | Bin 0 -> 422 bytes .../FCKeditor/editor/dialog/fck_textarea.html | 94 + .../editor/dialog/fck_textfield.html | 136 + www/js/FCKeditor/editor/dtd/fck_dtd_test.html | 41 + .../FCKeditor/editor/dtd/fck_xhtml10strict.js | 116 + .../editor/dtd/fck_xhtml10transitional.js | 140 + www/js/FCKeditor/editor/fckdebug.html | 153 + www/js/FCKeditor/editor/fckdialog.html | 819 ++++ www/js/FCKeditor/editor/fckeditor.html | 317 ++ .../FCKeditor/editor/fckeditor.original.html | 425 ++ www/js/FCKeditor/editor/images/anchor.gif | Bin 0 -> 184 bytes www/js/FCKeditor/editor/images/arrow_ltr.gif | Bin 0 -> 49 bytes www/js/FCKeditor/editor/images/arrow_rtl.gif | Bin 0 -> 49 bytes .../editor/images/smiley/msn/angel_smile.gif | Bin 0 -> 445 bytes .../editor/images/smiley/msn/angry_smile.gif | Bin 0 -> 453 bytes .../editor/images/smiley/msn/broken_heart.gif | Bin 0 -> 423 bytes .../editor/images/smiley/msn/cake.gif | Bin 0 -> 453 bytes .../images/smiley/msn/confused_smile.gif | Bin 0 -> 322 bytes .../editor/images/smiley/msn/cry_smile.gif | Bin 0 -> 473 bytes .../editor/images/smiley/msn/devil_smile.gif | Bin 0 -> 444 bytes .../images/smiley/msn/embaressed_smile.gif | Bin 0 -> 1077 bytes .../editor/images/smiley/msn/envelope.gif | Bin 0 -> 1030 bytes .../editor/images/smiley/msn/heart.gif | Bin 0 -> 1012 bytes .../editor/images/smiley/msn/kiss.gif | Bin 0 -> 978 bytes .../editor/images/smiley/msn/lightbulb.gif | Bin 0 -> 303 bytes .../editor/images/smiley/msn/omg_smile.gif | Bin 0 -> 342 bytes .../images/smiley/msn/regular_smile.gif | Bin 0 -> 1036 bytes .../editor/images/smiley/msn/sad_smile.gif | Bin 0 -> 1039 bytes .../editor/images/smiley/msn/shades_smile.gif | Bin 0 -> 1059 bytes .../editor/images/smiley/msn/teeth_smile.gif | Bin 0 -> 1064 bytes .../editor/images/smiley/msn/thumbs_down.gif | Bin 0 -> 992 bytes .../editor/images/smiley/msn/thumbs_up.gif | Bin 0 -> 989 bytes .../editor/images/smiley/msn/tounge_smile.gif | Bin 0 -> 1055 bytes .../smiley/msn/whatchutalkingabout_smile.gif | Bin 0 -> 1034 bytes .../editor/images/smiley/msn/wink_smile.gif | Bin 0 -> 1041 bytes www/js/FCKeditor/editor/images/spacer.gif | Bin 0 -> 43 bytes www/js/FCKeditor/editor/js/fckadobeair.js | 176 + .../editor/js/fckeditorcode_gecko.js | 109 + .../FCKeditor/editor/js/fckeditorcode_ie.js | 110 + www/js/FCKeditor/editor/lang/af.js | 539 ++ www/js/FCKeditor/editor/lang/ar.js | 539 ++ www/js/FCKeditor/editor/lang/bg.js | 539 ++ www/js/FCKeditor/editor/lang/bn.js | 539 ++ www/js/FCKeditor/editor/lang/bs.js | 539 ++ www/js/FCKeditor/editor/lang/ca.js | 539 ++ www/js/FCKeditor/editor/lang/cs.js | 539 ++ www/js/FCKeditor/editor/lang/da.js | 539 ++ www/js/FCKeditor/editor/lang/de.js | 539 ++ www/js/FCKeditor/editor/lang/el.js | 539 ++ www/js/FCKeditor/editor/lang/en-au.js | 539 ++ www/js/FCKeditor/editor/lang/en-ca.js | 539 ++ www/js/FCKeditor/editor/lang/en-uk.js | 539 ++ www/js/FCKeditor/editor/lang/en.js | 539 ++ www/js/FCKeditor/editor/lang/eo.js | 539 ++ www/js/FCKeditor/editor/lang/es.js | 539 ++ www/js/FCKeditor/editor/lang/et.js | 539 ++ www/js/FCKeditor/editor/lang/eu.js | 540 ++ www/js/FCKeditor/editor/lang/fa.js | 539 ++ www/js/FCKeditor/editor/lang/fi.js | 539 ++ www/js/FCKeditor/editor/lang/fo.js | 539 ++ www/js/FCKeditor/editor/lang/fr-ca.js | 539 ++ www/js/FCKeditor/editor/lang/fr.js | 539 ++ www/js/FCKeditor/editor/lang/gl.js | 539 ++ www/js/FCKeditor/editor/lang/gu.js | 539 ++ www/js/FCKeditor/editor/lang/he.js | 539 ++ www/js/FCKeditor/editor/lang/hi.js | 539 ++ www/js/FCKeditor/editor/lang/hr.js | 539 ++ www/js/FCKeditor/editor/lang/hu.js | 539 ++ www/js/FCKeditor/editor/lang/is.js | 539 ++ www/js/FCKeditor/editor/lang/it.js | 539 ++ www/js/FCKeditor/editor/lang/ja.js | 539 ++ www/js/FCKeditor/editor/lang/km.js | 539 ++ www/js/FCKeditor/editor/lang/ko.js | 539 ++ www/js/FCKeditor/editor/lang/lt.js | 539 ++ www/js/FCKeditor/editor/lang/lv.js | 539 ++ www/js/FCKeditor/editor/lang/mn.js | 539 ++ www/js/FCKeditor/editor/lang/ms.js | 539 ++ www/js/FCKeditor/editor/lang/nb.js | 539 ++ www/js/FCKeditor/editor/lang/nl.js | 539 ++ www/js/FCKeditor/editor/lang/no.js | 539 ++ www/js/FCKeditor/editor/lang/pl.js | 539 ++ www/js/FCKeditor/editor/lang/pt-br.js | 539 ++ www/js/FCKeditor/editor/lang/pt.js | 539 ++ www/js/FCKeditor/editor/lang/ro.js | 539 ++ www/js/FCKeditor/editor/lang/ru.js | 539 ++ www/js/FCKeditor/editor/lang/sk.js | 539 ++ www/js/FCKeditor/editor/lang/sl.js | 539 ++ www/js/FCKeditor/editor/lang/sr-latn.js | 539 ++ www/js/FCKeditor/editor/lang/sr.js | 539 ++ www/js/FCKeditor/editor/lang/sv.js | 539 ++ www/js/FCKeditor/editor/lang/th.js | 539 ++ www/js/FCKeditor/editor/lang/tr.js | 539 ++ www/js/FCKeditor/editor/lang/uk.js | 539 ++ www/js/FCKeditor/editor/lang/vi.js | 539 ++ www/js/FCKeditor/editor/lang/zh-cn.js | 539 ++ www/js/FCKeditor/editor/lang/zh.js | 539 ++ .../editor/plugins/autogrow/fckplugin.js | 111 + .../editor/plugins/bbcode/fckplugin.js | 123 + .../plugins/dragresizetable/fckplugin.js | 529 ++ .../plugins/placeholder/fck_placeholder.html | 105 + .../editor/plugins/placeholder/fckplugin.js | 187 + .../editor/plugins/placeholder/lang/de.js | 27 + .../editor/plugins/placeholder/lang/en.js | 27 + .../editor/plugins/placeholder/lang/es.js | 27 + .../editor/plugins/placeholder/lang/fr.js | 27 + .../editor/plugins/placeholder/lang/it.js | 27 + .../editor/plugins/placeholder/lang/pl.js | 27 + .../plugins/placeholder/placeholder.gif | Bin 0 -> 96 bytes .../plugins/simplecommands/fckplugin.js | 29 + .../editor/plugins/tablecommands/fckplugin.js | 33 + .../editor/skins/silver/fck_dialog.css | 402 ++ .../editor/skins/silver/fck_dialog_ie6.js | 110 + .../editor/skins/silver/fck_editor.css | 473 ++ .../editor/skins/silver/fck_strip.gif | Bin 0 -> 5175 bytes .../skins/silver/images/dialog.sides.gif | Bin 0 -> 48 bytes .../skins/silver/images/dialog.sides.png | Bin 0 -> 198 bytes .../skins/silver/images/dialog.sides.rtl.png | Bin 0 -> 200 bytes .../editor/skins/silver/images/sprites.gif | Bin 0 -> 959 bytes .../editor/skins/silver/images/sprites.png | Bin 0 -> 3278 bytes .../silver/images/toolbar.arrowright.gif | Bin 0 -> 53 bytes .../silver/images/toolbar.buttonarrow.gif | Bin 0 -> 46 bytes .../skins/silver/images/toolbar.buttonbg.gif | Bin 0 -> 829 bytes .../skins/silver/images/toolbar.collapse.gif | Bin 0 -> 152 bytes .../skins/silver/images/toolbar.end.gif | Bin 0 -> 43 bytes .../skins/silver/images/toolbar.expand.gif | Bin 0 -> 152 bytes .../skins/silver/images/toolbar.separator.gif | Bin 0 -> 58 bytes .../skins/silver/images/toolbar.start.gif | Bin 0 -> 105 bytes www/js/FCKeditor/fckconfig.js | 325 ++ www/js/FCKeditor/fckeditor.js | 330 ++ www/js/FCKeditor/fckpackager.xml | 264 + www/js/FCKeditor/fckstyles.xml | 111 + www/js/FCKeditor/fcktemplates.xml | 103 + www/js/FCKeditor/license.txt | 1246 +++++ www/js/excanvas.min.js | 1 + www/js/jqplot/jqplot.barRenderer.min.js | 1 + .../jqplot.canvasAxisLabelRenderer.min.js | 1 + .../jqplot.canvasAxisTickRenderer.min.js | 1 + .../jqplot/jqplot.canvasTextRenderer.min.js | 1 + .../jqplot/jqplot.categoryAxisRenderer.min.js | 1 + www/js/jqplot/jqplot.cursor.min.js | 1 + www/js/jqplot/jqplot.dateAxisRenderer.min.js | 1 + www/js/jqplot/jqplot.dragable.min.js | 1 + www/js/jqplot/jqplot.highlighter.min.js | 1 + www/js/jqplot/jqplot.logAxisRenderer.min.js | 1 + www/js/jqplot/jqplot.ohlcRenderer.min.js | 1 + www/js/jqplot/jqplot.pieRenderer.min.js | 1 + www/js/jqplot/jqplot.pointLabels.min.js | 1 + www/js/jqplot/jqplot.trendline.min.js | 1 + www/js/jquery-1.3.2.min.js | 19 + www/js/jquery.jqplot.min.js | 1 + www/js/js.php | 33 + www/js/ortro.js | 566 +++ www/js/ortro_wf.js | 172 + www/js/overlibmws.js | 684 +++ www/js/ui.accordion.js | 477 ++ www/js/ui.core.js | 519 ++ www/js/ui.datepicker.ortro.js | 61 + www/js/ui.datepicker.patched.js | 1637 +++++++ www/js/ui.tabs.js | 685 +++ www/template/action/autodiscovery.php | 149 + www/template/action/calendars.php | 179 + www/template/action/cas_settings.php | 45 + www/template/action/db.php | 133 + www/template/action/filemanager.php | 114 + www/template/action/group.php | 132 + www/template/action/host.php | 161 + www/template/action/identity_management.php | 209 + www/template/action/import_export.php | 212 + www/template/action/jobs.php | 495 ++ www/template/action/ldap_settings.php | 47 + www/template/action/notify.php | 156 + www/template/action/plugin.php | 265 + www/template/action/plugin_notify.php | 262 + www/template/action/settings.php | 46 + www/template/action/system.php | 137 + www/template/action/user.php | 165 + www/template/action/workflows.php | 448 ++ www/template/add/autodiscovery.php | 122 + www/template/add/calendars.php | 122 + www/template/add/db.php | 131 + www/template/add/group.php | 100 + www/template/add/host.php | 128 + www/template/add/identity_management.php | 134 + www/template/add/jobs.php | 288 ++ www/template/add/notify.php | 178 + www/template/add/plugin.php | 70 + www/template/add/plugin_notify.php | 70 + www/template/add/system.php | 70 + www/template/add/user.php | 235 + www/template/add/workflows.php | 168 + www/template/body.php | 36 + www/template/default.php | 25 + www/template/details/db.php | 58 + .../details/display_archive_results.php | 172 + www/template/details/display_reports.php | 175 + www/template/details/jobs.php | 230 + www/template/details/notify.php | 124 + www/template/details/workflows.php | 226 + www/template/edit/calendars.php | 131 + www/template/edit/db.php | 116 + www/template/edit/filemanager.php | 224 + www/template/edit/group.php | 120 + www/template/edit/host.php | 96 + www/template/edit/identity_management.php | 157 + www/template/edit/jobs.php | 276 ++ www/template/edit/notify.php | 169 + www/template/edit/plugin.php | 108 + www/template/edit/plugin_notify.php | 111 + www/template/edit/system.php | 83 + www/template/edit/user.php | 173 + www/template/edit/userGroup.php | 137 + www/template/edit/workflows.php | 261 + www/template/footer.php | 52 + www/template/header.php | 156 + www/template/install/0.php | 64 + www/template/install/1.php | 53 + www/template/install/2.php | 189 + www/template/install/3.php | 212 + www/template/install/4.php | 169 + www/template/install/5.php | 138 + www/template/install/6.php | 208 + www/template/install/7.php | 72 + www/template/install/add_cron.sh | 30 + www/template/install/backup_cron.sh | 17 + www/template/install/footer.php | 38 + www/template/install/gpl.html | 218 + www/template/install/header.php | 63 + www/template/install/index.php | 124 + www/template/install/menu.php | 55 + www/template/install/ortro.schema.xml | 1404 ++++++ .../database_check_tablespace-1.2.2.tar.gz | Bin 0 -> 10078 bytes .../database_custom_query-1.2.2.tar.gz | Bin 0 -> 10034 bytes .../database_custom_query_report-1.2.2.tar.gz | Bin 0 -> 9861 bytes .../install/plugins/file_create-1.2.2.tar.gz | Bin 0 -> 8655 bytes .../plugins/file_ftp_upload-1.0.3.tar.gz | Bin 0 -> 10131 bytes .../plugins/file_read_file-1.0.2.tar.gz | Bin 0 -> 8692 bytes .../plugins/file_retention-1.2.4.tar.gz | Bin 0 -> 11392 bytes .../install/plugins/file_search-1.2.4.tar.gz | Bin 0 -> 10530 bytes .../plugins/file_size_check-1.2.3.tar.gz | Bin 0 -> 10124 bytes .../general_custom_script-1.2.3.tar.gz | Bin 0 -> 9463 bytes ...eral_windows_remote_execution-1.0.1.tar.gz | Bin 0 -> 9501 bytes .../plugins/notification_jabber-1.2.3.tar.gz | Bin 0 -> 18585 bytes .../plugins/notification_mail-1.2.6.tar.gz | Bin 0 -> 54910 bytes .../plugins/notification_sms_ftp-1.2.3.tar.gz | Bin 0 -> 9890 bytes .../notification_tibco_rvd-1.2.2.tar.gz | Bin 0 -> 8919 bytes .../notification_tivoli_postemsg-1.2.2.tar.gz | Bin 0 -> 9143 bytes .../plugins/system_cpu_idle-1.0.4.tar.gz | Bin 0 -> 9751 bytes .../system_file_system_check-1.2.4.tar.gz | Bin 0 -> 10846 bytes .../install/plugins/system_ping-1.2.4.tar.gz | Bin 0 -> 17003 bytes .../plugins/system_service_check-1.2.4.tar.gz | Bin 0 -> 9861 bytes .../www_check_uri_response_code-1.0.4.tar.gz | Bin 0 -> 29127 bytes .../www_testgen4web_simpletest-1.2.6.tar.gz | Bin 0 -> 135528 bytes www/template/login.php | 72 + www/template/menu.php | 119 + www/template/showMessage.php | 25 + www/template/view/autodiscovery.php | 91 + www/template/view/calendars.php | 208 + www/template/view/cas_settings.php | 93 + www/template/view/db.php | 215 + www/template/view/filemanager.php | 159 + www/template/view/group.php | 111 + www/template/view/host.php | 225 + www/template/view/identity_management.php | 207 + www/template/view/import_export.php | 158 + www/template/view/jobs.php | 495 ++ www/template/view/ldap_settings.php | 93 + www/template/view/notify.php | 316 ++ www/template/view/plugin.php | 157 + www/template/view/plugin_notify.php | 126 + www/template/view/settings.php | 92 + www/template/view/system.php | 163 + www/template/view/user.php | 181 + www/template/view/workflows.php | 321 ++ www/xmlrpc/index.php | 230 + www/xmlrpc/test_xml_rpc_cli.php | 72 + 1111 files changed, 237776 insertions(+), 2 deletions(-) create mode 100644 COPYRIGHT create mode 100644 LICENSE create mode 100644 bin/crontab.php create mode 100644 conf/configure_metadata_cas.php create mode 100644 conf/configure_metadata_install.php create mode 100644 conf/configure_metadata_ldap.php create mode 100644 conf/init.inc.php create mode 100644 conf/init.php create mode 100644 lang/en/js/js.php create mode 100644 lang/en/plugins/database/check_tablespace/language.php create mode 100644 lang/en/plugins/database/custom_query/language.php create mode 100644 lang/en/plugins/database/custom_query_report/language.php create mode 100644 lang/en/plugins/database/execute_sql_from_file/language.php create mode 100644 lang/en/plugins/database/mysql_table_check/language.php create mode 100644 lang/en/plugins/database/oracle_freespa_report/language.php create mode 100644 lang/en/plugins/database/oracle_session_report/language.php create mode 100644 lang/en/plugins/file/advanced_file_transfer/language.php create mode 100644 lang/en/plugins/file/check_tail_status/language.php create mode 100644 lang/en/plugins/file/create/language.php create mode 100644 lang/en/plugins/file/ftp_upload/language.php create mode 100644 lang/en/plugins/file/read_file/language.php create mode 100644 lang/en/plugins/file/retention/language.php create mode 100644 lang/en/plugins/file/scp/language.php create mode 100644 lang/en/plugins/file/search/language.php create mode 100644 lang/en/plugins/file/size_check/language.php create mode 100644 lang/en/plugins/file/watch/language.php create mode 100644 lang/en/plugins/general/custom_script/language.php create mode 100644 lang/en/plugins/general/spreadsheet_to_db/language.php create mode 100755 lang/en/plugins/general/telnet_custom_script/language.php create mode 100644 lang/en/plugins/general/windows_remote_execution/language.php create mode 100644 lang/en/plugins/notification/jabber/language.php create mode 100644 lang/en/plugins/notification/mail/language.php create mode 100644 lang/en/plugins/notification/sms_ftp/language.php create mode 100644 lang/en/plugins/notification/tibco_rvd/language.php create mode 100644 lang/en/plugins/notification/tivoli_postemsg/language.php create mode 100644 lang/en/plugins/system/check_glance_status/language.php create mode 100644 lang/en/plugins/system/cpu_idle/language.php create mode 100644 lang/en/plugins/system/file_system_check/language.php create mode 100644 lang/en/plugins/system/mem_free/language.php create mode 100644 lang/en/plugins/system/ping/language.php create mode 100644 lang/en/plugins/system/service_check/language.php create mode 100644 lang/en/plugins/system/solaris_metadevice_check/language.php create mode 100644 lang/en/plugins/system/solaris_svc_check/language.php create mode 100644 lang/en/plugins/system/solaris_zfs_scrub_check/language.php create mode 100644 lang/en/plugins/system/solaris_zpool_check/language.php create mode 100644 lang/en/plugins/www/check_uri_response_code/language.php create mode 100644 lang/en/plugins/www/http_download_file/language.php create mode 100644 lang/en/plugins/www/testgen4web_simpletest/language.php create mode 100644 lang/en/plugins/www/webservice_soapui/language.php create mode 100644 lang/en/plugins/www/webtest_selenium/language.php create mode 100644 lang/en/plugins/www/webtest_slimdog/language.php create mode 100644 lang/en/template/action_msg.php create mode 100644 lang/en/template/common.php create mode 100644 lang/en/template/configure_metadata_install.php create mode 100644 lang/en/template/configure_metadata_ldap.php create mode 100644 lang/en/template/install.php create mode 100644 lang/en/template/menu.php create mode 100644 lang/en/template/plugin_common.php create mode 100644 lang/fr/js/js.php create mode 100644 lang/fr/plugins/database/check_tablespace/language.php create mode 100644 lang/fr/plugins/database/custom_query/language.php create mode 100644 lang/fr/plugins/database/custom_query_report/language.php create mode 100644 lang/fr/plugins/database/execute_sql_from_file/language.php create mode 100644 lang/fr/plugins/database/mysql_table_check/language.php create mode 100644 lang/fr/plugins/database/oracle_freespa_report/language.php create mode 100644 lang/fr/plugins/database/oracle_session_report/language.php create mode 100644 lang/fr/plugins/file/check_tail_status/language.php create mode 100644 lang/fr/plugins/file/create/language.php create mode 100644 lang/fr/plugins/file/ftp_upload/language.php create mode 100644 lang/fr/plugins/file/read_file/language.php create mode 100644 lang/fr/plugins/file/retention/language.php create mode 100644 lang/fr/plugins/file/search/language.php create mode 100644 lang/fr/plugins/file/size_check/language.php create mode 100644 lang/fr/plugins/general/custom_script/language.php create mode 100644 lang/fr/plugins/general/spreadsheet_to_db/language.php create mode 100644 lang/fr/plugins/general/telnet_custom_script/language.php create mode 100644 lang/fr/plugins/general/windows_remote_execution/language.php create mode 100644 lang/fr/plugins/notification/jabber/language.php create mode 100644 lang/fr/plugins/notification/mail/language.php create mode 100644 lang/fr/plugins/notification/sms_ftp/language.php create mode 100644 lang/fr/plugins/notification/tibco_rvd/language.php create mode 100644 lang/fr/plugins/notification/tivoli_postemsg/language.php create mode 100644 lang/fr/plugins/system/check_glance_status/language.php create mode 100644 lang/fr/plugins/system/cpu_idle/language.php create mode 100644 lang/fr/plugins/system/file_system_check/language.php create mode 100644 lang/fr/plugins/system/mem_free/language.php create mode 100644 lang/fr/plugins/system/ping/language.php create mode 100644 lang/fr/plugins/system/service_check/language.php create mode 100644 lang/fr/plugins/system/solaris_metadevice_check/language.php create mode 100644 lang/fr/plugins/system/solaris_svc_check/language.php create mode 100644 lang/fr/plugins/system/solaris_zfs_scrub_check/language.php create mode 100644 lang/fr/plugins/system/solaris_zpool_check/language.php create mode 100644 lang/fr/plugins/www/check_uri_response_code/language.php create mode 100644 lang/fr/plugins/www/http_download_file/language.php create mode 100644 lang/fr/plugins/www/testgen4web_simpletest/language.php create mode 100644 lang/fr/plugins/www/webservice_soapui/language.php create mode 100644 lang/fr/plugins/www/webtest_selenium/language.php create mode 100644 lang/fr/plugins/www/webtest_slimdog/language.php create mode 100644 lang/fr/template/action_msg.php create mode 100644 lang/fr/template/common.php create mode 100644 lang/fr/template/configure_metadata_install.php create mode 100644 lang/fr/template/configure_metadata_ldap.php create mode 100644 lang/fr/template/install.php create mode 100644 lang/fr/template/menu.php create mode 100644 lang/fr/template/plugin_common.php create mode 100644 lang/it/js/js.php create mode 100644 lang/it/plugins/database/check_tablespace/language.php create mode 100644 lang/it/plugins/database/custom_query/language.php create mode 100644 lang/it/plugins/database/custom_query_report/language.php create mode 100644 lang/it/plugins/database/execute_sql_from_file/language.php create mode 100644 lang/it/plugins/database/mysql_table_check/language.php create mode 100644 lang/it/plugins/database/oracle_freespa_report/language.php create mode 100644 lang/it/plugins/database/oracle_session_report/language.php create mode 100644 lang/it/plugins/file/advanced_file_transfer/language.php create mode 100644 lang/it/plugins/file/check_tail_status/language.php create mode 100644 lang/it/plugins/file/create/language.php create mode 100644 lang/it/plugins/file/ftp_upload/language.php create mode 100644 lang/it/plugins/file/read_file/language.php create mode 100644 lang/it/plugins/file/retention/language.php create mode 100644 lang/it/plugins/file/scp/language.php create mode 100644 lang/it/plugins/file/search/language.php create mode 100644 lang/it/plugins/file/size_check/language.php create mode 100644 lang/it/plugins/file/watch/language.php create mode 100644 lang/it/plugins/general/custom_script/language.php create mode 100644 lang/it/plugins/general/spreadsheet_to_db/language.php create mode 100755 lang/it/plugins/general/telnet_custom_script/language.php create mode 100644 lang/it/plugins/general/windows_remote_execution/language.php create mode 100644 lang/it/plugins/notification/jabber/language.php create mode 100644 lang/it/plugins/notification/mail/language.php create mode 100644 lang/it/plugins/notification/sms_ftp/language.php create mode 100644 lang/it/plugins/notification/tibco_rvd/language.php create mode 100644 lang/it/plugins/notification/tivoli_postemsg/language.php create mode 100644 lang/it/plugins/system/check_glance_status/language.php create mode 100644 lang/it/plugins/system/cpu_idle/language.php create mode 100644 lang/it/plugins/system/file_system_check/language.php create mode 100644 lang/it/plugins/system/mem_free/language.php create mode 100644 lang/it/plugins/system/ping/language.php create mode 100644 lang/it/plugins/system/service_check/language.php create mode 100644 lang/it/plugins/system/solaris_metadevice_check/language.php create mode 100644 lang/it/plugins/system/solaris_svc_check/language.php create mode 100644 lang/it/plugins/system/solaris_zfs_scrub_check/language.php create mode 100644 lang/it/plugins/system/solaris_zpool_check/language.php create mode 100644 lang/it/plugins/www/check_uri_response_code/language.php create mode 100644 lang/it/plugins/www/http_download_file/language.php create mode 100644 lang/it/plugins/www/testgen4web_simpletest/language.php create mode 100644 lang/it/plugins/www/webservice_soapui/language.php create mode 100644 lang/it/plugins/www/webtest_selenium/language.php create mode 100644 lang/it/plugins/www/webtest_slimdog/language.php create mode 100644 lang/it/template/action_msg.php create mode 100644 lang/it/template/common.php create mode 100644 lang/it/template/configure_metadata_install.php create mode 100644 lang/it/template/configure_metadata_ldap.php create mode 100644 lang/it/template/install.php create mode 100644 lang/it/template/menu.php create mode 100644 lang/it/template/plugin_common.php create mode 100644 lib/Pear/Archive/Tar.php create mode 100644 lib/Pear/Auth.php create mode 100644 lib/Pear/Auth/Auth.php create mode 100644 lib/Pear/Auth/Container.php create mode 100644 lib/Pear/Auth/Container/CAS.php create mode 100644 lib/Pear/Auth/Container/LDAP.php create mode 100644 lib/Pear/Auth/Container/MDB2.php create mode 100644 lib/Pear/Config.php create mode 100644 lib/Pear/Config/Container.php create mode 100644 lib/Pear/Config/Container/Apache.php create mode 100644 lib/Pear/Config/Container/GenericConf.php create mode 100644 lib/Pear/Config/Container/IniCommented.php create mode 100644 lib/Pear/Config/Container/IniFile.php create mode 100644 lib/Pear/Config/Container/PHPArray.php create mode 100644 lib/Pear/Config/Container/PHPConstants.php create mode 100644 lib/Pear/Config/Container/XML.php create mode 100644 lib/Pear/Console/Getopt.php create mode 100644 lib/Pear/HTML/Common.php create mode 100644 lib/Pear/HTML/QuickForm.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/Array.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/ArraySmarty.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/Default.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/ITDynamic.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/ITStatic.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/Object.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/ObjectFlexy.php create mode 100644 lib/Pear/HTML/QuickForm/Renderer/QuickHtml.php create mode 100644 lib/Pear/HTML/QuickForm/Rule.php create mode 100644 lib/Pear/HTML/QuickForm/Rule/Callback.php create mode 100644 lib/Pear/HTML/QuickForm/Rule/Compare.php create mode 100644 lib/Pear/HTML/QuickForm/Rule/Email.php create mode 100644 lib/Pear/HTML/QuickForm/Rule/Range.php create mode 100644 lib/Pear/HTML/QuickForm/Rule/Regex.php create mode 100644 lib/Pear/HTML/QuickForm/Rule/Required.php create mode 100644 lib/Pear/HTML/QuickForm/RuleRegistry.php create mode 100644 lib/Pear/HTML/QuickForm/advcheckbox.php create mode 100644 lib/Pear/HTML/QuickForm/autocomplete.php create mode 100644 lib/Pear/HTML/QuickForm/button.php create mode 100644 lib/Pear/HTML/QuickForm/checkbox.php create mode 100644 lib/Pear/HTML/QuickForm/date.php create mode 100644 lib/Pear/HTML/QuickForm/element.php create mode 100644 lib/Pear/HTML/QuickForm/file.php create mode 100644 lib/Pear/HTML/QuickForm/group.php create mode 100644 lib/Pear/HTML/QuickForm/header.php create mode 100644 lib/Pear/HTML/QuickForm/hidden.php create mode 100644 lib/Pear/HTML/QuickForm/hiddenselect.php create mode 100644 lib/Pear/HTML/QuickForm/hierselect.php create mode 100644 lib/Pear/HTML/QuickForm/html.php create mode 100644 lib/Pear/HTML/QuickForm/image.php create mode 100644 lib/Pear/HTML/QuickForm/input.php create mode 100644 lib/Pear/HTML/QuickForm/link.php create mode 100644 lib/Pear/HTML/QuickForm/password.php create mode 100644 lib/Pear/HTML/QuickForm/radio.php create mode 100644 lib/Pear/HTML/QuickForm/reset.php create mode 100644 lib/Pear/HTML/QuickForm/select.php create mode 100644 lib/Pear/HTML/QuickForm/static.php create mode 100644 lib/Pear/HTML/QuickForm/submit.php create mode 100644 lib/Pear/HTML/QuickForm/text.php create mode 100644 lib/Pear/HTML/QuickForm/textarea.php create mode 100644 lib/Pear/HTML/QuickForm/xbutton.php create mode 100644 lib/Pear/HTML/Table.php create mode 100644 lib/Pear/HTML/Table/Storage.php create mode 100644 lib/Pear/I18Nv2/CommonList.php create mode 100644 lib/Pear/I18Nv2/Country.php create mode 100644 lib/Pear/I18Nv2/Language.php create mode 100644 lib/Pear/I18Nv2/Language/aa.php create mode 100644 lib/Pear/I18Nv2/Language/af.php create mode 100644 lib/Pear/I18Nv2/Language/am.php create mode 100644 lib/Pear/I18Nv2/Language/ar.php create mode 100644 lib/Pear/I18Nv2/Language/as.php create mode 100644 lib/Pear/I18Nv2/Language/az.php create mode 100644 lib/Pear/I18Nv2/Language/be.php create mode 100644 lib/Pear/I18Nv2/Language/bg.php create mode 100644 lib/Pear/I18Nv2/Language/bn.php create mode 100644 lib/Pear/I18Nv2/Language/ca.php create mode 100644 lib/Pear/I18Nv2/Language/cs.php create mode 100644 lib/Pear/I18Nv2/Language/cy.php create mode 100644 lib/Pear/I18Nv2/Language/da.php create mode 100644 lib/Pear/I18Nv2/Language/de.php create mode 100644 lib/Pear/I18Nv2/Language/dv.php create mode 100644 lib/Pear/I18Nv2/Language/dz.php create mode 100644 lib/Pear/I18Nv2/Language/el.php create mode 100644 lib/Pear/I18Nv2/Language/en.php create mode 100644 lib/Pear/I18Nv2/Language/eo.php create mode 100644 lib/Pear/I18Nv2/Language/es.php create mode 100644 lib/Pear/I18Nv2/Language/et.php create mode 100644 lib/Pear/I18Nv2/Language/eu.php create mode 100644 lib/Pear/I18Nv2/Language/fa.php create mode 100644 lib/Pear/I18Nv2/Language/fi.php create mode 100644 lib/Pear/I18Nv2/Language/fo.php create mode 100644 lib/Pear/I18Nv2/Language/fr.php create mode 100644 lib/Pear/I18Nv2/Language/ga.php create mode 100644 lib/Pear/I18Nv2/Language/gl.php create mode 100644 lib/Pear/I18Nv2/Language/gu.php create mode 100644 lib/Pear/I18Nv2/Language/gv.php create mode 100644 lib/Pear/I18Nv2/Language/he.php create mode 100644 lib/Pear/I18Nv2/Language/hi.php create mode 100644 lib/Pear/I18Nv2/Language/hr.php create mode 100644 lib/Pear/I18Nv2/Language/hu.php create mode 100644 lib/Pear/I18Nv2/Language/hy.php create mode 100644 lib/Pear/I18Nv2/Language/id.php create mode 100644 lib/Pear/I18Nv2/Language/is.php create mode 100644 lib/Pear/I18Nv2/Language/it.php create mode 100644 lib/Pear/I18Nv2/Language/iu.php create mode 100644 lib/Pear/I18Nv2/Language/ja.php create mode 100644 lib/Pear/I18Nv2/Language/ka.php create mode 100644 lib/Pear/I18Nv2/Language/kk.php create mode 100644 lib/Pear/I18Nv2/Language/kl.php create mode 100644 lib/Pear/I18Nv2/Language/km.php create mode 100644 lib/Pear/I18Nv2/Language/kn.php create mode 100644 lib/Pear/I18Nv2/Language/ko.php create mode 100644 lib/Pear/I18Nv2/Language/kw.php create mode 100644 lib/Pear/I18Nv2/Language/ky.php create mode 100644 lib/Pear/I18Nv2/Language/lo.php create mode 100644 lib/Pear/I18Nv2/Language/lt.php create mode 100644 lib/Pear/I18Nv2/Language/lv.php create mode 100644 lib/Pear/I18Nv2/Language/mk.php create mode 100644 lib/Pear/I18Nv2/Language/ml.php create mode 100644 lib/Pear/I18Nv2/Language/mn.php create mode 100644 lib/Pear/I18Nv2/Language/mr.php create mode 100644 lib/Pear/I18Nv2/Language/ms.php create mode 100644 lib/Pear/I18Nv2/Language/mt.php create mode 100644 lib/Pear/I18Nv2/Language/nb.php create mode 100644 lib/Pear/I18Nv2/Language/nl.php create mode 100644 lib/Pear/I18Nv2/Language/nn.php create mode 100644 lib/Pear/I18Nv2/Language/om.php create mode 100644 lib/Pear/I18Nv2/Language/or.php create mode 100644 lib/Pear/I18Nv2/Language/pa.php create mode 100644 lib/Pear/I18Nv2/Language/pl.php create mode 100644 lib/Pear/I18Nv2/Language/ps.php create mode 100644 lib/Pear/I18Nv2/Language/pt.php create mode 100644 lib/Pear/I18Nv2/Language/ro.php create mode 100644 lib/Pear/I18Nv2/Language/ru.php create mode 100644 lib/Pear/I18Nv2/Language/sa.php create mode 100644 lib/Pear/I18Nv2/Language/sh.php create mode 100644 lib/Pear/I18Nv2/Language/sk.php create mode 100644 lib/Pear/I18Nv2/Language/sl.php create mode 100644 lib/Pear/I18Nv2/Language/so.php create mode 100644 lib/Pear/I18Nv2/Language/sq.php create mode 100644 lib/Pear/I18Nv2/Language/sr.php create mode 100644 lib/Pear/I18Nv2/Language/sv.php create mode 100644 lib/Pear/I18Nv2/Language/sw.php create mode 100644 lib/Pear/I18Nv2/Language/ta.php create mode 100644 lib/Pear/I18Nv2/Language/te.php create mode 100644 lib/Pear/I18Nv2/Language/th.php create mode 100644 lib/Pear/I18Nv2/Language/ti.php create mode 100644 lib/Pear/I18Nv2/Language/tr.php create mode 100644 lib/Pear/I18Nv2/Language/tt.php create mode 100644 lib/Pear/I18Nv2/Language/uk.php create mode 100644 lib/Pear/I18Nv2/Language/ur.php create mode 100644 lib/Pear/I18Nv2/Language/uz.php create mode 100644 lib/Pear/I18Nv2/Language/vi.php create mode 100644 lib/Pear/I18Nv2/Language/zh.php create mode 100644 lib/Pear/I18Nv2/Negotiator.php create mode 100644 lib/Pear/Image/GraphViz.php create mode 100644 lib/Pear/MDB2.php create mode 100644 lib/Pear/MDB2/Date.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/Common.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/ibase.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/mssql.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/mysql.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/mysqli.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/oci8.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/pgsql.php create mode 100644 lib/Pear/MDB2/Driver/Datatype/sqlite.php create mode 100644 lib/Pear/MDB2/Driver/Function/Common.php create mode 100644 lib/Pear/MDB2/Driver/Function/ibase.php create mode 100644 lib/Pear/MDB2/Driver/Function/mssql.php create mode 100644 lib/Pear/MDB2/Driver/Function/mysql.php create mode 100644 lib/Pear/MDB2/Driver/Function/mysqli.php create mode 100644 lib/Pear/MDB2/Driver/Function/oci8.php create mode 100644 lib/Pear/MDB2/Driver/Function/pgsql.php create mode 100644 lib/Pear/MDB2/Driver/Function/sqlite.php create mode 100644 lib/Pear/MDB2/Driver/Manager/Common.php create mode 100644 lib/Pear/MDB2/Driver/Manager/ibase.php create mode 100644 lib/Pear/MDB2/Driver/Manager/mssql.php create mode 100644 lib/Pear/MDB2/Driver/Manager/mysql.php create mode 100644 lib/Pear/MDB2/Driver/Manager/mysqli.php create mode 100644 lib/Pear/MDB2/Driver/Manager/oci8.php create mode 100644 lib/Pear/MDB2/Driver/Manager/pgsql.php create mode 100644 lib/Pear/MDB2/Driver/Manager/sqlite.php create mode 100644 lib/Pear/MDB2/Driver/Native/Common.php create mode 100644 lib/Pear/MDB2/Driver/Native/ibase.php create mode 100644 lib/Pear/MDB2/Driver/Native/mssql.php create mode 100644 lib/Pear/MDB2/Driver/Native/mysql.php create mode 100644 lib/Pear/MDB2/Driver/Native/mysqli.php create mode 100644 lib/Pear/MDB2/Driver/Native/oci8.php create mode 100644 lib/Pear/MDB2/Driver/Native/pgsql.php create mode 100644 lib/Pear/MDB2/Driver/Native/sqlite.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/Common.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/ibase.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/mssql.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/mysql.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/mysqli.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/oci8.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/pgsql.php create mode 100644 lib/Pear/MDB2/Driver/Reverse/sqlite.php create mode 100644 lib/Pear/MDB2/Driver/ibase.php create mode 100644 lib/Pear/MDB2/Driver/mssql.php create mode 100644 lib/Pear/MDB2/Driver/mysql.php create mode 100644 lib/Pear/MDB2/Driver/mysqli.php create mode 100644 lib/Pear/MDB2/Driver/oci8.php create mode 100644 lib/Pear/MDB2/Driver/pgsql.php create mode 100644 lib/Pear/MDB2/Driver/sqlite.php create mode 100644 lib/Pear/MDB2/Extended.php create mode 100644 lib/Pear/MDB2/Iterator.php create mode 100644 lib/Pear/MDB2/LOB.php create mode 100644 lib/Pear/MDB2/Schema.php create mode 100644 lib/Pear/MDB2/Schema/Parser.php create mode 100644 lib/Pear/MDB2/Schema/Parser2.php create mode 100644 lib/Pear/MDB2/Schema/Reserved/ibase.php create mode 100644 lib/Pear/MDB2/Schema/Reserved/mssql.php create mode 100644 lib/Pear/MDB2/Schema/Reserved/mysql.php create mode 100644 lib/Pear/MDB2/Schema/Reserved/oci8.php create mode 100644 lib/Pear/MDB2/Schema/Reserved/pgsql.php create mode 100644 lib/Pear/MDB2/Schema/Validate.php create mode 100644 lib/Pear/MDB2/Schema/Writer.php create mode 100644 lib/Pear/Net/Nmap.php create mode 100644 lib/Pear/Net/Nmap/Exception.php create mode 100644 lib/Pear/Net/Nmap/Host.php create mode 100644 lib/Pear/Net/Nmap/Parser.php create mode 100644 lib/Pear/Net/Nmap/Service.php create mode 100644 lib/Pear/OS/Guess.php create mode 100644 lib/Pear/PEAR.php create mode 100644 lib/Pear/PEAR/Exception.php create mode 100644 lib/Pear/System.php create mode 100644 lib/Pear/XML/Parser.php create mode 100644 lib/Pear/XML/Parser/Simple.php create mode 100644 lib/Pear/XML/RPC.php create mode 100644 lib/Pear/XML/RPC/Dump.php create mode 100644 lib/Pear/XML/RPC/Server.php create mode 100644 lib/authUtil.php create mode 100644 lib/cronUtil.php create mode 100644 lib/dbUtil.php create mode 100644 lib/htmlUtil.php create mode 100644 lib/installUtil.php create mode 100644 lib/ioUtil.php create mode 100644 lib/langUtil.php create mode 100644 lib/ldapUtil.php create mode 100644 lib/logUtil.php create mode 100644 lib/notifyUtil.php create mode 100644 lib/sshUtil.php create mode 100644 packages/deb/crontab.php create mode 100644 packages/deb/init.inc.php create mode 100644 packages/deb/init.php create mode 100755 packages/deb/mkdeb.sh create mode 100644 packages/deb/ortro-apache2.conf create mode 100755 packages/deb/post_install.sh create mode 100755 packages/deb/post_remove.sh create mode 100644 plugins/database/check_tablespace/CHANGELOG create mode 100644 plugins/database/check_tablespace/LICENSE create mode 100644 plugins/database/check_tablespace/configure.php create mode 100644 plugins/database/check_tablespace/core.php create mode 100644 plugins/database/custom_query/CHANGELOG create mode 100644 plugins/database/custom_query/LICENSE create mode 100644 plugins/database/custom_query/configure.php create mode 100644 plugins/database/custom_query/core.php create mode 100644 plugins/database/custom_query_report/CHANGELOG create mode 100644 plugins/database/custom_query_report/LICENSE create mode 100644 plugins/database/custom_query_report/configure.php create mode 100644 plugins/database/custom_query_report/core.php create mode 100644 plugins/database/execute_sql_from_file/CHANGELOG create mode 100644 plugins/database/execute_sql_from_file/LICENSE create mode 100644 plugins/database/execute_sql_from_file/configure.php create mode 100644 plugins/database/execute_sql_from_file/core.php create mode 100755 plugins/database/mysql_table_check/CHANGELOG create mode 100755 plugins/database/mysql_table_check/LICENSE create mode 100755 plugins/database/mysql_table_check/configure.php create mode 100755 plugins/database/mysql_table_check/core.php create mode 100644 plugins/database/oracle_freespa_report/CHANGELOG create mode 100644 plugins/database/oracle_freespa_report/LICENSE create mode 100644 plugins/database/oracle_freespa_report/configure.php create mode 100644 plugins/database/oracle_freespa_report/core.php create mode 100644 plugins/database/oracle_session_report/CHANGELOG create mode 100644 plugins/database/oracle_session_report/LICENSE create mode 100644 plugins/database/oracle_session_report/configure.php create mode 100644 plugins/database/oracle_session_report/core.php create mode 100644 plugins/file/advanced_file_transfer/CHANGELOG create mode 100644 plugins/file/advanced_file_transfer/LICENSE create mode 100644 plugins/file/advanced_file_transfer/configure.php create mode 100644 plugins/file/advanced_file_transfer/configure_metadata.php create mode 100644 plugins/file/advanced_file_transfer/core.php create mode 100644 plugins/file/check_tail_status/CHANGELOG create mode 100644 plugins/file/check_tail_status/LICENSE create mode 100644 plugins/file/check_tail_status/configure.php create mode 100644 plugins/file/check_tail_status/core.php create mode 100644 plugins/file/check_tail_status/tail.sh create mode 100644 plugins/file/create/CHANGELOG create mode 100644 plugins/file/create/LICENSE create mode 100644 plugins/file/create/configure.php create mode 100644 plugins/file/create/core.php create mode 100644 plugins/file/ftp_upload/CHANGELOG create mode 100644 plugins/file/ftp_upload/LICENSE create mode 100644 plugins/file/ftp_upload/configure.php create mode 100644 plugins/file/ftp_upload/core.php create mode 100644 plugins/file/read_file/CHANGELOG create mode 100644 plugins/file/read_file/LICENSE create mode 100644 plugins/file/read_file/configure.php create mode 100644 plugins/file/read_file/core.php create mode 100644 plugins/file/retention/CHANGELOG create mode 100644 plugins/file/retention/LICENSE create mode 100644 plugins/file/retention/configure.php create mode 100644 plugins/file/retention/core.php create mode 100644 plugins/file/retention/script.sh create mode 100644 plugins/file/scp/CHANGELOG create mode 100644 plugins/file/scp/LICENSE create mode 100644 plugins/file/scp/configure.php create mode 100644 plugins/file/scp/configure_metadata.php create mode 100644 plugins/file/scp/core.php create mode 100644 plugins/file/scp/lib/Pear/File.php create mode 100644 plugins/file/scp/lib/Pear/File/CSV.php create mode 100644 plugins/file/scp/lib/Pear/File/Util.php create mode 100644 plugins/file/scp/lib/Pear/Net/OpenSSH.php create mode 100644 plugins/file/scp/lib/Pear/Net/OpenSSH/Exception.php create mode 100644 plugins/file/scp/lib/Pear/Net/OpenSSH/SSH.php create mode 100644 plugins/file/scp/lib/Pear/Net/OpenSSH/SSHCopyId.php create mode 100644 plugins/file/scp/lib/Pear/Net/OpenSSH/SSHKeygen.php create mode 100644 plugins/file/scp/lib/Pear/Net/OpenSSH/Scp.php create mode 100644 plugins/file/search/CHANGELOG create mode 100644 plugins/file/search/LICENSE create mode 100644 plugins/file/search/configure.php create mode 100644 plugins/file/search/core.php create mode 100644 plugins/file/search/script.sh create mode 100644 plugins/file/size_check/CHANGELOG create mode 100644 plugins/file/size_check/LICENSE create mode 100644 plugins/file/size_check/configure.php create mode 100644 plugins/file/size_check/core.php create mode 100644 plugins/file/size_check/script.sh create mode 100644 plugins/file/watch/CHANGELOG create mode 100644 plugins/file/watch/LICENSE create mode 100644 plugins/file/watch/configure.php create mode 100644 plugins/file/watch/core.php create mode 100644 plugins/file/watch/script.sh create mode 100644 plugins/general/custom_script/CHANGELOG create mode 100644 plugins/general/custom_script/LICENSE create mode 100644 plugins/general/custom_script/configure.php create mode 100644 plugins/general/custom_script/core.php create mode 100644 plugins/general/spreadsheet_to_db/CHANGELOG create mode 100644 plugins/general/spreadsheet_to_db/COPYRIGHT create mode 100644 plugins/general/spreadsheet_to_db/LICENSE create mode 100644 plugins/general/spreadsheet_to_db/configure.php create mode 100644 plugins/general/spreadsheet_to_db/core.php create mode 100644 plugins/general/spreadsheet_to_db/lib/Excel/oleread.inc create mode 100644 plugins/general/spreadsheet_to_db/lib/Excel/reader.php create mode 100755 plugins/general/telnet_custom_script/CHANGELOG create mode 100755 plugins/general/telnet_custom_script/LICENSE create mode 100755 plugins/general/telnet_custom_script/configure.php create mode 100755 plugins/general/telnet_custom_script/core.php create mode 100755 plugins/general/telnet_custom_script/telnet.sh create mode 100644 plugins/general/windows_remote_execution/CHANGELOG create mode 100644 plugins/general/windows_remote_execution/LICENSE create mode 100644 plugins/general/windows_remote_execution/configure.php create mode 100644 plugins/general/windows_remote_execution/configure_metadata.php create mode 100644 plugins/general/windows_remote_execution/core.php create mode 100644 plugins/init.inc.php create mode 100644 plugins/notification/jabber/CHANGELOG create mode 100644 plugins/notification/jabber/COPYRIGHT create mode 100644 plugins/notification/jabber/LICENSE create mode 100644 plugins/notification/jabber/configure.php create mode 100644 plugins/notification/jabber/configure_metadata.php create mode 100644 plugins/notification/jabber/core.php create mode 100644 plugins/notification/jabber/lib/class.jabber2.php create mode 100644 plugins/notification/mail/CHANGELOG create mode 100644 plugins/notification/mail/COPYRIGHT create mode 100644 plugins/notification/mail/LICENSE create mode 100644 plugins/notification/mail/configure.php create mode 100644 plugins/notification/mail/configure_metadata.php create mode 100644 plugins/notification/mail/core.php create mode 100644 plugins/notification/mail/lib/Pear/Mail.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/RFC822.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/mail.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/mime.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/mimeDecode.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/mimePart.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/null.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/sendmail.php create mode 100644 plugins/notification/mail/lib/Pear/Mail/smtp.php create mode 100644 plugins/notification/mail/lib/Pear/Net/SMTP.php create mode 100644 plugins/notification/mail/lib/Pear/Net/Socket.php create mode 100644 plugins/notification/sms_ftp/CHANGELOG create mode 100644 plugins/notification/sms_ftp/LICENSE create mode 100644 plugins/notification/sms_ftp/configure.php create mode 100644 plugins/notification/sms_ftp/configure_metadata.php create mode 100644 plugins/notification/sms_ftp/core.php create mode 100644 plugins/notification/tibco_rvd/CHANGELOG create mode 100644 plugins/notification/tibco_rvd/LICENSE create mode 100644 plugins/notification/tibco_rvd/configure.php create mode 100644 plugins/notification/tibco_rvd/configure_metadata.php create mode 100644 plugins/notification/tibco_rvd/core.php create mode 100644 plugins/notification/tivoli_postemsg/CHANGELOG create mode 100644 plugins/notification/tivoli_postemsg/LICENSE create mode 100644 plugins/notification/tivoli_postemsg/configure.php create mode 100644 plugins/notification/tivoli_postemsg/configure_metadata.php create mode 100644 plugins/notification/tivoli_postemsg/core.php create mode 100644 plugins/system/check_glance_status/CHANGELOG create mode 100644 plugins/system/check_glance_status/LICENSE create mode 100644 plugins/system/check_glance_status/configure.php create mode 100644 plugins/system/check_glance_status/core.php create mode 100755 plugins/system/check_glance_status/glance.sh create mode 100644 plugins/system/cpu_idle/CHANGELOG create mode 100644 plugins/system/cpu_idle/LICENSE create mode 100644 plugins/system/cpu_idle/configure.php create mode 100644 plugins/system/cpu_idle/core.php create mode 100644 plugins/system/cpu_idle/cpu-idle.ksh create mode 100644 plugins/system/file_system_check/CHANGELOG create mode 100644 plugins/system/file_system_check/LICENSE create mode 100644 plugins/system/file_system_check/configure.php create mode 100644 plugins/system/file_system_check/core.php create mode 100644 plugins/system/file_system_check/dynamic_parameters.php create mode 100644 plugins/system/file_system_check/script.sh create mode 100644 plugins/system/mem_free/CHANGELOG create mode 100644 plugins/system/mem_free/LICENSE create mode 100644 plugins/system/mem_free/configure.php create mode 100644 plugins/system/mem_free/core.php create mode 100644 plugins/system/mem_free/mem-free.ksh create mode 100644 plugins/system/ping/CHANGELOG create mode 100644 plugins/system/ping/COPYRIGHT create mode 100644 plugins/system/ping/LICENSE create mode 100644 plugins/system/ping/configure.php create mode 100644 plugins/system/ping/core.php create mode 100644 plugins/system/ping/lib/Pear/Net/Ping.php create mode 100644 plugins/system/service_check/CHANGELOG create mode 100644 plugins/system/service_check/LICENSE create mode 100644 plugins/system/service_check/configure.php create mode 100644 plugins/system/service_check/core.php create mode 100644 plugins/system/service_check/services.php create mode 100644 plugins/system/solaris_metadevice_check/CHANGELOG create mode 100644 plugins/system/solaris_metadevice_check/LICENSE create mode 100644 plugins/system/solaris_metadevice_check/configure.php create mode 100644 plugins/system/solaris_metadevice_check/core.php create mode 100644 plugins/system/solaris_metadevice_check/metadevice-check.ksh create mode 100644 plugins/system/solaris_svc_check/CHANGELOG create mode 100644 plugins/system/solaris_svc_check/LICENSE create mode 100644 plugins/system/solaris_svc_check/configure.php create mode 100644 plugins/system/solaris_svc_check/core.php create mode 100644 plugins/system/solaris_svc_check/svc-check.ksh create mode 100644 plugins/system/solaris_zfs_scrub_check/CHANGELOG create mode 100644 plugins/system/solaris_zfs_scrub_check/LICENSE create mode 100644 plugins/system/solaris_zfs_scrub_check/configure.php create mode 100644 plugins/system/solaris_zfs_scrub_check/core.php create mode 100644 plugins/system/solaris_zfs_scrub_check/zfs-scrub-check.ksh create mode 100644 plugins/system/solaris_zpool_check/CHANGELOG create mode 100644 plugins/system/solaris_zpool_check/LICENSE create mode 100644 plugins/system/solaris_zpool_check/configure.php create mode 100644 plugins/system/solaris_zpool_check/core.php create mode 100644 plugins/system/solaris_zpool_check/zpool-check.ksh create mode 100644 plugins/www/check_uri_response_code/CHANGELOG create mode 100644 plugins/www/check_uri_response_code/COPYRIGHT create mode 100644 plugins/www/check_uri_response_code/LICENSE create mode 100644 plugins/www/check_uri_response_code/configure.php create mode 100644 plugins/www/check_uri_response_code/core.php create mode 100644 plugins/www/check_uri_response_code/lib/Pear/HTTP/Request.php create mode 100644 plugins/www/check_uri_response_code/lib/Pear/HTTP/Request/Listener.php create mode 100644 plugins/www/check_uri_response_code/lib/Pear/Net/Socket.php create mode 100644 plugins/www/check_uri_response_code/lib/Pear/Net/URL.php create mode 100644 plugins/www/http_download_file/CHANGELOG create mode 100644 plugins/www/http_download_file/COPYRIGHT create mode 100644 plugins/www/http_download_file/LICENSE create mode 100644 plugins/www/http_download_file/configure.php create mode 100644 plugins/www/http_download_file/core.php create mode 100644 plugins/www/http_download_file/lib/Pear/HTTP/Request.php create mode 100644 plugins/www/http_download_file/lib/Pear/HTTP/Request/Listener.php create mode 100644 plugins/www/http_download_file/lib/Pear/Net/Socket.php create mode 100644 plugins/www/http_download_file/lib/Pear/Net/URL.php create mode 100644 plugins/www/testgen4web_simpletest/CHANGELOG create mode 100644 plugins/www/testgen4web_simpletest/COPYRIGHT create mode 100644 plugins/www/testgen4web_simpletest/LICENSE create mode 100644 plugins/www/testgen4web_simpletest/configure.php create mode 100644 plugins/www/testgen4web_simpletest/core.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Config.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/Generator.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestActions.inc.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestGenerator.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/MyWebTest.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/simpletest.inc.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/PHPGenerator.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/ActionParser.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/XMLParser.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Logger.php create mode 100644 plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Util.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/LICENSE create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/README create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/Test.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/VERSION create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/authentication.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/autorun.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/browser.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/collector.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/compatibility.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/cookies.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/default_reporter.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/detached.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/dumper.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/eclipse.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/encoding.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/errors.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/exceptions.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/expectation.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/extensions/pear_test_case.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/extensions/phpunit_test_case.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox/test.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/form.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/frames.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/http.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/invoker.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/mock_objects.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/page.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/parser.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php4.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php5.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/remote.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/reporter.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/scorer.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/selector.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/shell_tester.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/simpletest.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/socket.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/tag.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/test_case.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/unit_tester.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/url.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/user_agent.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/web_tester.php create mode 100644 plugins/www/testgen4web_simpletest/lib/simpletest/xml.php create mode 100644 plugins/www/webservice_soapui/CHANGELOG create mode 100644 plugins/www/webservice_soapui/LICENSE create mode 100644 plugins/www/webservice_soapui/configure.php create mode 100644 plugins/www/webservice_soapui/configure_metadata.php create mode 100644 plugins/www/webservice_soapui/core.php create mode 100644 plugins/www/webtest_selenium/CHANGELOG create mode 100644 plugins/www/webtest_selenium/LICENSE create mode 100644 plugins/www/webtest_selenium/configure.php create mode 100644 plugins/www/webtest_selenium/configure_metadata.php create mode 100644 plugins/www/webtest_selenium/core.php create mode 100644 plugins/www/webtest_slimdog/CHANGELOG create mode 100644 plugins/www/webtest_slimdog/LICENSE create mode 100644 plugins/www/webtest_slimdog/configure.php create mode 100644 plugins/www/webtest_slimdog/configure_metadata.php create mode 100644 plugins/www/webtest_slimdog/core.php create mode 100755 plugins/www/webtest_slimdog/script.sh create mode 100644 tools/create_package.php create mode 100644 tools/ortro_sync.exclude create mode 100755 tools/ortro_sync.sh create mode 100644 upgrade/upgrade.php create mode 100644 www/css/jquery.jqplot.css create mode 100644 www/css/layout.css create mode 100644 www/css/layout_login.css create mode 100644 www/css/no-theme/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100644 www/css/no-theme/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 www/css/no-theme/images/ui-bg_flat_10_000000_40x100.png create mode 100644 www/css/no-theme/images/ui-bg_glass_100_f6f6f6_1x400.png create mode 100644 www/css/no-theme/images/ui-bg_glass_100_fdf5ce_1x400.png create mode 100644 www/css/no-theme/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 www/css/no-theme/images/ui-bg_gloss-wave_35_f6a828_500x100.png create mode 100644 www/css/no-theme/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100644 www/css/no-theme/images/ui-bg_highlight-soft_75_ffe45c_1x100.png create mode 100644 www/css/no-theme/images/ui-icons_222222_256x240.png create mode 100644 www/css/no-theme/images/ui-icons_228ef1_256x240.png create mode 100644 www/css/no-theme/images/ui-icons_ef8c08_256x240.png create mode 100644 www/css/no-theme/images/ui-icons_ffd27a_256x240.png create mode 100644 www/css/no-theme/images/ui-icons_ffffff_256x240.png create mode 100644 www/css/no-theme/jquery-ui-1.7.2.custom.css create mode 100644 www/css/style.css create mode 100644 www/css/style_login.css create mode 100644 www/img/add.png create mode 100644 www/img/archive.png create mode 100644 www/img/arrowdown.png create mode 100644 www/img/arrowup.png create mode 100755 www/img/back.png create mode 100644 www/img/copy.png create mode 100755 www/img/date.png create mode 100644 www/img/details.png create mode 100644 www/img/edit.png create mode 100644 www/img/eraser.png create mode 100644 www/img/eraser_16x16.png create mode 100644 www/img/favicon.ico create mode 100644 www/img/filesave.png create mode 100644 www/img/filter.png create mode 100755 www/img/forward.png create mode 100644 www/img/groups.png create mode 100644 www/img/header-back-white.png create mode 100644 www/img/header-back.png create mode 100644 www/img/header-login-back.png create mode 100755 www/img/identity.png create mode 100755 www/img/immediate.png create mode 100644 www/img/info.png create mode 100755 www/img/kill.png create mode 100644 www/img/lock.png create mode 100644 www/img/locked.png create mode 100644 www/img/ortro-logo-small.png create mode 100644 www/img/ortro-logo.png create mode 100644 www/img/page-background.png create mode 100644 www/img/reload_page.png create mode 100644 www/img/run.png create mode 100644 www/img/running.png create mode 100644 www/img/success.png create mode 100755 www/img/toolbar-locked.png create mode 100755 www/img/toolbar-unlocked.png create mode 100644 www/img/transparent.png create mode 100644 www/img/undo.png create mode 100644 www/img/unlock.png create mode 100644 www/img/valid-css.png create mode 100644 www/img/valid-xhtml10.png create mode 100755 www/img/wait-for-exec.png create mode 100644 www/img/wait.png create mode 100644 www/img/warning.png create mode 100644 www/index.php create mode 100644 www/init.inc.php create mode 100644 www/js/FCKeditor/editor/css/behaviors/disablehandles.htc create mode 100644 www/js/FCKeditor/editor/css/behaviors/showtableborders.htc create mode 100644 www/js/FCKeditor/editor/css/fck_editorarea.css create mode 100644 www/js/FCKeditor/editor/css/fck_internal.css create mode 100644 www/js/FCKeditor/editor/css/fck_showtableborders_gecko.css create mode 100644 www/js/FCKeditor/editor/css/images/block_address.png create mode 100644 www/js/FCKeditor/editor/css/images/block_blockquote.png create mode 100644 www/js/FCKeditor/editor/css/images/block_div.png create mode 100644 www/js/FCKeditor/editor/css/images/block_h1.png create mode 100644 www/js/FCKeditor/editor/css/images/block_h2.png create mode 100644 www/js/FCKeditor/editor/css/images/block_h3.png create mode 100644 www/js/FCKeditor/editor/css/images/block_h4.png create mode 100644 www/js/FCKeditor/editor/css/images/block_h5.png create mode 100644 www/js/FCKeditor/editor/css/images/block_h6.png create mode 100644 www/js/FCKeditor/editor/css/images/block_p.png create mode 100644 www/js/FCKeditor/editor/css/images/block_pre.png create mode 100644 www/js/FCKeditor/editor/css/images/fck_anchor.gif create mode 100644 www/js/FCKeditor/editor/css/images/fck_flashlogo.gif create mode 100644 www/js/FCKeditor/editor/css/images/fck_hiddenfield.gif create mode 100644 www/js/FCKeditor/editor/css/images/fck_pagebreak.gif create mode 100644 www/js/FCKeditor/editor/css/images/fck_plugin.gif create mode 100644 www/js/FCKeditor/editor/dialog/common/fck_dialog_common.css create mode 100644 www/js/FCKeditor/editor/dialog/common/fck_dialog_common.js create mode 100644 www/js/FCKeditor/editor/dialog/common/images/locked.gif create mode 100644 www/js/FCKeditor/editor/dialog/common/images/reset.gif create mode 100644 www/js/FCKeditor/editor/dialog/common/images/unlocked.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_about.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_about/logo_fckeditor.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_about/logo_fredck.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_about/sponsors/spellchecker_net.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_anchor.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_button.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_checkbox.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_colorselector.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_div.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_docprops.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_docprops/fck_document_preview.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_flash.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_flash/fck_flash.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_flash/fck_flash_preview.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_form.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_hiddenfield.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_image.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_image/fck_image.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_image/fck_image_preview.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_link.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_link/fck_link.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_listprop.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_paste.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_radiobutton.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_replace.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_select.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_select/fck_select.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_smiley.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_source.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_specialchar.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css create mode 100644 www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js create mode 100644 www/js/FCKeditor/editor/dialog/fck_table.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_tablecell.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_template.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_template/images/template1.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_template/images/template2.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_template/images/template3.gif create mode 100644 www/js/FCKeditor/editor/dialog/fck_textarea.html create mode 100644 www/js/FCKeditor/editor/dialog/fck_textfield.html create mode 100644 www/js/FCKeditor/editor/dtd/fck_dtd_test.html create mode 100644 www/js/FCKeditor/editor/dtd/fck_xhtml10strict.js create mode 100644 www/js/FCKeditor/editor/dtd/fck_xhtml10transitional.js create mode 100644 www/js/FCKeditor/editor/fckdebug.html create mode 100644 www/js/FCKeditor/editor/fckdialog.html create mode 100644 www/js/FCKeditor/editor/fckeditor.html create mode 100644 www/js/FCKeditor/editor/fckeditor.original.html create mode 100644 www/js/FCKeditor/editor/images/anchor.gif create mode 100644 www/js/FCKeditor/editor/images/arrow_ltr.gif create mode 100644 www/js/FCKeditor/editor/images/arrow_rtl.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/angel_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/angry_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/broken_heart.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/cake.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/confused_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/cry_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/devil_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/embaressed_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/envelope.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/heart.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/kiss.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/lightbulb.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/omg_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/regular_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/sad_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/shades_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/teeth_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/thumbs_down.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/thumbs_up.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/tounge_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif create mode 100644 www/js/FCKeditor/editor/images/smiley/msn/wink_smile.gif create mode 100644 www/js/FCKeditor/editor/images/spacer.gif create mode 100644 www/js/FCKeditor/editor/js/fckadobeair.js create mode 100644 www/js/FCKeditor/editor/js/fckeditorcode_gecko.js create mode 100644 www/js/FCKeditor/editor/js/fckeditorcode_ie.js create mode 100644 www/js/FCKeditor/editor/lang/af.js create mode 100644 www/js/FCKeditor/editor/lang/ar.js create mode 100644 www/js/FCKeditor/editor/lang/bg.js create mode 100644 www/js/FCKeditor/editor/lang/bn.js create mode 100644 www/js/FCKeditor/editor/lang/bs.js create mode 100644 www/js/FCKeditor/editor/lang/ca.js create mode 100644 www/js/FCKeditor/editor/lang/cs.js create mode 100644 www/js/FCKeditor/editor/lang/da.js create mode 100644 www/js/FCKeditor/editor/lang/de.js create mode 100644 www/js/FCKeditor/editor/lang/el.js create mode 100644 www/js/FCKeditor/editor/lang/en-au.js create mode 100644 www/js/FCKeditor/editor/lang/en-ca.js create mode 100644 www/js/FCKeditor/editor/lang/en-uk.js create mode 100644 www/js/FCKeditor/editor/lang/en.js create mode 100644 www/js/FCKeditor/editor/lang/eo.js create mode 100644 www/js/FCKeditor/editor/lang/es.js create mode 100644 www/js/FCKeditor/editor/lang/et.js create mode 100644 www/js/FCKeditor/editor/lang/eu.js create mode 100644 www/js/FCKeditor/editor/lang/fa.js create mode 100644 www/js/FCKeditor/editor/lang/fi.js create mode 100644 www/js/FCKeditor/editor/lang/fo.js create mode 100644 www/js/FCKeditor/editor/lang/fr-ca.js create mode 100644 www/js/FCKeditor/editor/lang/fr.js create mode 100644 www/js/FCKeditor/editor/lang/gl.js create mode 100644 www/js/FCKeditor/editor/lang/gu.js create mode 100644 www/js/FCKeditor/editor/lang/he.js create mode 100644 www/js/FCKeditor/editor/lang/hi.js create mode 100644 www/js/FCKeditor/editor/lang/hr.js create mode 100644 www/js/FCKeditor/editor/lang/hu.js create mode 100755 www/js/FCKeditor/editor/lang/is.js create mode 100644 www/js/FCKeditor/editor/lang/it.js create mode 100644 www/js/FCKeditor/editor/lang/ja.js create mode 100644 www/js/FCKeditor/editor/lang/km.js create mode 100644 www/js/FCKeditor/editor/lang/ko.js create mode 100644 www/js/FCKeditor/editor/lang/lt.js create mode 100644 www/js/FCKeditor/editor/lang/lv.js create mode 100644 www/js/FCKeditor/editor/lang/mn.js create mode 100644 www/js/FCKeditor/editor/lang/ms.js create mode 100644 www/js/FCKeditor/editor/lang/nb.js create mode 100644 www/js/FCKeditor/editor/lang/nl.js create mode 100644 www/js/FCKeditor/editor/lang/no.js create mode 100644 www/js/FCKeditor/editor/lang/pl.js create mode 100644 www/js/FCKeditor/editor/lang/pt-br.js create mode 100644 www/js/FCKeditor/editor/lang/pt.js create mode 100644 www/js/FCKeditor/editor/lang/ro.js create mode 100644 www/js/FCKeditor/editor/lang/ru.js create mode 100644 www/js/FCKeditor/editor/lang/sk.js create mode 100644 www/js/FCKeditor/editor/lang/sl.js create mode 100644 www/js/FCKeditor/editor/lang/sr-latn.js create mode 100644 www/js/FCKeditor/editor/lang/sr.js create mode 100644 www/js/FCKeditor/editor/lang/sv.js create mode 100644 www/js/FCKeditor/editor/lang/th.js create mode 100644 www/js/FCKeditor/editor/lang/tr.js create mode 100644 www/js/FCKeditor/editor/lang/uk.js create mode 100644 www/js/FCKeditor/editor/lang/vi.js create mode 100644 www/js/FCKeditor/editor/lang/zh-cn.js create mode 100644 www/js/FCKeditor/editor/lang/zh.js create mode 100644 www/js/FCKeditor/editor/plugins/autogrow/fckplugin.js create mode 100644 www/js/FCKeditor/editor/plugins/bbcode/fckplugin.js create mode 100644 www/js/FCKeditor/editor/plugins/dragresizetable/fckplugin.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/fck_placeholder.html create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/fckplugin.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/lang/de.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/lang/en.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/lang/es.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/lang/fr.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/lang/it.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/lang/pl.js create mode 100644 www/js/FCKeditor/editor/plugins/placeholder/placeholder.gif create mode 100644 www/js/FCKeditor/editor/plugins/simplecommands/fckplugin.js create mode 100644 www/js/FCKeditor/editor/plugins/tablecommands/fckplugin.js create mode 100644 www/js/FCKeditor/editor/skins/silver/fck_dialog.css create mode 100644 www/js/FCKeditor/editor/skins/silver/fck_dialog_ie6.js create mode 100644 www/js/FCKeditor/editor/skins/silver/fck_editor.css create mode 100644 www/js/FCKeditor/editor/skins/silver/fck_strip.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/dialog.sides.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/dialog.sides.png create mode 100644 www/js/FCKeditor/editor/skins/silver/images/dialog.sides.rtl.png create mode 100644 www/js/FCKeditor/editor/skins/silver/images/sprites.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/sprites.png create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.arrowright.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.buttonarrow.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.buttonbg.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.collapse.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.end.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.expand.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.separator.gif create mode 100644 www/js/FCKeditor/editor/skins/silver/images/toolbar.start.gif create mode 100644 www/js/FCKeditor/fckconfig.js create mode 100644 www/js/FCKeditor/fckeditor.js create mode 100644 www/js/FCKeditor/fckpackager.xml create mode 100644 www/js/FCKeditor/fckstyles.xml create mode 100644 www/js/FCKeditor/fcktemplates.xml create mode 100644 www/js/FCKeditor/license.txt create mode 100644 www/js/excanvas.min.js create mode 100644 www/js/jqplot/jqplot.barRenderer.min.js create mode 100644 www/js/jqplot/jqplot.canvasAxisLabelRenderer.min.js create mode 100644 www/js/jqplot/jqplot.canvasAxisTickRenderer.min.js create mode 100644 www/js/jqplot/jqplot.canvasTextRenderer.min.js create mode 100644 www/js/jqplot/jqplot.categoryAxisRenderer.min.js create mode 100644 www/js/jqplot/jqplot.cursor.min.js create mode 100644 www/js/jqplot/jqplot.dateAxisRenderer.min.js create mode 100644 www/js/jqplot/jqplot.dragable.min.js create mode 100644 www/js/jqplot/jqplot.highlighter.min.js create mode 100644 www/js/jqplot/jqplot.logAxisRenderer.min.js create mode 100644 www/js/jqplot/jqplot.ohlcRenderer.min.js create mode 100644 www/js/jqplot/jqplot.pieRenderer.min.js create mode 100644 www/js/jqplot/jqplot.pointLabels.min.js create mode 100644 www/js/jqplot/jqplot.trendline.min.js create mode 100644 www/js/jquery-1.3.2.min.js create mode 100644 www/js/jquery.jqplot.min.js create mode 100644 www/js/js.php create mode 100644 www/js/ortro.js create mode 100644 www/js/ortro_wf.js create mode 100644 www/js/overlibmws.js create mode 100644 www/js/ui.accordion.js create mode 100644 www/js/ui.core.js create mode 100644 www/js/ui.datepicker.ortro.js create mode 100644 www/js/ui.datepicker.patched.js create mode 100644 www/js/ui.tabs.js create mode 100644 www/template/action/autodiscovery.php create mode 100644 www/template/action/calendars.php create mode 100644 www/template/action/cas_settings.php create mode 100644 www/template/action/db.php create mode 100644 www/template/action/filemanager.php create mode 100644 www/template/action/group.php create mode 100644 www/template/action/host.php create mode 100644 www/template/action/identity_management.php create mode 100644 www/template/action/import_export.php create mode 100644 www/template/action/jobs.php create mode 100644 www/template/action/ldap_settings.php create mode 100644 www/template/action/notify.php create mode 100644 www/template/action/plugin.php create mode 100644 www/template/action/plugin_notify.php create mode 100644 www/template/action/settings.php create mode 100644 www/template/action/system.php create mode 100644 www/template/action/user.php create mode 100644 www/template/action/workflows.php create mode 100644 www/template/add/autodiscovery.php create mode 100644 www/template/add/calendars.php create mode 100644 www/template/add/db.php create mode 100644 www/template/add/group.php create mode 100644 www/template/add/host.php create mode 100644 www/template/add/identity_management.php create mode 100644 www/template/add/jobs.php create mode 100644 www/template/add/notify.php create mode 100644 www/template/add/plugin.php create mode 100644 www/template/add/plugin_notify.php create mode 100644 www/template/add/system.php create mode 100644 www/template/add/user.php create mode 100644 www/template/add/workflows.php create mode 100644 www/template/body.php create mode 100644 www/template/default.php create mode 100644 www/template/details/db.php create mode 100644 www/template/details/display_archive_results.php create mode 100644 www/template/details/display_reports.php create mode 100644 www/template/details/jobs.php create mode 100644 www/template/details/notify.php create mode 100644 www/template/details/workflows.php create mode 100644 www/template/edit/calendars.php create mode 100644 www/template/edit/db.php create mode 100644 www/template/edit/filemanager.php create mode 100644 www/template/edit/group.php create mode 100644 www/template/edit/host.php create mode 100644 www/template/edit/identity_management.php create mode 100644 www/template/edit/jobs.php create mode 100644 www/template/edit/notify.php create mode 100644 www/template/edit/plugin.php create mode 100644 www/template/edit/plugin_notify.php create mode 100644 www/template/edit/system.php create mode 100644 www/template/edit/user.php create mode 100644 www/template/edit/userGroup.php create mode 100644 www/template/edit/workflows.php create mode 100644 www/template/footer.php create mode 100644 www/template/header.php create mode 100644 www/template/install/0.php create mode 100644 www/template/install/1.php create mode 100644 www/template/install/2.php create mode 100644 www/template/install/3.php create mode 100644 www/template/install/4.php create mode 100644 www/template/install/5.php create mode 100644 www/template/install/6.php create mode 100644 www/template/install/7.php create mode 100644 www/template/install/add_cron.sh create mode 100644 www/template/install/backup_cron.sh create mode 100644 www/template/install/footer.php create mode 100644 www/template/install/gpl.html create mode 100644 www/template/install/header.php create mode 100644 www/template/install/index.php create mode 100644 www/template/install/menu.php create mode 100644 www/template/install/ortro.schema.xml create mode 100644 www/template/install/plugins/database_check_tablespace-1.2.2.tar.gz create mode 100644 www/template/install/plugins/database_custom_query-1.2.2.tar.gz create mode 100644 www/template/install/plugins/database_custom_query_report-1.2.2.tar.gz create mode 100644 www/template/install/plugins/file_create-1.2.2.tar.gz create mode 100644 www/template/install/plugins/file_ftp_upload-1.0.3.tar.gz create mode 100644 www/template/install/plugins/file_read_file-1.0.2.tar.gz create mode 100644 www/template/install/plugins/file_retention-1.2.4.tar.gz create mode 100644 www/template/install/plugins/file_search-1.2.4.tar.gz create mode 100644 www/template/install/plugins/file_size_check-1.2.3.tar.gz create mode 100644 www/template/install/plugins/general_custom_script-1.2.3.tar.gz create mode 100644 www/template/install/plugins/general_windows_remote_execution-1.0.1.tar.gz create mode 100644 www/template/install/plugins/notification_jabber-1.2.3.tar.gz create mode 100644 www/template/install/plugins/notification_mail-1.2.6.tar.gz create mode 100644 www/template/install/plugins/notification_sms_ftp-1.2.3.tar.gz create mode 100644 www/template/install/plugins/notification_tibco_rvd-1.2.2.tar.gz create mode 100644 www/template/install/plugins/notification_tivoli_postemsg-1.2.2.tar.gz create mode 100644 www/template/install/plugins/system_cpu_idle-1.0.4.tar.gz create mode 100644 www/template/install/plugins/system_file_system_check-1.2.4.tar.gz create mode 100644 www/template/install/plugins/system_ping-1.2.4.tar.gz create mode 100644 www/template/install/plugins/system_service_check-1.2.4.tar.gz create mode 100644 www/template/install/plugins/www_check_uri_response_code-1.0.4.tar.gz create mode 100644 www/template/install/plugins/www_testgen4web_simpletest-1.2.6.tar.gz create mode 100644 www/template/login.php create mode 100644 www/template/menu.php create mode 100644 www/template/showMessage.php create mode 100644 www/template/view/autodiscovery.php create mode 100644 www/template/view/calendars.php create mode 100644 www/template/view/cas_settings.php create mode 100644 www/template/view/db.php create mode 100644 www/template/view/filemanager.php create mode 100644 www/template/view/group.php create mode 100644 www/template/view/host.php create mode 100644 www/template/view/identity_management.php create mode 100644 www/template/view/import_export.php create mode 100644 www/template/view/jobs.php create mode 100644 www/template/view/ldap_settings.php create mode 100644 www/template/view/notify.php create mode 100644 www/template/view/plugin.php create mode 100644 www/template/view/plugin_notify.php create mode 100644 www/template/view/settings.php create mode 100644 www/template/view/system.php create mode 100644 www/template/view/user.php create mode 100644 www/template/view/workflows.php create mode 100644 www/xmlrpc/index.php create mode 100644 www/xmlrpc/test_xml_rpc_cli.php diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..2800e2a --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,152 @@ +Ortro an open source framework designed to make easy activities +for job scheduling and system/application monitoring. +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Ortro includes or is derivative of works distributed under the following copyright notices: + +Pear packages: +============== + +Config +------ +Copyright: 1997, 1998, 1999, 2000, 2001 The PHP Group +License: PHP license + +HTML_Common +----------- +Copyright: 1997, 1998, 1999, 2000, 2001 The PHP Group +License: PHP license + +HTML_QuickForm +-------------- +Copyright: 1997-2003 The PHP Group +License: PHP license + +Note: HTML_QuickForm was patched see point 1 and below for details. + +1) Patch to enable the javascript check form control only if the input form is not disabled. +The script modified is HTML/QuickForm/RuleRegistry.php +Go to: +function getValidationScript +Change: +if (" . str_replace('{jsVar}', 'value', $jsCheck) . " && !errFlag['{$jsField}']) {\n" +with: +if (" . str_replace('{jsVar}', 'value', $jsCheck) . " && !errFlag['{$jsField}'] && !frm.elements['{$jsField}'].disabled) {\n" + +and + +if (res < {$ruleData['howmany']} && !errFlag['{$jsField}']) {\n" . + with +if (res < {$ruleData['howmany']} && !errFlag['{$jsField}'] && !frm.elements['{$jsField}'].disabled) {\n" . + +2) Set to null the default values for $_jsPrefix and $_jsPostfix +Modified file HTML/QuickForm.php + +HTML_Table +---------- +Copyright: 2005-2006 The PHP Group +License: New BSD + +MDB2 +---- +License: BSD License + +MDB2_Driver_ibase +----------------- +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith, Lorenzo Alberton +License: BSD License + +MDB2_Driver_mssql +----------------- +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith, Frank M. Kromann +License: BSD License + +MDB2_Driver_mysql +----------------- +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith +License: BSD License + +MDB2_Driver_mysqli +----------------- +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith +License: BSD License + +MDB2_Driver_oci8 +----------------- +Copyright: 1998-2007 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith +License: BSD License + +MDB2_Driver_pgsql +----------------- +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith +License: BSD License + +MDB2_Driver_sqlite +------------------ +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith +License: BSD License + +MDB2_Schema +----------- +Copyright: 1998-2006 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, Lukas Smith +License: BSD License + +XML_Parser +---------- +Copyright: 1997-2004 The PHP Group +License: PHP License + +XML_RPC +-------- +Copyright: 1999-2001 Edd Dumbill, 2001-2006 The PHP Group +License: PHP License + +PEAR +---- +Copyright: 1997-2006 The PHP Group +License: PHP License + +FCKEditor +========= +Copyright: 2003-2007 Frederico Caldeira Knabben +License: GNU Lesser General Public License Version 2.1 or later (the "LGPL") + +Overlibwms +========== +Copyright: Copyright Foteos Macrides 2002-2007 +License: Artistic (see: http://www.macridesweb.com/oltest/license.html) + +Open Flash Chart +================ +Copyright: (C) 2007 John Glazebrook +License: GNU General Public License 2 or later + + +Icons: +====== + +KDE Crystal theme icons +----------------------- +Copyright: 2002 and following years KDE Artists +License: GNU Lesser General Public License (the "LGPL") + +Nuvola +------ +Copyright: 2003-2004 David Vignoni +License: GNU Lesser General Public License (the "LGPL") diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md index 171f316..914beaa 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,59 @@ -ortro -===== \ No newline at end of file + -------------------------- Ortro ------------------------------- +An open source framework designed to make easy activities +for job scheduling and system/application monitoring. + ---------------------------------------------------------------- + +License: GNU GPL (GNU General Public License. See LICENSE file), + OSI Certified Open Source Software license. +Version: 1.4.x +Platforms: Linux, BSD, Solaris and other *NIX's, BeOS, OS/2... +Author: Luca Corbo +Web site and latest version: http://www.ortro.net + +Features +======== + +Ortro is an OpenSource project released under the GNU GPL license, +it's written in PHP and runs on Linux, BSD, Solaris and other *NIX's, BeOS, +OS/2... platforms + +It's extensible, every compontent is seen like a plug-in +(php classes loaded dinamically). + +Ortro does not require installation of software/daemon on the hosts, +it communicates with hosts using ssh or dbms connection. + +For the latest documentation and how to install please refer to the web site: +http://www.ortro.net + +Requirements +============ + +- Apache 2.x or a web server with php support +- Php 5.1.x +- Mysql 5.0.x or Sqlite or Postgres +- Ssh client + +External libraries +================== + +Ortro includes or is derivative of works distributed under the copyright +notices as reported in the COPYRIGHT file. + +About the author, license and support +===================================== +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/bin/crontab.php b/bin/crontab.php new file mode 100644 index 0000000..8723e66 --- /dev/null +++ b/bin/crontab.php @@ -0,0 +1,26 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'init.inc.php'; +require_once 'cronUtil.php'; +$cronUtil = new CronUtil(); +$cronUtil->runCron(); + +?> \ No newline at end of file diff --git a/conf/configure_metadata_cas.php b/conf/configure_metadata_cas.php new file mode 100644 index 0000000..0ce76d6 --- /dev/null +++ b/conf/configure_metadata_cas.php @@ -0,0 +1,51 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/* cas Configuration */ +$conf_metadata['cas']['description'] = 'CAS Configuration'; + +$conf_metadata['cas']['server_hostname']['description'] = 'The hostname of the CAS server'; +$conf_metadata['cas']['server_hostname']['type'] = 'text'; +$conf_metadata['cas']['server_hostname']['name'] = 'cas-server_hostname'; +$conf_metadata['cas']['server_hostname']['value'] = 'localhost'; +$conf_metadata['cas']['server_hostname']['attributes'] = 'size=30'; + +$conf_metadata['cas']['server_port']['description'] = 'The port the CAS server is running on'; +$conf_metadata['cas']['server_port']['type'] = 'text'; +$conf_metadata['cas']['server_port']['name'] = 'cas-server_port'; +$conf_metadata['cas']['server_port']['value'] = '443'; +$conf_metadata['cas']['server_port']['attributes'] = 'size=30'; + +$conf_metadata['cas']['server_uri']['description'] = 'The URI the CAS server is responding on'; +$conf_metadata['cas']['server_uri']['type'] = 'text'; +$conf_metadata['cas']['server_uri']['name'] = 'cas-server_uri'; +$conf_metadata['cas']['server_uri']['value'] = ''; +$conf_metadata['cas']['server_uri']['attributes'] = 'size=30'; + +$conf_metadata['cas']['curl_opt_ssl_version']['description'] = 'The SSL version (2 or 3) to use. + By default PHP will try to determine this itself, + although in some cases this must be set manually.'; +$conf_metadata['cas']['curl_opt_ssl_version']['type'] = 'select'; +$conf_metadata['cas']['curl_opt_ssl_version']['name'] = 'cas-curl_opt_ssl_version'; +$conf_metadata['cas']['curl_opt_ssl_version']['value'] = array('0' => 'Not specified', + '2' => 'SSL version 2', + '3' => 'SSL version 3'); +$conf_metadata['cas']['curl_opt_ssl_version']['attributes'] = ''; +?> \ No newline at end of file diff --git a/conf/configure_metadata_install.php b/conf/configure_metadata_install.php new file mode 100644 index 0000000..a105de6 --- /dev/null +++ b/conf/configure_metadata_install.php @@ -0,0 +1,218 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['db']['description'] = CONF_INSTALL_DB_DESCRIPTION; +$conf_metadata['db']['phptype']['description'] = CONF_INSTALL_DB_PHPTYPE_DESCRIPTION; +$conf_metadata['db']['phptype']['type'] = 'select'; +$conf_metadata['db']['phptype']['name'] = 'db-phptype'; +$conf_metadata['db']['phptype']['value'] = array('mysql' => CONF_INSTALL_DB_PHPTYPE_VALUE_1, + 'mysqli' => CONF_INSTALL_DB_PHPTYPE_VALUE_2, + 'oci8' => CONF_INSTALL_DB_PHPTYPE_VALUE_3, + 'pgsql' => CONF_INSTALL_DB_PHPTYPE_VALUE_4, + 'sqlite' => CONF_INSTALL_DB_PHPTYPE_VALUE_5, + 'mssql' => CONF_INSTALL_DB_PHPTYPE_VALUE_6, + 'ibase' => CONF_INSTALL_DB_PHPTYPE_VALUE_7); +$conf_metadata['db']['phptype']['attributes'] = ''; + +$conf_metadata['db']['host']['description'] = CONF_INSTALL_DB_HOST_DESCRIPTION; +$conf_metadata['db']['host']['type'] = 'text'; +$conf_metadata['db']['host']['name'] = 'db-host'; +$conf_metadata['db']['host']['value'] = CONF_INSTALL_DB_HOST_VALUE; +$conf_metadata['db']['host']['attributes'] = 'size=30'; +$conf_metadata['db']['host']['num_rules'] = '1'; +$conf_metadata['db']['host']['rule_msg'][0] = CONF_INSTALL_DB_HOST_RULE_1_0; +$conf_metadata['db']['host']['rule_type'][0] = 'required'; +$conf_metadata['db']['host']['rule_attribute'][0] = ''; + +$conf_metadata['db']['port']['description'] = CONF_INSTALL_DB_PORT_DESCRIPTION; +$conf_metadata['db']['port']['type'] = 'text'; +$conf_metadata['db']['port']['name'] = 'db-port'; +$conf_metadata['db']['port']['value'] = '3306'; +$conf_metadata['db']['port']['attributes'] = 'size=10'; +$conf_metadata['db']['port']['num_rules'] = '1'; +$conf_metadata['db']['port']['rule_msg'][0] = CONF_INSTALL_DB_PORT_RULE_1_0; +$conf_metadata['db']['port']['rule_type'][0] = 'numeric'; +$conf_metadata['db']['port']['rule_attribute'][0] = ''; + +$conf_metadata['db']['database']['description'] = CONF_INSTALL_DB_DATABASE_DESCRIPTION; +$conf_metadata['db']['database']['type'] = 'text'; +$conf_metadata['db']['database']['name'] = 'db-database'; +$conf_metadata['db']['database']['value'] = CONF_INSTALL_DB_DATABASE_VALUE; +$conf_metadata['db']['database']['attributes'] = 'size=30'; +$conf_metadata['db']['database']['rule_msg'][0] = CONF_INSTALL_DB_DATABASE_RULE_1_0; +$conf_metadata['db']['database']['rule_type'][0] = 'required'; +$conf_metadata['db']['database']['rule_attribute'][0] = ''; + +$conf_metadata['db']['username']['description'] = CONF_INSTALL_DB_USERNAME_DESCRIPTION; +$conf_metadata['db']['username']['type'] = 'text'; +$conf_metadata['db']['username']['name'] = 'db-username'; +$conf_metadata['db']['username']['value'] = CONF_INSTALL_DB_USERNAME_VALUE; +$conf_metadata['db']['username']['attributes'] = 'size=30'; +$conf_metadata['db']['username']['rule_msg'][0] = CONF_INSTALL_DB_USERNAME_RULE_1_0; +$conf_metadata['db']['username']['rule_type'][0] = 'required'; +$conf_metadata['db']['username']['rule_attribute'][0] = ''; + +$conf_metadata['db']['password']['description'] = CONF_INSTALL_DB_PASSWORD_DESCRIPTION; +$conf_metadata['db']['password']['type'] = 'password'; +$conf_metadata['db']['password']['name'] = 'db-password'; +$conf_metadata['db']['password']['value'] = ''; +$conf_metadata['db']['password']['attributes'] = 'size=30'; + +$conf_metadata['db']['tableprefix']['description'] = CONF_INSTALL_DB_TABLEPREFIX_DESCRIPTION; +$conf_metadata['db']['tableprefix']['type'] = 'text'; +$conf_metadata['db']['tableprefix']['name'] = 'db-tableprefix'; +$conf_metadata['db']['tableprefix']['value'] = CONF_INSTALL_DB_TABLEPREFIX_VALUE; +$conf_metadata['db']['tableprefix']['attributes'] = 'size=30'; + +/* Auth configuration */ +require_once 'authUtil.php'; +$conf_metadata['auth']['description'] = CONF_INSTALL_AUTH_DESCRIPTION; + +// Authentication settings +$conf_metadata['auth']['default']['description'] = CONF_INSTALL_AUTH_DEFAULT_DESCRIPTION; +$conf_metadata['auth']['default']['type'] = 'select'; +$conf_metadata['auth']['default']['name'] = 'auth-default'; +$conf_metadata['auth']['default']['value'] = authUtil::getAvailableAuthMethods(); +$conf_metadata['auth']['default']['attributes'] = ''; + +// Database fallback authentication method +$conf_metadata['auth']['fallback']['description'] = CONF_INSTALL_AUTH_FALLBACK_DESCRIPTION; +$conf_metadata['auth']['fallback']['type'] = 'select'; +$conf_metadata['auth']['fallback']['name'] = 'auth-fallback'; +$conf_metadata['auth']['fallback']['value'] = array('0' => DISABLE, '1' => ENABLE); +$conf_metadata['auth']['fallback']['attributes'] = ''; + +/* Environment configuration */ +$conf_metadata['env']['description'] = CONF_INSTALL_ENV_DESCRIPTION; + +// Language settings +$conf_metadata['env']['lang']['description'] = CONF_INSTALL_ENV_LANG_DESCRIPTION; +$conf_metadata['env']['lang']['type'] = 'select'; +$conf_metadata['env']['lang']['name'] = 'env-lang'; +$conf_metadata['env']['lang']['value'] = getAvailableLanguages(); +$conf_metadata['env']['lang']['attributes'] = ''; + +$conf_metadata['env']['php_path']['description'] = CONF_INSTALL_ENV_PHP_PATH_DESCRIPTION; +$conf_metadata['env']['php_path']['type'] = 'text'; +$conf_metadata['env']['php_path']['name'] = 'env-php_path'; +$conf_metadata['env']['php_path']['value'] = '/usr/bin/'; +$conf_metadata['env']['php_path']['attributes'] = 'size=30'; +$conf_metadata['env']['php_path']['rule_msg'][0] = CONF_INSTALL_ENV_PHP_PATH_RULE_1_0; +$conf_metadata['env']['php_path']['rule_type'][0] = 'required'; +$conf_metadata['env']['php_path']['rule_attribute'][0] = ''; + +// SSH Settings +$conf_metadata['env']['ssh_path']['description'] = CONF_INSTALL_ENV_SSH_PATH_DESCRIPTION; +$conf_metadata['env']['ssh_path']['type'] = 'text'; +$conf_metadata['env']['ssh_path']['name'] = 'env-ssh_path'; +$conf_metadata['env']['ssh_path']['value'] = '/usr/bin/'; +$conf_metadata['env']['ssh_path']['attributes'] = 'size=30'; +$conf_metadata['env']['ssh_path']['rule_msg'][0] = CONF_INSTALL_ENV_SSH_PATH_RULE_1_0; +$conf_metadata['env']['ssh_path']['rule_type'][0] = 'required'; +$conf_metadata['env']['ssh_path']['rule_attribute'][0] = ''; + +$conf_metadata['env']['ssh_keyname']['description'] = CONF_INSTALL_ENV_SSH_KEYNAME_DESCRIPTION; +$conf_metadata['env']['ssh_keyname']['type'] = 'text'; +$conf_metadata['env']['ssh_keyname']['name'] = 'env-ssh_keyname'; +$conf_metadata['env']['ssh_keyname']['value'] = 'ortro_rsa'; +$conf_metadata['env']['ssh_keyname']['attributes'] = 'size=30'; +$conf_metadata['env']['ssh_keyname']['rule_msg'][0] = CONF_INSTALL_ENV_SSH_KEYNAME_RULE_1_0; +$conf_metadata['env']['ssh_keyname']['rule_type'][0] = 'required'; +$conf_metadata['env']['ssh_keyname']['rule_attribute'][0] = ''; + +$conf_metadata['env']['ssh_type']['description'] = CONF_INSTALL_ENV_SSH_TYPE_DESCRIPTION; +$conf_metadata['env']['ssh_type']['type'] = 'select'; +$conf_metadata['env']['ssh_type']['name'] = 'env-ssh_type'; +$conf_metadata['env']['ssh_type']['value'] = array('rsa' => 'rsa', 'dsa' => 'dsa'); +$conf_metadata['env']['ssh_type']['attributes'] = ''; + +$conf_metadata['env']['ssh_bits']['description'] = CONF_INSTALL_ENV_SSH_BITS_DESCRIPTION; +$conf_metadata['env']['ssh_bits']['type'] = 'select'; +$conf_metadata['env']['ssh_bits']['name'] = 'env-ssh_bits'; +$conf_metadata['env']['ssh_bits']['value'] = array('1024' => '1024', '2048' => '2048'); +$conf_metadata['env']['ssh_bits']['attributes'] = ''; + +$conf_metadata['env']['ssh_StrictHostKeyChecking']['description'] = CONF_INSTALL_ENV_SSH_STRICTHOSTKEYCHECKING_DESCRIPTION; +$conf_metadata['env']['ssh_StrictHostKeyChecking']['type'] = 'select'; +$conf_metadata['env']['ssh_StrictHostKeyChecking']['name'] = 'env-ssh_StrictHostKeyChecking'; +$conf_metadata['env']['ssh_StrictHostKeyChecking']['value'] = array('no' => NO, 'ask' => ASK, 'yes' => YES); +$conf_metadata['env']['ssh_StrictHostKeyChecking']['attributes'] =''; + + +$conf_metadata['env']['zip_path']['description'] = CONF_INSTALL_ENV_ZIP_PATH_DESCRIPTION; +$conf_metadata['env']['zip_path']['type'] = 'text'; +$conf_metadata['env']['zip_path']['name'] = 'env-zip_path'; +$conf_metadata['env']['zip_path']['value'] = '/usr/bin/zip'; +$conf_metadata['env']['zip_path']['attributes'] ='size=30'; + +$conf_metadata['env']['zip_threshold']['description'] = CONF_INSTALL_ENV_ZIP_THRESHOLD_DESCRIPTION; +$conf_metadata['env']['zip_threshold']['type'] = 'text'; +$conf_metadata['env']['zip_threshold']['name'] = 'env-zip_threshold'; +$conf_metadata['env']['zip_threshold']['value'] = '512000'; +$conf_metadata['env']['zip_threshold']['attributes'] = 'size=30'; + +// Log settings +$conf_metadata['env']['log_level']['description'] = CONF_INSTALL_ENV_LOG_LEVEL_DESCRIPTION; +$conf_metadata['env']['log_level']['type'] = 'select'; +$conf_metadata['env']['log_level']['name'] = 'env-log_level'; +$conf_metadata['env']['log_level']['value'] = array('DEBUG' => CONF_INSTALL_ENV_LOG_LEVEL_DEBUG, + 'INFO' => CONF_INSTALL_ENV_LOG_LEVEL_INFO, + 'ERROR' => CONF_INSTALL_ENV_LOG_LEVEL_ERROR); +$conf_metadata['env']['log_level']['attributes'] = ''; + +$conf_metadata['env']['dateFormat']['description'] = CONF_INSTALL_ENV_DATEFORMAT_DESCRIPTION; +$conf_metadata['env']['dateFormat']['type'] = 'text'; +$conf_metadata['env']['dateFormat']['name'] = 'env-dateFormat'; +$conf_metadata['env']['dateFormat']['value'] = 'Y-m-d'; +$conf_metadata['env']['dateFormat']['attributes'] = 'size=10'; +$conf_metadata['env']['dateFormat']['rule_msg'][0] = CONF_INSTALL_DATEFORMAT_RULE_1_0; +$conf_metadata['env']['dateFormat']['rule_type'][0] = 'required'; +$conf_metadata['env']['dateFormat']['rule_attribute'][0] = ''; + +$conf_metadata['env']['timeFormat']['description'] = CONF_INSTALL_ENV_TIMEFORMAT_DESCRIPTION; +$conf_metadata['env']['timeFormat']['type'] = 'text'; +$conf_metadata['env']['timeFormat']['name'] = 'env-timeFormat'; +$conf_metadata['env']['timeFormat']['value'] = 'H:i:s'; +$conf_metadata['env']['timeFormat']['attributes'] = 'size=10'; +$conf_metadata['env']['timeFormat']['rule_msg'][0] = CONF_INSTALL_ENV_DATEFORMAT_RULE_1_0; +$conf_metadata['env']['timeFormat']['rule_type'][0] = 'required'; +$conf_metadata['env']['timeFormat']['rule_attribute'][0] = ''; + +$conf_metadata['env']['job_timeout']['description'] = CONF_INSTALL_ENV_JOB_TIMEOUT_DESCRIPTION; +$conf_metadata['env']['job_timeout']['type'] = 'text'; +$conf_metadata['env']['job_timeout']['name'] = 'env-job_timeout'; +$conf_metadata['env']['job_timeout']['value'] = '0'; +$conf_metadata['env']['job_timeout']['attributes'] = 'size=10'; +$conf_metadata['env']['job_timeout']['rule_msg'][0] = CONF_INSTALL_ENV_JOB_TIMEOUT_RULE_1_0; +$conf_metadata['env']['job_timeout']['rule_type'][0] = 'numeric'; +$conf_metadata['env']['job_timeout']['rule_attribute'][0] = ''; + +/* XML-RPC configuration */ +$conf_metadata['xmlrpc']['description'] = CONF_INSTALL_XMLRPC_DESCRIPTION; + +$conf_metadata['xmlrpc']['timeout']['description'] = CONF_INSTALL_XMLRPC_TIMEOUT_DESCRIPTION; +$conf_metadata['xmlrpc']['timeout']['type'] = 'text'; +$conf_metadata['xmlrpc']['timeout']['name'] = 'xmlrpc-timeout'; +$conf_metadata['xmlrpc']['timeout']['value'] = '3600'; +$conf_metadata['xmlrpc']['timeout']['attributes'] = 'size=10'; +$conf_metadata['xmlrpc']['timeout']['rule_msg'][0] = CONF_INSTALL_XMLRPC_TIMEOUT_RULE_1_0; +$conf_metadata['xmlrpc']['timeout']['rule_type'][0] = 'numeric'; +$conf_metadata['xmlrpc']['timeout']['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/conf/configure_metadata_ldap.php b/conf/configure_metadata_ldap.php new file mode 100644 index 0000000..64e5919 --- /dev/null +++ b/conf/configure_metadata_ldap.php @@ -0,0 +1,71 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/* LDAP Configuration */ +$conf_metadata['ldap']['description'] = CONF_LDAP_DESCRIPTION; + +$conf_metadata['ldap']['address_book']['description'] = CONF_LDAP_ADDRESS_BOOK_DESCRIPTION; +$conf_metadata['ldap']['address_book']['type'] = 'select'; +$conf_metadata['ldap']['address_book']['name'] = 'ldap-address_book'; +$conf_metadata['ldap']['address_book']['value'] = array('0' => DISABLE, '1' => ENABLE); +$conf_metadata['ldap']['address_book']['attributes'] = ''; + +$conf_metadata['ldap']['server']['description'] = CONF_LDAP_SERVER_DESCRIPTION; +$conf_metadata['ldap']['server']['type'] = 'text'; +$conf_metadata['ldap']['server']['name'] = 'ldap-server'; +$conf_metadata['ldap']['server']['value'] = 'ldap://directory.localhost:389'; +$conf_metadata['ldap']['server']['attributes'] = 'size=30'; + +$conf_metadata['ldap']['base_dn']['description'] = CONF_LDAP_BASE_DN_DESCRIPTION; +$conf_metadata['ldap']['base_dn']['type'] = 'text'; +$conf_metadata['ldap']['base_dn']['name'] = 'ldap-base_dn'; +$conf_metadata['ldap']['base_dn']['value'] = 'cn=users,dc=example,dc=com'; +$conf_metadata['ldap']['base_dn']['attributes'] = 'size=30'; + +$conf_metadata['ldap']['bind_dn']['description'] = CONF_LDAP_BIND_DN_DESCRIPTION; +$conf_metadata['ldap']['bind_dn']['type'] = 'text'; +$conf_metadata['ldap']['bind_dn']['name'] = 'ldap-bind_dn'; +$conf_metadata['ldap']['bind_dn']['value'] = ''; +$conf_metadata['ldap']['bind_dn']['attributes'] = 'size=30'; + +$conf_metadata['ldap']['bind_password']['description'] = CONF_LDAP_BIND_PASSWORD_DESCRIPTION; +$conf_metadata['ldap']['bind_password']['type'] = 'password'; +$conf_metadata['ldap']['bind_password']['name'] = 'ldap-bind_password'; +$conf_metadata['ldap']['bind_password']['value'] = ''; +$conf_metadata['ldap']['bind_password']['attributes'] = 'size=10'; + +$conf_metadata['ldap']['search_attribute_uid']['description'] = CONF_LDAP_SEARCH_ATTRIBUTE_UID_DESCRIPTION; +$conf_metadata['ldap']['search_attribute_uid']['type'] = 'text'; +$conf_metadata['ldap']['search_attribute_uid']['name'] = 'ldap-search_attribute_uid'; +$conf_metadata['ldap']['search_attribute_uid']['value'] = 'uid'; +$conf_metadata['ldap']['search_attribute_uid']['attributes'] = 'size=10'; + +$conf_metadata['ldap']['search_attribute_cn']['description'] = CONF_LDAP_SEARCH_ATTRIBUTE_CN_DESCRIPTION; +$conf_metadata['ldap']['search_attribute_cn']['type'] = 'text'; +$conf_metadata['ldap']['search_attribute_cn']['name'] = 'ldap-search_attribute_cn'; +$conf_metadata['ldap']['search_attribute_cn']['value'] = 'cn'; +$conf_metadata['ldap']['search_attribute_cn']['attributes'] = 'size=10'; + +$conf_metadata['ldap']['search_attribute_mail']['description'] = CONF_LDAP_SEARCH_ATTRIBUTE_MAIL_DESCRIPTION; +$conf_metadata['ldap']['search_attribute_mail']['type'] = 'text'; +$conf_metadata['ldap']['search_attribute_mail']['name'] = 'ldap-search_attribute_mail'; +$conf_metadata['ldap']['search_attribute_mail']['value'] = 'mail'; +$conf_metadata['ldap']['search_attribute_mail']['attributes'] = 'size=10'; +?> \ No newline at end of file diff --git a/conf/init.inc.php b/conf/init.inc.php new file mode 100644 index 0000000..d972034 --- /dev/null +++ b/conf/init.inc.php @@ -0,0 +1,22 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once realpath(dirname(__FILE__) . '/../conf/init.php'); +?> \ No newline at end of file diff --git a/conf/init.php b/conf/init.php new file mode 100644 index 0000000..2c34a89 --- /dev/null +++ b/conf/init.php @@ -0,0 +1,102 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//########### ENV SETTINGS ########### +// DON'T MODIFY THE LINES BELOW !!!! # +//#################################### + +define('ORTRO_VERSION', '1.4.0-alpha'); +define('ORTRO_DEFAULT_LANGUAGE', 'en'); + +define('DS', DIRECTORY_SEPARATOR); +define('ORTRO_PATH', realpath(dirname(__FILE__) . DS . '..') . DS); + +define('ORTRO_CONF', ORTRO_PATH . 'conf' . DS); +define('ORTRO_CONF_PLUGINS', ORTRO_CONF . 'plugins' . DS); +define('ORTRO_SSH_PATH', ORTRO_CONF .'.ssh' . DS); +define('ORTRO_SESSION_SAVE_PATH', ORTRO_CONF .'session' . DS); + +define('ORTRO_DATA', ORTRO_PATH . 'data' . DS); +define('ORTRO_FILES', ORTRO_DATA . 'files' . DS); +define('ORTRO_INCOMING', ORTRO_DATA . 'incoming' . DS); +define('ORTRO_REPORTS', ORTRO_DATA . 'reports' . DS); +define('ORTRO_SQLITE_DB', ORTRO_DATA . 'db' . DS); +define('ORTRO_ATTACHMENTS', ORTRO_DATA . 'attachments' . DS); + +define('ORTRO_LANG', ORTRO_PATH . 'lang' . DS); + +define('ORTRO_LIB', ORTRO_PATH . 'lib' . DS); +define('ORTRO_LIB_PEAR', ORTRO_LIB . 'Pear' . DS); + +define('ORTRO_LOG', ORTRO_PATH . 'log' . DS); +define('ORTRO_LOG_PLUGINS', ORTRO_LOG . 'plugins' . DS); + +define('ORTRO_PLUGINS', ORTRO_PATH . 'plugins' . DS); +define('ORTRO_NOTIFICATION_PLUGINS', ORTRO_PLUGINS . 'notification' . DS); + +define('ORTRO_TEMP', ORTRO_PATH . 'tmp' . DS); + +define('ORTRO_WEB', ORTRO_PATH . 'www' . DS); +define('ORTRO_TEMPLATE', ORTRO_WEB . 'template' . DS); +define('ORTRO_INSTALL', ORTRO_TEMPLATE . 'install' . DS); + +//### ADD LIBS TO LIB_PATH ### +//Avoid problems with magic_quotes_runtime +@ini_set('magic_quotes_runtime', false); +//Disable display error +@ini_set('display_startup_errors', false); +@ini_set('display_errors', false); + +set_include_path(".:".ORTRO_LIB.":".ORTRO_LIB_PEAR.":".ORTRO_PLUGINS); + +//prepare config array() +global $conf; +$conf = array(); + +if (file_exists(ORTRO_CONF . 'configure.php')) { + include ORTRO_CONF . 'configure.php'; +} + +/** + * Throw new exception on error + * + * @param int $errno Contains the level of the error raised, as an integer. + * @param string $errstr Contains the error message + * @param string $errfile Contains the filename that the error was raised in + * @param int $errline Contains the line number the error was raised at + * @param array $errcontext An array that points to the active symbol + * table at the point the error occurred. + * In other words, errcontext will contain + * an array of every variable that existed in the scope + * the error was triggered in. + * + * @return boolean + * + */ +function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) +{ + if ($errno == E_WARNING || $errno == E_PARSE || $errno == E_ERROR) { + throw new Exception($errstr, $errno); + return true; + } else { + return false; + } +} +?> diff --git a/lang/en/js/js.php b/lang/en/js/js.php new file mode 100644 index 0000000..eeb8308 --- /dev/null +++ b/lang/en/js/js.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/en/plugins/database/check_tablespace/language.php b/lang/en/plugins/database/check_tablespace/language.php new file mode 100644 index 0000000..0cd5b27 --- /dev/null +++ b/lang/en/plugins/database/check_tablespace/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/database/custom_query/language.php b/lang/en/plugins/database/custom_query/language.php new file mode 100644 index 0000000..3e1d7f9 --- /dev/null +++ b/lang/en/plugins/database/custom_query/language.php @@ -0,0 +1,18 @@ + + * @author David Black + */ + +define('PLUGIN_DB_CUSTOM_QUERY_DESCRIPTION',"Executes a custom query against the selected database and compares the query result with an expected result using a logical operator.
On a true comparison result an error or success value is returned as defined in the field 'If test is true then return' flag."); +define('PLUGIN_DB_CUSTOM_QUERY_TITLE',"DB Custom Query"); +define('PLUGIN_DB_CUSTOM_QUERY_OPERATOR_DESCRIPTION',"Operator"); +define('PLUGIN_DB_CUSTOM_QUERY_SUCCESS',"Success"); +define('PLUGIN_DB_CUSTOM_QUERY_ERROR',"Error"); +define('PLUGIN_DB_CUSTOM_QUERY_THRESHOLD_DESCRIPTION',"Threshold"); +define('PLUGIN_DB_CUSTOM_QUERY_RULE_4_0',"Threshold is required"); +define('PLUGIN_DB_CUSTOM_QUERY_ERROR_DESCRIPTION',"If test evaluates true then return"); +?> \ No newline at end of file diff --git a/lang/en/plugins/database/custom_query_report/language.php b/lang/en/plugins/database/custom_query_report/language.php new file mode 100644 index 0000000..9870b5b --- /dev/null +++ b/lang/en/plugins/database/custom_query_report/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/database/execute_sql_from_file/language.php b/lang/en/plugins/database/execute_sql_from_file/language.php new file mode 100644 index 0000000..fa966aa --- /dev/null +++ b/lang/en/plugins/database/execute_sql_from_file/language.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/lang/en/plugins/database/mysql_table_check/language.php b/lang/en/plugins/database/mysql_table_check/language.php new file mode 100644 index 0000000..7135f6f --- /dev/null +++ b/lang/en/plugins/database/mysql_table_check/language.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/lang/en/plugins/database/oracle_freespa_report/language.php b/lang/en/plugins/database/oracle_freespa_report/language.php new file mode 100644 index 0000000..badf006 --- /dev/null +++ b/lang/en/plugins/database/oracle_freespa_report/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/en/plugins/database/oracle_session_report/language.php b/lang/en/plugins/database/oracle_session_report/language.php new file mode 100644 index 0000000..4de237c --- /dev/null +++ b/lang/en/plugins/database/oracle_session_report/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/advanced_file_transfer/language.php b/lang/en/plugins/file/advanced_file_transfer/language.php new file mode 100644 index 0000000..9a0b34c --- /dev/null +++ b/lang/en/plugins/file/advanced_file_transfer/language.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/check_tail_status/language.php b/lang/en/plugins/file/check_tail_status/language.php new file mode 100644 index 0000000..dcaaf37 --- /dev/null +++ b/lang/en/plugins/file/check_tail_status/language.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/create/language.php b/lang/en/plugins/file/create/language.php new file mode 100644 index 0000000..390bee8 --- /dev/null +++ b/lang/en/plugins/file/create/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/ftp_upload/language.php b/lang/en/plugins/file/ftp_upload/language.php new file mode 100644 index 0000000..6cc373f --- /dev/null +++ b/lang/en/plugins/file/ftp_upload/language.php @@ -0,0 +1,20 @@ + diff --git a/lang/en/plugins/file/read_file/language.php b/lang/en/plugins/file/read_file/language.php new file mode 100644 index 0000000..113bc63 --- /dev/null +++ b/lang/en/plugins/file/read_file/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/retention/language.php b/lang/en/plugins/file/retention/language.php new file mode 100644 index 0000000..1d483d6 --- /dev/null +++ b/lang/en/plugins/file/retention/language.php @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/scp/language.php b/lang/en/plugins/file/scp/language.php new file mode 100644 index 0000000..21d8cc7 --- /dev/null +++ b/lang/en/plugins/file/scp/language.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/search/language.php b/lang/en/plugins/file/search/language.php new file mode 100644 index 0000000..f3d2d6c --- /dev/null +++ b/lang/en/plugins/file/search/language.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/size_check/language.php b/lang/en/plugins/file/size_check/language.php new file mode 100644 index 0000000..2576f32 --- /dev/null +++ b/lang/en/plugins/file/size_check/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/en/plugins/file/watch/language.php b/lang/en/plugins/file/watch/language.php new file mode 100644 index 0000000..d612dfd --- /dev/null +++ b/lang/en/plugins/file/watch/language.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/lang/en/plugins/general/custom_script/language.php b/lang/en/plugins/general/custom_script/language.php new file mode 100644 index 0000000..bc50e87 --- /dev/null +++ b/lang/en/plugins/general/custom_script/language.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/en/plugins/general/spreadsheet_to_db/language.php b/lang/en/plugins/general/spreadsheet_to_db/language.php new file mode 100644 index 0000000..8c64e81 --- /dev/null +++ b/lang/en/plugins/general/spreadsheet_to_db/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/en/plugins/general/telnet_custom_script/language.php b/lang/en/plugins/general/telnet_custom_script/language.php new file mode 100755 index 0000000..036860d --- /dev/null +++ b/lang/en/plugins/general/telnet_custom_script/language.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/lang/en/plugins/general/windows_remote_execution/language.php b/lang/en/plugins/general/windows_remote_execution/language.php new file mode 100644 index 0000000..7bd02ca --- /dev/null +++ b/lang/en/plugins/general/windows_remote_execution/language.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/en/plugins/notification/jabber/language.php b/lang/en/plugins/notification/jabber/language.php new file mode 100644 index 0000000..eacf4d3 --- /dev/null +++ b/lang/en/plugins/notification/jabber/language.php @@ -0,0 +1,22 @@ +@server.com)"); +define('PLUGIN_JABBER_TO_DESCRIPTION_DETAIL', "To:"); + +?> \ No newline at end of file diff --git a/lang/en/plugins/notification/mail/language.php b/lang/en/plugins/notification/mail/language.php new file mode 100644 index 0000000..896fb35 --- /dev/null +++ b/lang/en/plugins/notification/mail/language.php @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/lang/en/plugins/notification/sms_ftp/language.php b/lang/en/plugins/notification/sms_ftp/language.php new file mode 100644 index 0000000..2d601f0 --- /dev/null +++ b/lang/en/plugins/notification/sms_ftp/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/en/plugins/notification/tibco_rvd/language.php b/lang/en/plugins/notification/tibco_rvd/language.php new file mode 100644 index 0000000..90eeffa --- /dev/null +++ b/lang/en/plugins/notification/tibco_rvd/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/en/plugins/notification/tivoli_postemsg/language.php b/lang/en/plugins/notification/tivoli_postemsg/language.php new file mode 100644 index 0000000..7f5ff5e --- /dev/null +++ b/lang/en/plugins/notification/tivoli_postemsg/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/check_glance_status/language.php b/lang/en/plugins/system/check_glance_status/language.php new file mode 100644 index 0000000..f81cfd4 --- /dev/null +++ b/lang/en/plugins/system/check_glance_status/language.php @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/cpu_idle/language.php b/lang/en/plugins/system/cpu_idle/language.php new file mode 100644 index 0000000..28d3f41 --- /dev/null +++ b/lang/en/plugins/system/cpu_idle/language.php @@ -0,0 +1,13 @@ +Note: lower idle time means the CPUs are more busy."); +define('PLUGIN_CPU_IDLE_RULE_3_0', "Threshold is required"); +define('PLUGIN_CPU_IDLE_THRESHOLD_DESCRIPTION', "Threshold"); +define('PLUGIN_CPU_IDLE_TITLE', "CPU Idle Time"); + +?> \ No newline at end of file diff --git a/lang/en/plugins/system/file_system_check/language.php b/lang/en/plugins/system/file_system_check/language.php new file mode 100644 index 0000000..67d4b35 --- /dev/null +++ b/lang/en/plugins/system/file_system_check/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/mem_free/language.php b/lang/en/plugins/system/mem_free/language.php new file mode 100644 index 0000000..5de3384 --- /dev/null +++ b/lang/en/plugins/system/mem_free/language.php @@ -0,0 +1,14 @@ + + * @author Francesco Acquista + */ + +define('PLUGIN_MEM_FREE_TITLE',"Memory free"); +define('PLUGIN_MEM_FREE_DESCRIPTION',"Check the amount of the free memory (percentage), and compares to a threshold value."); +define('PLUGIN_MEM_FREE_THRESHOLD_DESCRIPTION',"Threshold"); +define('PLUGIN_MEM_FREE_RULE_3_0',"Threshold is required"); +?> diff --git a/lang/en/plugins/system/ping/language.php b/lang/en/plugins/system/ping/language.php new file mode 100644 index 0000000..d5ed679 --- /dev/null +++ b/lang/en/plugins/system/ping/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/service_check/language.php b/lang/en/plugins/system/service_check/language.php new file mode 100644 index 0000000..fcc03cc --- /dev/null +++ b/lang/en/plugins/system/service_check/language.php @@ -0,0 +1,14 @@ + diff --git a/lang/en/plugins/system/solaris_metadevice_check/language.php b/lang/en/plugins/system/solaris_metadevice_check/language.php new file mode 100644 index 0000000..1b53ed1 --- /dev/null +++ b/lang/en/plugins/system/solaris_metadevice_check/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/solaris_svc_check/language.php b/lang/en/plugins/system/solaris_svc_check/language.php new file mode 100644 index 0000000..ea395df --- /dev/null +++ b/lang/en/plugins/system/solaris_svc_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/solaris_zfs_scrub_check/language.php b/lang/en/plugins/system/solaris_zfs_scrub_check/language.php new file mode 100644 index 0000000..3f1c4a8 --- /dev/null +++ b/lang/en/plugins/system/solaris_zfs_scrub_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/en/plugins/system/solaris_zpool_check/language.php b/lang/en/plugins/system/solaris_zpool_check/language.php new file mode 100644 index 0000000..db910f1 --- /dev/null +++ b/lang/en/plugins/system/solaris_zpool_check/language.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/lang/en/plugins/www/check_uri_response_code/language.php b/lang/en/plugins/www/check_uri_response_code/language.php new file mode 100644 index 0000000..82fc735 --- /dev/null +++ b/lang/en/plugins/www/check_uri_response_code/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/en/plugins/www/http_download_file/language.php b/lang/en/plugins/www/http_download_file/language.php new file mode 100644 index 0000000..a0d1d70 --- /dev/null +++ b/lang/en/plugins/www/http_download_file/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/en/plugins/www/testgen4web_simpletest/language.php b/lang/en/plugins/www/testgen4web_simpletest/language.php new file mode 100644 index 0000000..8b41097 --- /dev/null +++ b/lang/en/plugins/www/testgen4web_simpletest/language.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/lang/en/plugins/www/webservice_soapui/language.php b/lang/en/plugins/www/webservice_soapui/language.php new file mode 100644 index 0000000..9f8214f --- /dev/null +++ b/lang/en/plugins/www/webservice_soapui/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/en/plugins/www/webtest_selenium/language.php b/lang/en/plugins/www/webtest_selenium/language.php new file mode 100644 index 0000000..816b3a2 --- /dev/null +++ b/lang/en/plugins/www/webtest_selenium/language.php @@ -0,0 +1,18 @@ +Replace in the code the username and password of the identity with and"); +define('PLUGIN_WEBTEST_SELENIUM_RULE_3_0', "The script code is required"); + +?> \ No newline at end of file diff --git a/lang/en/plugins/www/webtest_slimdog/language.php b/lang/en/plugins/www/webtest_slimdog/language.php new file mode 100644 index 0000000..9b99046 --- /dev/null +++ b/lang/en/plugins/www/webtest_slimdog/language.php @@ -0,0 +1,15 @@ +Replace in the code the username and password of the identity with and"); +define('PLUGIN_WEBTEST_SLIMDOG_RULE_2_0', "The script code is required"); + +?> \ No newline at end of file diff --git a/lang/en/template/action_msg.php b/lang/en/template/action_msg.php new file mode 100644 index 0000000..4e590c9 --- /dev/null +++ b/lang/en/template/action_msg.php @@ -0,0 +1,105 @@ +Maximum allowed size for uploaded files:"); +define('MSG_ACTION_REMOVE_ALL_NOTIFICATIONS', "You must first remove all notification methods."); +define('MSG_ACTION_REMOVE_IDENTITY_FIRST', "The job(s) below are associated with this Identity. Please remove the job(s) first."); +define('MSG_ACTION_REMOVE_JOB_FIRST', "The job(s) below are associated with this plugin. Please remove the job(s) first."); +define('MSG_ACTION_REMOVE_NOTIFICATION_FIRST', "There are notification(s) associated with this plugin. Please remove the notification(s) first."); +define('MSG_ACTION_REMOVE_USER_FIRST', "The user(s) below are associated with this group. Please remove the user(s) first."); +define('MSG_ACTION_STEP_ADDED', "Step successfully added."); +define('MSG_ACTION_STRANGE_STATUS', "Unknown status... Please contact systems administrator."); +define('MSG_ACTION_SYSTEM_ADDED', "System successfully added."); +define('MSG_ACTION_SYSTEM_ALREADY_USED', "The system name is already in use."); +define('MSG_ACTION_SYSTEM_DELETED', "System(s) successfully deleted."); +define('MSG_ACTION_SYSTEM_HOSTNAME_ALREADY_USED', "That system-host association already exists."); +define('MSG_ACTION_SYSTEM_REMOVE_JOB_FIRST', "The job(s) below are associated with this system. Please remove the job(s) first."); +define('MSG_ACTION_SYSTEM_MODIFIED', "System name successfully modified."); +define('MSG_ACTION_USER_ADDED', "User successfully added."); +define('MSG_ACTION_USER_DELETED', "User(s) successfully deleted."); +define('MSG_ACTION_USER_DELETED_FROM_GROUP', "User successfully removed from group(s)."); +define('MSG_ACTION_USER_IN_GROUP_ADDED', "User successfully added in group(s)."); +define('MSG_ACTION_USER_MODIFIED', "User settings successfully modified."); +define('MSG_ACTION_USERNAME_ALREADY_USED', "Username already in use"); +define('MSG_PERMISSION_DENIED', "Permission denied!"); +define('MSG_LOGOUT', "You are now logged out."); +define('MSG_IDENTITY_PICK', "Pick"); +define('FIELD_IDENTITY_PICK', "Select the identity to use:"); +define('FIELD_IDENTITY_PICK_TITLE', "Pick Identity"); +define('MSG_IDENTITY_NOT_FOUND', "No identity found for the specified system."); +define('MSG_ACTION_FILE_UPLOAD_SUCCESS', "The file was successfully uploaded."); +define('MSG_ACTION_FILE_DELETED_SUCCESS', "The file was successfully deleted."); +define('MSG_ACTION_FILE_DELETED_ERROR', "An error occurred while deleting file."); +define('MSG_ACTION_MIN_VERSION_REQUIRED', "The minimum version of Ortro required for this plugin is:"); +define('MSG_GD_LIB_NOT_ENABLED', "Cannot create image.
GD library support not enabled in your PHP installation."); +define('MSG_EXECUTION_ABORTED', "Execution aborted"); +define('MSG_ACTION_SYSTEM_HOST_LOCKED',"System or host is locked... you must first unlock it."); +define('MSG_ACTION_SYSTEM_STATUS_UPDATED', "System status successfully updated."); +define('MSG_CALENDAR_REQUIRED', "Define a calendar"); +define('MSG_ACTION_CALENDAR_ADDED', "Calendar successfully added."); +define('MSG_ACTION_CALENDAR_MODIFIED', "Calendar successfully updated."); +define('MSG_ACTION_CALENDAR_DELETED', "Calendar successfully deleted."); +define('MSG_ACTION_CALENDAR_COPIED', "Calendar successfully copied."); +define('MSG_ACTION_REMOVE_CALENDAR_FIRST', "The job(s) below are associated with this calendar. Please remove the job(s) first."); +define('FIELD_CALENDAR_PICK', "Select the calendar to use:"); +define('FIELD_CALENDAR_PICK_TITLE', "Pick Calendar"); +?> \ No newline at end of file diff --git a/lang/en/template/common.php b/lang/en/template/common.php new file mode 100644 index 0000000..89b3634 --- /dev/null +++ b/lang/en/template/common.php @@ -0,0 +1,379 @@ +

an open source framework designed to make easy activities

for job scheduling and system/application monitoring."); +define('JS_NOT_ENABLED', "You don't have JavaScript enabled.
Ortro uses JavaScript and much of it will not work correctly without it enabled.
Please turn JavaScript back on and reload this page."); +define('HEADER_PROFILE_DESCRIPTION', "Profile"); +define('HEADER_PROFILE_TOOLTIP', "Edit your profile"); +define('HEADER_LOGOUT', "Logout"); +define('TITLE', "Ortro"); +define('ACTION_TITLE', "Actions"); +define('ACTION_LOCK_UNLOCK', "Lock/unlock action toolbar"); +define('ACTION_RELOAD_DESCRIPTION', "Reload this page"); +define('ACTION_PREV_PAGE_DESCRIPTION', "Back to the previous page"); +define('ACTION_NEXT_PAGE_DESCRIPTION', "Go to the next page"); +define('ACTION_EDIT_DESCRIPTION', "Edit"); +define('ACTION_DELETE_DESCRIPTION', "Delete"); +define('ACTION_DETAIL_DESCRIPTION', "Details"); +define('ACTION_COPY_DESCRIPTION', "Copy"); +define('ACTION_GROUP_DESCRIPTION', "Groups"); +define('ACTION_ADD_DESCRIPTION', "Add"); +define('ACTION_LOCK_DESCRIPTION', "Lock"); +define('ACTION_UNLOCK_DESCRIPTION', "Unlock"); +define('ACTION_RUN_DESCRIPTION', "Run"); +define('ACTION_PREV_STEP_DESCRIPTION', "Back to the previous step"); +define('ACTION_NEXT_STEP_DESCRIPTION', "Go to the next step"); +define('ACTION_KILL_DESCRIPTION', "Kill"); +define('REFRESH_TITLE', "Refresh:"); +define('REFRESH_MANUAL', "Manual"); +define('REFRESH_EVERY_15', "Every 15 sec."); +define('REFRESH_EVERY_30', "Every 30 sec."); +define('REFRESH_EVERY_60', "Every 60 sec."); +define('REFRESH_EVERY_180', "Every 180 sec."); +define('BUTTON_ADD', "Add"); +define('BUTTON_APPLY', "Apply"); +define('BUTTON_SEARCH', "Search"); +define('BUTTON_ADD_IN_GROUP', "Add to group"); +define('BUTTON_REMOVE_FROM_GROUP', "Remove from group"); +define('BUTTON_SAVE_SETTING', "Save Settings"); +define('BUTTON_INSTALL', "Install"); +define('BUTTON_LOGIN', "Login"); +define('BUTTON_CHANGE_PASSWORD', "Change password"); +define('SYSTEM_TOP', "Systems: view"); +define('SYSTEM_TITLE', "Below is the list of Systems configured in this Ortro installation.
Systems are administrative containers grouping a set of Hosts."); +define('SYSTEM_ADD_TOP', "Systems: add"); +define('SYSTEM_ADD_TITLE', "Use the form below to add a System."); +define('SYSTEM_EDIT_TOP', "Systems: edit"); +define('SYSTEM_EDIT_TITLE', "Use the form below to edit the System name."); +define('SYSTEM_NAME', "System Name"); +define('DATABASES_TOP', "Databases: view"); +define('DATABASES_TITLE', "Below is the list of external Databases monitored or used for reporting by this Ortro installation.
Each Database is associated with a single Host."); +define('DATABASE_ADD_TOP', "Databases: add"); +define('DATABASE_ADD_TITLE', "Use the form below to associate a Database with a Host"); +define('DATABASE_EDIT_TOP', "Databases: edit"); +define('DATABASE_EDIT_TITLE', "Use the form below to edit the Database settings."); +define('DATABASE_DETAILS_TOP', "Database: details"); +define('HOST_TOP', "Hosts: view"); +define('HOST_TITLE', "Below is the list of Hosts configured in this Ortro installation.
Hosts are where Jobs execute, and each Host is associated with a System."); +define('HOST_ADD_TOP', "Hosts: add"); +define('HOST_ADD_TITLE', "Use the form below to add a host to a system."); +define('HOST_EDIT_TOP', "Hosts: edit"); +define('HOST_EDIT_TITLE', "Use the form below to edit the host settings."); +define('JOB_TOP', "Jobs: view"); +define('JOB_TITLE', "Below is the list of Jobs configured in this Ortro installation.
Jobs are a unit of work, and each Job executes on a specified Host."); +define('JOB_ADD_TOP', "Jobs: add"); +define('JOB_ADD_TITLE', "Use the form below to add a Job."); +define('JOB_EDIT_TOP', "Jobs: edit"); +define('JOB_EDIT_TITLE', "Use the form below to edit the Job settings."); +define('JOB_DETAILS_TOP', "Jobs: details"); +define('NOTIFICATION_TOP', "Notifications: view"); +define('NOTIFICATION_TITLE', "Below is the list of Notifications configured in this Ortro installation.
Each Notification is associated with a Job and conditionally triggered by the Job completion status."); +define('NOTIFICATION_ADD_TOP', "Notifications: add"); +define('NOTIFICATION_ADD_TITLE', "Use the form below to add a Notification."); +define('NOTIFICATION_EDIT_TOP', "Notifications: edit"); +define('NOTIFICATION_EDIT_TITLE', "Use the form below to edit the Notification settings."); +define('NOTIFICATION_DETAILS_TOP', "Notifications: details"); +define('USER_TOP', "Users: view"); +define('USER_TITLE', "Below is the list of Users authorized to log in to Ortro.
User privileges are determined by membership in Groups."); +define('USER_ADD_TOP', "Users: add"); +define('USER_ADD_TITLE', "Use the form below to add a User."); +define('USER_EDIT_TOP', "Users: edit"); +define('USER_EDIT_TITLE', "Use the form below to edit the User settings."); +define('USER_DETAILS_TOP', "Users: details"); +define('USER_GROUP_EDIT_TOP', "Group Memberships: edit"); +define('USER_GROUP_EDIT_TITLE', "Use the form below to edit Group memberships."); +define('GROUP_TOP', "Groups: view"); +define('GROUP_TITLE', "Below is the list of Groups configured in this Ortro installation.
Group membership determines what actions a User may perform."); +define('GROUP_ADD_TOP', "Groups: add"); +define('GROUP_ADD_TITLE', "Use the form below to add a Group."); +define('GROUP_EDIT_TOP', "Groups: edit"); +define('GROUP_EDIT_TITLE', "Use the form below to edit the Group settings."); +define('ID_ADMIN_TOP', "Identity Management: view"); +define('ID_ADMIN_TITLE', "Below is the list of Identities configured in this Ortro installation.
Identities are stored credentials used for accessing Databases and other resources associated with a Job."); +define('ID_ADMIN_ADD_TOP', "Identity Management: add"); +define('ID_ADMIN_ADD_TITLE', "Use the form below to add a new Identity to a System and share it with other Systems."); +define('ID_ADMIN_EDIT_TOP', "Identity Management: edit"); +define('ID_ADMIN_EDIT_TITLE', "Use the form below to edit the Identity settings."); +define('ID_ADMIN_SHARE_WITH', "Select the System(s) that are to share this Identity:"); +define('SETTING_TITLE', "Please set the fields below according to your environment."); +define('LDAP_SETTING_TITLE', "Please set the fields below according to your environment."); +define('PLUGIN_TOP', "Plugins: view"); +define('PLUGIN_TITLE', "Below is the list of Plugins configured in this Ortro installation.
Each configured Job makes use of a Plugin, according to the Job purpose."); +define('PLUGIN_ADD_TOP', "Plugins: add"); +define('PLUGIN_ADD_TITLE', "Use the form below to install a new Plugin."); +define('PLUGIN_ADD_ARCHIVE', "Plugin archive"); +define('PLUGIN_EDIT_TOP', "Plugins: edit"); +define('PLUGIN_EDIT_TITLE', "Use the form below to edit the Plugin settings."); +define('PLUGIN_EDIT_ENV', "Please set the fields below according to your environment."); +define('NOTIFICATION_PLUGIN_TOP', "Notification Plugins: view"); +define('NOTIFICATION_PLUGIN_TITLE', "Below is the list of Notification Plugins configured in this Ortro installation.
Notification Plugins determine the methods by which a user may be notified at the completion of a Job."); +define('NOTIFICATION_PLUGIN_ADD_TOP', "Notification Plugins: add"); +define('NOTIFICATION_PLUGIN_ADD_TITLE', "Use the form below to install a new Notification Plugin."); +define('NOTIFICATION_PLUGIN_EDIT_TOP', "Notification Plugins: edit"); +define('NOTIFICATION_PLUGIN_EDIT_TITLE', "Use the form below to edit the Notification Plugin settings."); +define('WORKFLOW_TOP', "Workflows: view"); +define('WORKFLOW_TITLE', "Below is the list of Workflows configured in this Ortro installation.
A Workflow is a conditional sequence of Jobs."); +define('WORKFLOW_ADD_TOP', "Workflows: add"); +define('WORKFLOW_ADD_TITLE', "Use the form below to add a Workflow."); +define('WORKFLOW_EDIT_TOP', "Workflows: edit"); +define('WORKFLOW_EDIT_TITLE', "Use the form below to edit the Workflow settings."); +define('WORKFLOW_DETAILS_TOP', "Workflows: details"); +define('FILE_MANAGER_TOP', "File manager"); +define('FILE_MANAGER_TITLE', "Use the form below to upload and manage the file stored within Ortro.
Such files may be used as input to a Job."); +define('FILE_MANAGER_DISABLED', "The PHP file_uploads feature is disabled.
Please set file_uploads=On in the server php.ini file."); +define('FILTER', "Filter"); +define('FILTER_SYSTEM', "System:"); +define('FILTER_JOB', "Job:"); +define('FILTER_STATUS', "Status:"); +define('FILTER_RESULT', "Result:"); +define('FILTER_NOTIFY_TYPE', "Notify Type:"); +define('FILTER_NOTIFY_ON', "Notify on:"); +define('FILTER_GROUP', "Group:"); +define('FILTER_USERNAME', "Username:"); +define('FILTER_NAME', "Name:"); +define('FILTER_MAIL', "Mail:"); +define('FILTER_RESET_TITLE', "Reset"); +define('FILTER_APPLY_FILTER_TITLE', "Apply Filter"); +define('FILTER_ALL', "--- All ---"); +define('FILTER_NONE', "---"); +define('FILTER_LOCKED', "Locked"); +define('FILTER_RUNNING', "Running"); +define('FILTER_WAIT', "Wait"); +define('FILTER_SUCCESS', "Success"); +define('FILTER_ERROR', "Error"); +define('FILTER_START', "Start"); +define('FILTER_END', "End"); +define('FILTER_WORKFLOW', "Workflow:"); +define('FIELD_SYSTEM', "System"); +define('FIELD_DATABASE', "Database(s)"); +define('FIELD_DATABASE_ONLY', "Database"); +define('FIELD_HOSTNAME', "Host"); +define('FIELD_IP', "Hostname/IP Address"); +define('FIELD_SYSTEM_HOST', "System/Host"); +define('FIELD_PASSWORD', "Password"); +define('FIELD_CONFIRM_PASSWORD', "Confirm password"); +define('FIELD_OLD_PASSWORD', "Old password"); +define('FIELD_LABEL_IDENTITY', "Label identity"); +define('FIELD_USERNAME', "Username"); +define('FIELD_IDENTITY', "Identity"); +define('FIELD_SHARE', "Share"); +define('FIELD_SHARED_SYSTEM', "Shared with System(s)"); +define('FIELD_LABEL', "Label"); +define('FIELD_DB_NAME_SID', "DB name/SID"); +define('FIELD_PORT', "Port"); +define('FIELD_DBMS', DBMS); +define('FIELD_ADD_HOST', "Add Host"); +define('FIELD_SELECT_SYSTEM', "--- System ---"); +define('FIELD_SELECT_HOST', "--- Host ---"); +define('FIELD_SELECT_DB', "--- DB ---"); +define('FIELD_SELECT_NONE', "---"); +define('FIELD_SELECT_CATEGORY', "--- Category ---"); +define('FIELD_SELECT_JOB', "--- Job ---"); +define('FIELD_SELECT_NOTIFICATION', "--- Notification ---"); +define('FIELD_SELECT_WORKFLOW', "--- Workflow ---"); +define('FIELD_SELECT_LABEL', "--- Label ---"); +define('FIELD_SELECT_ADD_A_STEP', "--- Add ---"); +define('FIELD_SELECT_STEP', "--- Step ---"); +define('FIELD_JOB', "Job Name"); +define('FIELD_JOB_STATUS', "Status"); +define('FIELD_LAST_JOB_RESULT', "Last result"); +define('FIELD_LAST_EXEC_TIME', "Last execution"); +define('FIELD_NEXT_EXEC_TIME', "Next execution"); +define('FIELD_JOB_PROPERTIES', "Properties"); +define('FIELD_JOB_DESCRIPTION', "Description"); +define('FIELD_JOB_PRIORITY', "Priority (1 - 100)"); +define('FIELD_JOB_PRIORITY_DETAILS', "Priority"); +define('FIELD_JOB_MAX_ATTEMPT', "Max check attempts on job failure"); +define('FIELD_JOB_DELAY', "Retry delay for this job (seconds)"); +define('FIELD_SYSTEM_HOST_DB', "System/Host/Database"); +define('FIELD_JOB_TYPE', "Job Type"); +define('FIELD_NOTIFY_TYPE', "Notify Type"); +define('FIELD_NOTIFY_JOB_ERROR', "Error"); +define('FIELD_NOTIFY_JOB_SUCCESS', "Success"); +define('FIELD_NOTIFY_JOB_END', "End"); +define('FIELD_NOTIFY_JOB_START', "Start"); +define('FIELD_NOTIFY_SEND_ON', "Notification on job"); +define('FIELD_NOTIFY_METHOD', "Notification method"); +define('FIELD_NOTIFY_DESCRIPTION', "Description"); +define('FIELD_JOB_SCHEDULE', "Schedule"); +define('FIELD_JOB_SCHEDULE_EVERY_5', "Every 5"); +define('FIELD_JOB_SCHEDULE_EVERY_15', "Every 15"); +define('FIELD_JOB_SCHEDULE_EVERY_30', "Every 30"); +define('FIELD_JOB_SCHEDULE_EVERY_6', "Every 6"); +define('FIELD_JOB_SCHEDULE_EVERY_12', "Every 12"); +define('FIELD_JOB_SCHEDULE_EVERY_MIN', "Every minute"); +define('FIELD_JOB_SCHEDULE_EVERY_5_MIN', "Every 5 minutes"); +define('FIELD_JOB_SCHEDULE_EVERY_15_MIN', "Every 15 minutes"); +define('FIELD_JOB_SCHEDULE_EVERY_30_MIN', "Every 30 minutes"); +define('FIELD_JOB_SCHEDULE_CUSTOM', "Custom"); +define('FIELD_JOB_SCHEDULE_EVERY_HOUR', "Every hour"); +define('FIELD_JOB_SCHEDULE_EVERY_6_HOUR', "Every 6 hours"); +define('FIELD_JOB_SCHEDULE_EVERY_12_HOUR', "Every 12 hours"); +define('FIELD_JOB_SCHEDULE_EVERY_DAY', "Every day"); +define('FIELD_JOB_SCHEDULE_EVERY_MONTH', "Every month"); +define('FIELD_JOB_SCHEDULE_EVERY_DAY_OF_WEEK', "Every day of week"); +define('FIELD_JOB_SCHEDULE_SUNDAY', "Sunday"); +define('FIELD_JOB_SCHEDULE_MONDAY', "Monday"); +define('FIELD_JOB_SCHEDULE_TUESDAY', "Tuesday"); +define('FIELD_JOB_SCHEDULE_WEDNEDAY', "Wednesday"); +define('FIELD_JOB_SCHEDULE_THURSDAY', "Thursday"); +define('FIELD_JOB_SCHEDULE_FRIDAY', "Friday"); +define('FIELD_JOB_SCHEDULE_SATURDAY', "Saturday"); +define('FIELD_JOB_SCHEDULE_ENABLE', "Enabled"); +define('FIELD_JOB_SCHEDULE_ENABLE_WORKFLOW', "Enabled only for workflow"); +define('FIELD_JOB_SCHEDULE_ENABLE_JOB', "Enabled only for job"); +define('FIELD_JOB_SCHEDULE_DISABLE', "Disabled"); +define('FIELD_JOB_SCHEDULE_MINUTE', "Minutes"); +define('FIELD_JOB_SCHEDULE_HOUR', "Hour"); +define('FIELD_JOB_SCHEDULE_DAY_OF_MONTH', "Day of Month"); +define('FIELD_JOB_SCHEDULE_MONTH_OF_YEAR', "Month of year"); +define('FIELD_JOB_SCHEDULE_DAY_OF_WEEK', "Day of week"); +define('FIELD_JOB_SCHEDULE_MANUAL', "Manual"); +define('FIELD_USER', "User"); +define('FIELD_USER_NAME', "Name"); +define('FIELD_USER_MAIL', "Email"); +define('FIELD_USER_GROUP', "Groups"); +define('FIELD_USER_ID', "User ID"); +define('FIELD_USER_ACTION', "Action"); +define('FIELD_USER_COMPLETE_NAME', "Complete name"); +define('FIELD_USER_FIND_ON_LDAP', "Find a user in LDAP"); +define('FIELD_USER_SEARCH_FOR', "Search for"); +define('FIELD_USER_SEARCH_STRING', "String to search"); +define('FIELD_USER_LANG', "Language"); +define('FIELD_USER_AVAILABLE_GROUPS', "Available groups"); +define('FIELD_USER_MEMBER_GROUPS', "Member groups"); +define('FIELD_GROUP', "Group"); +define('FIELD_ROLE', "Role"); +define('FIELD_SYSTEMS', "System(s)"); +define('FIELD_GROUP_NAME', "Group Name"); +define('FIELD_CATEGORY', "Category"); +define('FIELD_PLUGIN', "Plugin"); +define('FIELD_VERSION', "Version"); +define('FIELD_AUTHOR', "Author(s)"); +define('FIELD_DESCRIPTION', "Description"); +define('FIELD_WORKFLOW', "Workflow"); +define('FIELD_WORKFLOW_STATUS', "Status"); +define('FIELD_WORKFLOW_STEP', "Step"); +define('FIELD_WORKFLOW_JOB_TO_EXEC', "Job to execute"); +define('FIELD_WORKFLOW_STEP_TO_EXEC', "Step to execute"); +define('FIELD_WORKFLOW_STEP_ERROR', "On error go to step"); +define('FIELD_WORKFLOW_STEP_SUCCESS', "On success go to step"); +define('FIELD_UPLOAD_FILE', "File to upload"); +define('FIELD_FILE_MANAGER', "File manager"); +define('TOOLTIP_WAIT_FOR_EXEC', "Waiting for execution"); +define('TOOLTIP_RUNNING', "Running"); +define('TOOLTIP_LOCKED', "Locked"); +define('TOOLTIP_JOB_RESULT', "Job Result"); +define('TOOLTIP_JOB_DESCRIPTION', "Job Description"); +define('TOOLTIP_NOTIFICATION_DETAILS', "Notification details"); +define('TOOLTIP_IDENTITY_PICKER', "Identity Selector"); +define('TOOLTIP_PLUGIN_DESCRIPTION', "Plugin Description"); +define('TOOLTIP_WORKFLOW_DESCRIPTION', "Workflow Description"); +define('TOOLTIP_SUCCESS', "Success"); +define('TOOLTIP_ERROR', "Error"); +define('TOOLTIP_STEP_EXEC_IMMEDIATE', "Immediately execute the selected step"); +define('TOOLTIP_STEP_WAIT_FOR_SCHED', "Execute the selected step as scheduled in the Job settings"); +define('MSG_SYSTEM_NAME_REQUIRED', "System Name is required"); +define('MSG_HOST_NAME_REQUIRED', "Host is required"); +define('MSG_IP_REQUIRED', "Hostname/IP address is required"); +define('MSG_SELECT_A_SYSTEM', "Please select a system"); +define('MSG_SELECT_A_HOST', "Please select a host"); +define('MSG_LABEL_REQUIRED', "Label is required"); +define('MSG_SID_REQUIRED', "SID is required"); +define('MSG_PORT_REQUIRED', "Port is required"); +define('MSG_PORT_IS_A_NUMBER', "Port must be a number"); +define('MSG_USERNAME_REQUIRED', "Username is required"); +define('MSG_PASSWORD_NOT_MATCH', "The passwords do not match"); +define('MSG_PASSWORD_REQUIRED', "Password is required"); +define('MSG_PASSWORD_MIN_CHAR', "The password must be at least six chars."); +define('MSG_PRIORITY_REQUIRED', "Priority is required"); +define('MSG_PRIORITY_HAS_VALUE', "Priority has a value between 0 - 100"); +define('MSG_MAX_CHECK_ATTEMPT_IS_NUMERIC', "Max check attempts must be numeric (Leave 0 to disable)"); +define('MSG_MAX_CHECK_ATTEMPT_REQUIRED', "Max check attempts is required (Leave 0 to disable)"); +define('MSG_MAX_DELAY_IS_NUMERIC', "Retry delay must be numeric (Leave 0 to disable)"); +define('MSG_MAX_DELAY_REQUIRED', "Retry delay is required (Leave 0 to disable)"); +define('MSG_SELECT_A_JOB_TYPE', "Please select a job type"); +define('MSG_SELECT_A_NOTIFICATION_TYPE', "Please select a notification method"); +define('MSG_SELECT_A_NOTIFICATION_ON', "Please select a notification event"); +define('MSG_SELECT_A_VALUE_FOR_MINUTE', "Select a value for minute"); +define('MSG_SELECT_A_VALUE_FOR_HOUR', "Select a value for hour"); +define('MSG_SELECT_A_VALUE_FOR_DAY', "Select a value for day"); +define('MSG_SELECT_A_VALUE_FOR_MONTH', "Select a value for month"); +define('MSG_SELECT_A_VALUE_FOR_DAY_OF_WEEK', "Select a value for day of week"); +define('MSG_LDAP_CONNECTION_FAILED', "Connection to LDAP server failed!
Please contact system administrator."); +define('MSG_LDAP_NO_MATCH_FOUND', "No match found!"); +define('MSG_LDAP_NOT_ENABLED', "ldap module for PHP not enabled."); +define('MSG_COMPLETE_NAME_REQUIRED', "Complete name is required"); +define('MSG_MAIL_REQUIRED', "Mail is required"); +define('MSG_MAIL_NOT_VALID', "Mail format is not valid"); +define('MSG_SEARCH_FIELD_REQUIRED', "Search field is required"); +define('MSG_GROUP_NAME_REQUIRED', "Group name is required"); +define('MSG_AUTHENTICATION_FAILED', "Authentication failed!"); +define('MSG_PLUGIN_NO_FURTHER_CONFIGURATION', "This plugin does not have any global configuration."); +define('MSG_SELECT_A_VALUE_FOR_GROUP', "Please select a group"); +define('MSG_ADD_WORKFLOW_JOB_IS_REQUIRED', "Please select a job to continue."); +define('MSG_SELECT_A_WORKFLOW_OR_JOB', "Please select a workflow or job to execute"); +define('MSG_SELECT_A_FILE', "Please select a file"); +define('MSG_SELECT_A_VALUE_FOR_SYSTEM', "Please select a system"); +define('DISPLAY_REPORTS_TOP', "Below is the list of all archived reports"); +define('MSG_REPORTS_NOT_AVAILABLE', "Reports are not available."); +define('MSG_DOWNLOAD', "Download"); +define('BUTTON_ORDER_BY_FILENAME', "Filename"); +define('BUTTON_ORDER_BY_DATE', "Date"); +define('BUTTON_ORDER_BY_SIZE', "Size"); +define('DISPLAY_ARCHIVED_RESULTS_TOP', "Below is the list of all archived results for"); +define('MSG_ARCHIVED_RESULTS_NOT_AVAILABLE', "There are no results archived for"); +define('MSG_JOB_ARCHIVED_RESULT', "Result"); +define('MSG_JOB_ARCHIVED_EXIT_CODE', "Exit code"); +define('MSG_JOB_ARCHIVED_START_EXEC', "Start execution time"); +define('MSG_JOB_ARCHIVED_END_EXEC', "End execution time"); +define('MSG_FILES_NOT_FOUNDS', "Actually there are no files stored for the system:"); +define('MSG_PAGE_NOT_FOUND', "Page not found."); +define('FIELD_OVERWRITE_EXISTING_DB', "Overwrite existing database"); +define('FIELD_DATABASE_ALREADY_EXISTS', "Specified database name is already in use.
But the configuration files are imported.
Click on link: Check/Edit."); +define('IMPORT_EXPORT_TOP', "Import and Export Tool"); +define('IMPORT_EXPORT_TITLE', "Use the form below to import/export the Ortro settings."); +define('FIELD_IMPORT_SUBMIT', "Import"); +define('FIELD_EXPORT_SUBMIT', "Export"); +define('FIELD_EXPORT_DESCRIPTION', "Export the Ortro settings"); +define('FIELD_EXPORT_SUB_DESCRIPTION', "Backup the database and the configuration files (tar.gz)"); +define('FIELD_IMPORT_DESCRIPTION', "Import the Ortro settings"); +define('FIELD_IMPORT_SUB_DESCRIPTION', "Select a previous backup to restore."); +define('FIELD_IMPORT_SUCCESS', "Import done with success.
Please check the configure.php file. The old configuration files should be stored under the conf/backup directory.
Click on link: Check/Edit."); +define('FIELD_EXPORT_SUCCESS', "Export done with success"); +define('FIELD_EXPORT_ERROR', "Export failed, the backup file is corrupted"); +define('FIELD_IMPORT_DB_NOT_SUPPORTED', "Sorry. This functionality is not avalible for your database type."); +define('FIELD_CHECK_NEW_SETTINGS_DESCRIPTION', "It's important check and modify the new configuration data."); +define('FIELD_CHECK_NEW_SETTINGS_LINK', "Check/Edit data"); +define('AUTODISCOVERY_TOP', "Autodiscovery: scan"); +define('AUTODISCOVERY_TITLE', "Use this tool to autodiscovery the Hosts in your network and successively add them to a System."); +define('FIELD_AUTODISCOVERY', "Autodiscovery"); +define('FIELD_NMAP_TARGET', "Target specification: can pass hostnames, IP addresses, networks, etc. separated by space
Ex: scanme.example.org example.com/24 192.168.0.1 10.0.0-255.1-254"); +define('FIELD_AUTODISCOVERY_OS_DETECTION', "Enable detailed OS detection."); +define('FIELD_NMAP_BINARY', "Nmap binary path:"); +define('BUTTON_SCAN', "Scan"); +define('MSG_TARGET_REQUIRED', "Target specification is required"); +define('MSG_NMAP_BINARY_REQUIRED', "Nmap binary is required"); +define('FAILED_TO_RESOLVE', "Failed to resolve given hostname/IP:"); +define('AUTODISCOVERY_ADD_TOP', "Autodiscovery: add"); +define('AUTODISCOVERY_ADD_TITLE', "Use the form below to add the Hosts to a System."); +define('FIELD_OS_DETAILS', "Operative System"); +define('YES', "Yes"); +define('NO', "No"); +define('ASK', "Ask"); +define('DISABLE', "Disable"); +define('ENABLE', "Enable"); +define('CALENDAR_TOP', "Calendars: view"); +define('CALENDAR_TITLE', "Below is the list of Calendars configured in this Ortro installation.
Calendars are used to customize job schedule."); +define('CALENDAR_ADD_TOP', "Calendars: add"); +define('CALENDAR_ADD_TITLE', "Use the form below to add a Calendar."); +define('CALENDAR_EDIT_TOP', "Calendars: edit"); +define('CALENDAR_EDIT_TITLE', "Use the form below to edit the Calendar label."); +define('CALENDAR_LABEL', "Calendar"); +define('CALENDAR_SHARE_WITH', "Select the System(s) that are to share this Calendar:"); +define('MSG_CALENDAR_REQUIRED', "Calendar is required"); +?> \ No newline at end of file diff --git a/lang/en/template/configure_metadata_install.php b/lang/en/template/configure_metadata_install.php new file mode 100644 index 0000000..d278c2d --- /dev/null +++ b/lang/en/template/configure_metadata_install.php @@ -0,0 +1,60 @@ +On connecting with ssh, should Ortro ignore errors with a remote host's key,
die immediately, or ask the user if it should continue? (Default: no)"); +define('CONF_INSTALL_ENV_LOG_LEVEL_DEBUG', DEBUG); +define('CONF_INSTALL_ENV_LOG_LEVEL_INFO', INFO); +define('CONF_INSTALL_ENV_LOG_LEVEL_ERROR', ERROR); +define('CONF_INSTALL_ENV_LOG_LEVEL_DESCRIPTION', "Log trace level: DEBUG logs most, ERROR logs least"); +define('CONF_INSTALL_ENV_ZIP_PATH_DESCRIPTION', "Absolute path to the zip executable - default /usr/bin/zip"); +define('CONF_INSTALL_ENV_ZIP_THRESHOLD_DESCRIPTION', "Maximum allowable size of zip archive file (bytes)"); +define('CONF_INSTALL_ENV_DATEFORMAT_DESCRIPTION', "Date format"); +define('CONF_INSTALL_DATEFORMAT_RULE_1_0', "The Date format is required"); +define('CONF_INSTALL_ENV_TIMEFORMAT_DESCRIPTION', "Time format"); +define('CONF_INSTALL_ENV_DATEFORMAT_RULE_1_0', "The Date format is required"); +define('CONF_INSTALL_XMLRPC_DESCRIPTION', "XML-RPC services configuration"); +define('CONF_INSTALL_XMLRPC_TIMEOUT_DESCRIPTION', "Session timeout (seconds)"); +define('CONF_INSTALL_XMLRPC_TIMEOUT_RULE_1_0', "The session timeout is required"); +define('CONF_INSTALL_AUTH_DESCRIPTION',"Ortro Authentication settings"); +define('CONF_INSTALL_AUTH_DEFAULT_DESCRIPTION',"Default authentication method"); +define('CONF_INSTALL_AUTH_FALLBACK_DESCRIPTION',"Fallback authentication"); +define('CONF_INSTALL_ENV_JOB_TIMEOUT_DESCRIPTION', "Timeout value for jobs (minutes). Leave 0 to disable"); +define('CONF_INSTALL_ENV_JOB_TIMEOUT_RULE_1_0', "The job timeout is required"); +?> \ No newline at end of file diff --git a/lang/en/template/configure_metadata_ldap.php b/lang/en/template/configure_metadata_ldap.php new file mode 100644 index 0000000..6e1093b --- /dev/null +++ b/lang/en/template/configure_metadata_ldap.php @@ -0,0 +1,19 @@ +(leave blank for anonymous bind). e.g. cn=ldap_search_user,dc=example,dc=com"); +define('CONF_LDAP_BIND_PASSWORD_DESCRIPTION', "Bind Password: password for above LDAP search user
(leave blank for anonymous bind)"); +define('CONF_LDAP_SEARCH_ATTRIBUTE_UID_DESCRIPTION', "User login attribute, e.g. uid or sAMAccountName"); +define('CONF_LDAP_SEARCH_ATTRIBUTE_CN_DESCRIPTION', "User full name attribute, e.g. cn"); +define('CONF_LDAP_SEARCH_ATTRIBUTE_MAIL_DESCRIPTION', "User email address attribute, e.g. mail"); + +?> \ No newline at end of file diff --git a/lang/en/template/install.php b/lang/en/template/install.php new file mode 100644 index 0000000..1258025 --- /dev/null +++ b/lang/en/template/install.php @@ -0,0 +1,64 @@ +for job scheduling and system/application monitoring."); +define('INSTALL_CRONTAB_MSG_PART_1', "Add the line below to the crontab for the"); +define('INSTALL_CRONTAB_MSG_PART_2', "user:"); +define('INSTALL_CRONTAB_MSG_PART_3', "Click on the 'Edit crontab' button to add it automatically in the crontab now.
A copy of the current crontab will be saved in:"); +define('INSTALL_CRONTAB_NEW', "New crontab:"); +define('INSTALL_CRONTAB_OLD', "Old crontab:"); +define('INSTALL_CRONTAB_TITLE', "Add Ortro entry to crontab"); +define('INSTALL_EXTENSIONS', "PHP Extensions"); +define('INSTALL_EXTENSIONS_ALERT', "Not found extensions:"); +define('INSTALL_FILE_PERMISSION', "File Permission"); +define('INSTALL_FINISH_MSG_PART_1', "Ortro successfully installed!"); +define('INSTALL_FINISH_MSG_PART_2', "Now you can "); +define('INSTALL_FINISH_MSG_PART_3', "log in"); +define('INSTALL_FINISH_MSG_PART_4', " with username admin, password admin"); +define('INSTALL_FINISH_MSG_PART_5', "For security reasons do not forget to remove the installation directory:"); +define('INSTALL_HOW_DESCRIPTION', "To begin the installation of Ortro, please select your language and click on the 'Next' button"); +define('INSTALL_LICENSE', "GNU/GPL License:"); +define('INSTALL_MENU_CRONTAB', "Crontab"); +define('INSTALL_MENU_DATABASE', "Database"); +define('INSTALL_MENU_FINISH', "Finish"); +define('INSTALL_MENU_LICENSE', "License"); +define('INSTALL_MENU_PLUGINS', "Plugins"); +define('INSTALL_MENU_PRE_INSTALL_CHECK', "Pre-Installation Check"); +define('INSTALL_MENU_SSH', SSH); +define('INSTALL_MENU_TITLE', "Installation steps"); +define('INSTALL_MENU_WELCOME', "Welcome"); +define('INSTALL_MSG_ACTION_CONFIGURE_FILE_NOT_FOUND', "configure.php not found in"); +define('INSTALL_MSG_DB_CREATED_WITH_SUCCESS', "Database successfully created"); +define('INSTALL_MSG_INSTALL_OK', "The plugins listed below have been successfully installed:"); +define('INSTALL_MSG_NO_PLUGIN_TO_INSTALL', "There are no plugins to install."); +define('INSTALL_MSG_PLUGIN_FURTHER_CONFIGURATION', "The plugins listed below require further configuration. After login please configure them before use."); +define('INSTALL_PHP', PHP); +define('INSTALL_PHP_CLI_PATH', "PHP-cli absolute path:"); +define('INSTALL_PHP_CLI_VERSION', "PHP-cli version >= 5.1.0"); +define('INSTALL_PHP_VERSION', "PHP version >= 5.1.0"); +define('INSTALL_PLUGIN_NAME', "Name"); +define('INSTALL_PLUGIN_VERSION', "Version"); +define('INSTALL_RDBMS', "Databases Supported"); +define('INSTALL_RDBMS_ALERT', "It appears your PHP installation does not support any databases. Please install at least one PHP database module and try again."); +define('INSTALL_SSH', SSH); +define('INSTALL_SSH_CLIENT', "SSH client"); +define('INSTALL_SSH_CLIENT_PATH', "SSH client absolute path:"); +define('INSTALL_SSH_TITLE', "Generate SSH public/private key pair"); +define('INSTALL_WELCOME_DESCRIPTION', "Welcome to Ortro"); +define('INSTALL_WRITE_PERMISSION', "is writable"); +define('UPGRADE_CONFIGURE_NOT_FOUND', "configure.php not found!!!"); +define('UPGRADE_DB_SCHEMA', "Upgrading database..."); +define('UPGRADE_ERROR', "ERROR:"); +define('UPGRADE_JS', "Upgrading javascript files..."); +define('UPGRADE_PLUGINS', "Upgrading plugins..."); +define('UPGRADE_REMOVE_INSTALL_DIR', "Deleting installation directory..."); + +?> \ No newline at end of file diff --git a/lang/en/template/menu.php b/lang/en/template/menu.php new file mode 100644 index 0000000..547a8a8 --- /dev/null +++ b/lang/en/template/menu.php @@ -0,0 +1,49 @@ + \ No newline at end of file diff --git a/lang/en/template/plugin_common.php b/lang/en/template/plugin_common.php new file mode 100644 index 0000000..ce95edc --- /dev/null +++ b/lang/en/template/plugin_common.php @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/lang/fr/js/js.php b/lang/fr/js/js.php new file mode 100644 index 0000000..b229516 --- /dev/null +++ b/lang/fr/js/js.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/database/check_tablespace/language.php b/lang/fr/plugins/database/check_tablespace/language.php new file mode 100644 index 0000000..e28ca06 --- /dev/null +++ b/lang/fr/plugins/database/check_tablespace/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/database/custom_query/language.php b/lang/fr/plugins/database/custom_query/language.php new file mode 100644 index 0000000..14e3c32 --- /dev/null +++ b/lang/fr/plugins/database/custom_query/language.php @@ -0,0 +1,17 @@ +En cas d'égalité, un code de retour de succès ou d'erreur est renvoyé en fonction de la case à cocher 'Si le test est vrai, alors renvoyer'"); +define('PLUGIN_DB_CUSTOM_QUERY_ERROR', "Erreur"); +define('PLUGIN_DB_CUSTOM_QUERY_ERROR_DESCRIPTION', "Si le test est vrai, alors renvoyer"); +define('PLUGIN_DB_CUSTOM_QUERY_OPERATOR_DESCRIPTION', "Opérateur"); +define('PLUGIN_DB_CUSTOM_QUERY_RULE_4_0', "Le seuil est obligatoire."); +define('PLUGIN_DB_CUSTOM_QUERY_SUCCESS', "Succès"); +define('PLUGIN_DB_CUSTOM_QUERY_THRESHOLD_DESCRIPTION', "Seuil"); +define('PLUGIN_DB_CUSTOM_QUERY_TITLE', "Requête personnalisée sur une base de données"); + +?> \ No newline at end of file diff --git a/lang/fr/plugins/database/custom_query_report/language.php b/lang/fr/plugins/database/custom_query_report/language.php new file mode 100644 index 0000000..cf1484c --- /dev/null +++ b/lang/fr/plugins/database/custom_query_report/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/database/execute_sql_from_file/language.php b/lang/fr/plugins/database/execute_sql_from_file/language.php new file mode 100644 index 0000000..7389557 --- /dev/null +++ b/lang/fr/plugins/database/execute_sql_from_file/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/database/mysql_table_check/language.php b/lang/fr/plugins/database/mysql_table_check/language.php new file mode 100644 index 0000000..a59bdc6 --- /dev/null +++ b/lang/fr/plugins/database/mysql_table_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/database/oracle_freespa_report/language.php b/lang/fr/plugins/database/oracle_freespa_report/language.php new file mode 100644 index 0000000..fc39e1e --- /dev/null +++ b/lang/fr/plugins/database/oracle_freespa_report/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/database/oracle_session_report/language.php b/lang/fr/plugins/database/oracle_session_report/language.php new file mode 100644 index 0000000..c464374 --- /dev/null +++ b/lang/fr/plugins/database/oracle_session_report/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/check_tail_status/language.php b/lang/fr/plugins/file/check_tail_status/language.php new file mode 100644 index 0000000..175d2b2 --- /dev/null +++ b/lang/fr/plugins/file/check_tail_status/language.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/create/language.php b/lang/fr/plugins/file/create/language.php new file mode 100644 index 0000000..5217322 --- /dev/null +++ b/lang/fr/plugins/file/create/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/ftp_upload/language.php b/lang/fr/plugins/file/ftp_upload/language.php new file mode 100644 index 0000000..d55b628 --- /dev/null +++ b/lang/fr/plugins/file/ftp_upload/language.php @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/read_file/language.php b/lang/fr/plugins/file/read_file/language.php new file mode 100644 index 0000000..f221868 --- /dev/null +++ b/lang/fr/plugins/file/read_file/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/retention/language.php b/lang/fr/plugins/file/retention/language.php new file mode 100644 index 0000000..7fe067c --- /dev/null +++ b/lang/fr/plugins/file/retention/language.php @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/search/language.php b/lang/fr/plugins/file/search/language.php new file mode 100644 index 0000000..32c896b --- /dev/null +++ b/lang/fr/plugins/file/search/language.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/file/size_check/language.php b/lang/fr/plugins/file/size_check/language.php new file mode 100644 index 0000000..aeaff1d --- /dev/null +++ b/lang/fr/plugins/file/size_check/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/general/custom_script/language.php b/lang/fr/plugins/general/custom_script/language.php new file mode 100644 index 0000000..8330082 --- /dev/null +++ b/lang/fr/plugins/general/custom_script/language.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/general/spreadsheet_to_db/language.php b/lang/fr/plugins/general/spreadsheet_to_db/language.php new file mode 100644 index 0000000..5eb3088 --- /dev/null +++ b/lang/fr/plugins/general/spreadsheet_to_db/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/general/telnet_custom_script/language.php b/lang/fr/plugins/general/telnet_custom_script/language.php new file mode 100644 index 0000000..f3e6caf --- /dev/null +++ b/lang/fr/plugins/general/telnet_custom_script/language.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/general/windows_remote_execution/language.php b/lang/fr/plugins/general/windows_remote_execution/language.php new file mode 100644 index 0000000..dcd4394 --- /dev/null +++ b/lang/fr/plugins/general/windows_remote_execution/language.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/notification/jabber/language.php b/lang/fr/plugins/notification/jabber/language.php new file mode 100644 index 0000000..e9dd224 --- /dev/null +++ b/lang/fr/plugins/notification/jabber/language.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/notification/mail/language.php b/lang/fr/plugins/notification/mail/language.php new file mode 100644 index 0000000..19ee1d6 --- /dev/null +++ b/lang/fr/plugins/notification/mail/language.php @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/notification/sms_ftp/language.php b/lang/fr/plugins/notification/sms_ftp/language.php new file mode 100644 index 0000000..f61b705 --- /dev/null +++ b/lang/fr/plugins/notification/sms_ftp/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/notification/tibco_rvd/language.php b/lang/fr/plugins/notification/tibco_rvd/language.php new file mode 100644 index 0000000..1a686b7 --- /dev/null +++ b/lang/fr/plugins/notification/tibco_rvd/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/notification/tivoli_postemsg/language.php b/lang/fr/plugins/notification/tivoli_postemsg/language.php new file mode 100644 index 0000000..bb7f86d --- /dev/null +++ b/lang/fr/plugins/notification/tivoli_postemsg/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/check_glance_status/language.php b/lang/fr/plugins/system/check_glance_status/language.php new file mode 100644 index 0000000..b303bf8 --- /dev/null +++ b/lang/fr/plugins/system/check_glance_status/language.php @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/cpu_idle/language.php b/lang/fr/plugins/system/cpu_idle/language.php new file mode 100644 index 0000000..07d7f9d --- /dev/null +++ b/lang/fr/plugins/system/cpu_idle/language.php @@ -0,0 +1,13 @@ +Note: une valeur basse pour la charge signifie que le serveur est plus occupé."); +define('PLUGIN_CPU_IDLE_RULE_3_0', "Le seuil est obligatoire"); +define('PLUGIN_CPU_IDLE_THRESHOLD_DESCRIPTION', "Seuil"); +define('PLUGIN_CPU_IDLE_TITLE', "Temps CPU Libre"); + +?> \ No newline at end of file diff --git a/lang/fr/plugins/system/file_system_check/language.php b/lang/fr/plugins/system/file_system_check/language.php new file mode 100644 index 0000000..b4b05ea --- /dev/null +++ b/lang/fr/plugins/system/file_system_check/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/mem_free/language.php b/lang/fr/plugins/system/mem_free/language.php new file mode 100644 index 0000000..6d1d766 --- /dev/null +++ b/lang/fr/plugins/system/mem_free/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/ping/language.php b/lang/fr/plugins/system/ping/language.php new file mode 100644 index 0000000..03c20c3 --- /dev/null +++ b/lang/fr/plugins/system/ping/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/service_check/language.php b/lang/fr/plugins/system/service_check/language.php new file mode 100644 index 0000000..aa2a6a9 --- /dev/null +++ b/lang/fr/plugins/system/service_check/language.php @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/solaris_metadevice_check/language.php b/lang/fr/plugins/system/solaris_metadevice_check/language.php new file mode 100644 index 0000000..64ba95f --- /dev/null +++ b/lang/fr/plugins/system/solaris_metadevice_check/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/solaris_svc_check/language.php b/lang/fr/plugins/system/solaris_svc_check/language.php new file mode 100644 index 0000000..5a0ce53 --- /dev/null +++ b/lang/fr/plugins/system/solaris_svc_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/solaris_zfs_scrub_check/language.php b/lang/fr/plugins/system/solaris_zfs_scrub_check/language.php new file mode 100644 index 0000000..f9eb4c2 --- /dev/null +++ b/lang/fr/plugins/system/solaris_zfs_scrub_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/system/solaris_zpool_check/language.php b/lang/fr/plugins/system/solaris_zpool_check/language.php new file mode 100644 index 0000000..a0ebf6f --- /dev/null +++ b/lang/fr/plugins/system/solaris_zpool_check/language.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/www/check_uri_response_code/language.php b/lang/fr/plugins/www/check_uri_response_code/language.php new file mode 100644 index 0000000..fe5ad1a --- /dev/null +++ b/lang/fr/plugins/www/check_uri_response_code/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/www/http_download_file/language.php b/lang/fr/plugins/www/http_download_file/language.php new file mode 100644 index 0000000..f7bf2dd --- /dev/null +++ b/lang/fr/plugins/www/http_download_file/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/www/testgen4web_simpletest/language.php b/lang/fr/plugins/www/testgen4web_simpletest/language.php new file mode 100644 index 0000000..37cc872 --- /dev/null +++ b/lang/fr/plugins/www/testgen4web_simpletest/language.php @@ -0,0 +1,22 @@ +Remplacer dans le code le nom de l'utilisateur et le mot de passe avec ceux de l'identité et"); +define('PLUGIN_TEST4WEB_RULE_5_0', "Le XML est obligatoire."); +define('PLUGIN_TEST4WEB_TYPE', "Sélectionner le résultat à fournir"); +define('PLUGIN_TEST4WEB_DETAILS', "Rapport détailler"); +define('PLUGIN_TEST4WEB_ONLY_TIME', "Seulement le temps d'exécution"); +define('PLUGIN_TEST4WEB_THRESHOLD_DESCRIPTION', "Délai pour le test de navigation en secondes (laisser à 0 pour le temps maximum)"); +define('PLUGIN_TEST4WEB_RULE_7_0', "Le délai est obligatoire."); +define('PLUGIN_TEST4WEB_RULE_7_1', "Le délai doit être un nombre."); + +?> \ No newline at end of file diff --git a/lang/fr/plugins/www/webservice_soapui/language.php b/lang/fr/plugins/www/webservice_soapui/language.php new file mode 100644 index 0000000..f8018a4 --- /dev/null +++ b/lang/fr/plugins/www/webservice_soapui/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/fr/plugins/www/webtest_selenium/language.php b/lang/fr/plugins/www/webtest_selenium/language.php new file mode 100644 index 0000000..4e5b1e7 --- /dev/null +++ b/lang/fr/plugins/www/webtest_selenium/language.php @@ -0,0 +1,18 @@ +Remplacer dans le code le nom de l'utilisateur et le mot de passe avec ceux de l'identité et"); +define('PLUGIN_WEBTEST_SELENIUM_RULE_3_0', "Le code du script est obligatoire."); + +?> \ No newline at end of file diff --git a/lang/fr/plugins/www/webtest_slimdog/language.php b/lang/fr/plugins/www/webtest_slimdog/language.php new file mode 100644 index 0000000..1b015a1 --- /dev/null +++ b/lang/fr/plugins/www/webtest_slimdog/language.php @@ -0,0 +1,15 @@ +Remplacer dans le code le nom de l'utilisateur et le mot de passe avec ceux de l'identité et"); +define('PLUGIN_WEBTEST_SLIMDOG_DESCRIPTION', "Permettre le test d'un serveur Web en utilisant Slimdog"); +define('PLUGIN_WEBTEST_SLIMDOG_METADATA_JAVA_PATH_DESCRIPTION', "Chemin absolu sur l'exécutable Java"); +define('PLUGIN_WEBTEST_SLIMDOG_METADATA_SLIMDOG_PATH_DESCRIPTION', "Chemin absolu sur les librairies Slimdog"); +define('PLUGIN_WEBTEST_SLIMDOG_RULE_2_0', "Le code du script est obligatoire."); +define('PLUGIN_WEBTEST_SLIMDOG_TITLE', "Tester un serveur Web en utilisant Slimdog"); + +?> \ No newline at end of file diff --git a/lang/fr/template/action_msg.php b/lang/fr/template/action_msg.php new file mode 100644 index 0000000..e14866b --- /dev/null +++ b/lang/fr/template/action_msg.php @@ -0,0 +1,97 @@ +La taille maximum d'un fichier téléchargé est :"); +define('MSG_ACTION_REMOVE_ALL_NOTIFICATIONS', "Vous devez d'abord supprimer toutes les méthodes de notifications."); +define('MSG_ACTION_REMOVE_IDENTITY_FIRST', "Les travaux ci-dessous sont associés avec cette identité. Supprimer d'abord les travaux."); +define('MSG_ACTION_REMOVE_JOB_FIRST', "Les travaux ci-dessous sont associés avec cette extensions de traitement. Supprimer d'abord les travaux."); +define('MSG_ACTION_REMOVE_NOTIFICATION_FIRST', "Les notifications ci-dessous sont associés avec cette extension. Supprimer d'abord les notifications."); +define('MSG_ACTION_REMOVE_USER_FIRST', "Les utilisateurs ci-dessous sont associés avec ce groupe. Supprimer d'abord les utilisateurs."); +define('MSG_ACTION_STEP_ADDED', "Etape ajoutée."); +define('MSG_ACTION_STRANGE_STATUS', "Etat inconnu. Veuillez contacter l'administrateur."); +define('MSG_ACTION_SYSTEM_ADDED', "Système ajouté."); +define('MSG_ACTION_SYSTEM_ALREADY_USED', "Ce nom de système est déjà utilisé."); +define('MSG_ACTION_SYSTEM_DELETED', "Système supprimé."); +define('MSG_ACTION_SYSTEM_HOSTNAME_ALREADY_USED', "L'association entre ce système et ce serveur existe déjà."); +define('MSG_ACTION_SYSTEM_MODIFIED', "Le nom du système a été modifié."); +define('MSG_ACTION_SYSTEM_REMOVE_JOB_FIRST', "Les travaux ci-dessous sont associés avec ce système. Supprimer d'abord les travaux."); +define('MSG_ACTION_USERNAME_ALREADY_USED', "Ce nom d'utilisateur existe déjà."); +define('MSG_ACTION_USER_ADDED', "Utilisateur ajouté."); +define('MSG_ACTION_USER_DELETED', "Utilisateur supprimé."); +define('MSG_ACTION_USER_DELETED_FROM_GROUP', "Utilisateur supprimé du groupe."); +define('MSG_ACTION_USER_IN_GROUP_ADDED', "Utilisateur ajouté au groupe."); +define('MSG_ACTION_USER_MODIFIED', "Paramètres de l'utilisateur modifiés."); +define('MSG_ACTION_WORKFLOW_ADDED', "Enchaînement ajouté."); +define('MSG_ACTION_WORKFLOW_COPIED', "Enchaînement copié."); +define('MSG_ACTION_WORKFLOW_DELETED', "Enchaînement supprimé."); +define('MSG_ACTION_WORKFLOW_EXECUTED', "Enchaînement exécuté avec succès."); +define('MSG_ACTION_WORKFLOW_IS_LOCKED', "L'enchaînement est verrouillé. Vous devez d'abord le dé-verrouillé."); +define('MSG_ACTION_WORKFLOW_IS_NOT_RUNNING', "L'enchaînement n'est pas en cours d'exécution."); +define('MSG_ACTION_WORKFLOW_KILLED', "Enchaînement abandonné."); +define('MSG_ACTION_WORKFLOW_MODIFIED', "Enchaînement modifié."); +define('MSG_ACTION_WORKFLOW_REMOVE_STEP_FIRST', "Les étapes ci-dessous sont associées avec d'autres étapes. Supprimer d'abord les étapes."); +define('MSG_ACTION_WORKFLOW_STATUS_UPDATED', "Etat de l'enchaînement mis à jour."); +define('MSG_ACTION_WORKFLOW_STEP_ADDED', "Etape ajoutée dans l'enchaînement."); +define('MSG_ACTION_WORKFLOW_STEP_DELETED', "Etape supprimée."); +define('MSG_EXECUTION_ABORTED', "Exécution interrompue."); +define('MSG_GD_LIB_NOT_ENABLED', "Impossible de créer l'image.
PHP n'est pas configuré avec la librairie GD."); +define('MSG_IDENTITY_NOT_FOUND', "Pas d'identité trouvée pour ce système."); +define('MSG_IDENTITY_PICK', "Sélectionner"); +define('MSG_LOGOUT', "Vous êtes maintenant déconnecté."); +define('MSG_PERMISSION_DENIED', "Non autorisé!!!"); +define('MSG_ACTION_SYSTEM_HOST_LOCKED',"Le système ou le serveurest verrouillé. Vous devez d'abord le dé-verrouillé."); +define('MSG_ACTION_SYSTEM_STATUS_UPDATED', "Etat du système mis à jour."); +?> \ No newline at end of file diff --git a/lang/fr/template/common.php b/lang/fr/template/common.php new file mode 100644 index 0000000..90c234c --- /dev/null +++ b/lang/fr/template/common.php @@ -0,0 +1,373 @@ +
un logiciel open source pour facilité les activités

d'ordonnancement de travaux et la supervision de systèmes / applications."); +define('JS_NOT_ENABLED', "Vous n'avez pas le javascript d'activer dans votre navigateur.
Ortro utilise le javascript et il ne fonctionnera pas correctement sans.
Veuillez autoriser l'utilisation du javascript dans votre navigateur puis recharger cette page."); +define('HEADER_PROFILE_DESCRIPTION', "Profil"); +define('HEADER_PROFILE_TOOLTIP', "Modifier votre profil"); +define('HEADER_LOGOUT', "Déconnecter"); +define('TITLE', "Ortro"); +define('ACTION_TITLE', "Actions"); +define('ACTION_LOCK_UNLOCK', "Action verrouiller/déverrouiller dans la barre d'icônes."); +define('ACTION_RELOAD_DESCRIPTION', "Recharger la page"); +define('ACTION_PREV_PAGE_DESCRIPTION', "Aller à la page précédente"); +define('ACTION_NEXT_PAGE_DESCRIPTION', "Aller à la page suivante"); +define('ACTION_EDIT_DESCRIPTION', "Editer"); +define('ACTION_DELETE_DESCRIPTION', "Supprimer"); +define('ACTION_DETAIL_DESCRIPTION', "Détails"); +define('ACTION_COPY_DESCRIPTION', "Copier"); +define('ACTION_GROUP_DESCRIPTION', "Groupes"); +define('ACTION_ADD_DESCRIPTION', "Ajouter"); +define('ACTION_LOCK_DESCRIPTION', "Verrouiller"); +define('ACTION_UNLOCK_DESCRIPTION', "Déverrouiller"); +define('ACTION_RUN_DESCRIPTION', "Exécuter"); +define('ACTION_PREV_STEP_DESCRIPTION', "Retourner à l'étape précédente"); +define('ACTION_NEXT_STEP_DESCRIPTION', "Aller à l'étape suivante"); +define('ACTION_KILL_DESCRIPTION', "Abandonner"); +define('REFRESH_TITLE', "Rafraîchir"); +define('REFRESH_MANUAL', "Manuel"); +define('REFRESH_EVERY_15', "15 sec"); +define('REFRESH_EVERY_30', "30 sec"); +define('REFRESH_EVERY_60', "60 sec"); +define('REFRESH_EVERY_180', "180 sec"); +define('BUTTON_ADD', "Ajouter"); +define('BUTTON_APPLY', "Appliquer"); +define('BUTTON_SEARCH', "Rechercher"); +define('BUTTON_ADD_IN_GROUP', "Ajouter au groupe"); +define('BUTTON_REMOVE_FROM_GROUP', "Supprimer du groupe"); +define('BUTTON_SAVE_SETTING', "Enregistrer les paramètres"); +define('BUTTON_INSTALL', "Installer"); +define('BUTTON_LOGIN', "Connexion"); +define('BUTTON_CHANGE_PASSWORD', "Modifier le mot de passe"); +define('SYSTEM_TOP', "Systèmes: Visualisation"); +define('SYSTEM_TITLE', "Liste des systèmes configurés dans cette installation d'Ortro.
Un système est un ensemble administratif qui regroupe des serveurs."); +define('SYSTEM_ADD_TOP', "Systèmes: Ajout"); +define('SYSTEM_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter un système."); +define('SYSTEM_EDIT_TOP', "Systèmes: Modification"); +define('SYSTEM_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier un système."); +define('SYSTEM_NAME', "Nom du système"); +define('DATABASES_TOP', "Base de données: Visualisation"); +define('DATABASES_TITLE', "Listes des bases de données externes qui sont supervisées ou utilisées par cette installation d'Ortro.
Chaque base de données est associée à un seul serveur."); +define('DATABASE_ADD_TOP', "Base de données: Ajout"); +define('DATABASE_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter une base de données."); +define('DATABASE_EDIT_TOP', "Base de données: Modification"); +define('DATABASE_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier une base de données."); +define('DATABASE_DETAILS_TOP', "Base de données: Détails"); +define('HOST_TOP', "Serveurs: Visualisation"); +define('HOST_TITLE', "Liste des serveurs configurés dans cette installation d'Ortro.
Le serveurs sont les unités où s'exécutent les travaux. Chaque serveur est associé à un système."); +define('HOST_ADD_TOP', "Serveurs: Ajout"); +define('HOST_ADD_TITLE', "Utiliser les champs ci-dessous pour modifier un serveur."); +define('HOST_EDIT_TOP', "Serveurs: Modification"); +define('HOST_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier un serveur."); +define('JOB_TOP', "Travaux: Visualisation"); +define('JOB_TITLE', "Listes des travaux qui sont configurés dans cette installation d'Ortro.
Les travaux sont des unités de traitement. Chaque travail s'exécute sur un serveur."); +define('JOB_ADD_TOP', "Travaux: Ajout"); +define('JOB_ADD_TITLE', "Utiliser les champs ci-dessous pour modifier le travail."); +define('JOB_EDIT_TOP', "Travaux: Modification"); +define('JOB_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier le travail."); +define('JOB_DETAILS_TOP', "Travaux: Détails"); +define('NOTIFICATION_TOP', "Notifications: Visualisation"); +define('NOTIFICATION_TITLE', "Liste des notifications qui sont configurées dans cette installation d'Ortro.
Chaque notification est associée à un travail et est envoyée de manière conditionnelle en fonction du résultat de l'exécution du travail."); +define('NOTIFICATION_ADD_TOP', "Notifications: Ajout"); +define('NOTIFICATION_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter une notification."); +define('NOTIFICATION_EDIT_TOP', "Notifications: Modification"); +define('NOTIFICATION_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier la notification."); +define('NOTIFICATION_DETAILS_TOP', "Notifications: Détails"); +define('USER_TOP', "Utilisateurs: Visualisation"); +define('USER_TITLE', "Liste des utilisateurs qui sont autorisés à se connecter à Ortro.
Les privilèges sont déterminés en fonction de l'appartenance aux groupes."); +define('USER_ADD_TOP', "Utilisateurs: Ajout"); +define('USER_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter l'utilisateur."); +define('USER_EDIT_TOP', "Utilisateurs: Modification"); +define('USER_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier l'utilisateur."); +define('USER_DETAILS_TOP', "Utilisateurs: Détails"); +define('USER_GROUP_EDIT_TOP', "Membres du groupe: Modification"); +define('USER_GROUP_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier les membres du groupe."); +define('GROUP_TOP', "Groupes: Visualisation"); +define('GROUP_TITLE', "Liste des groupes qui sont configurés dans cette installation d'Ortro.
Les groupes permettent de définir les actions autorisées aux utilisateurs."); +define('GROUP_ADD_TOP', "Groupes: Ajout"); +define('GROUP_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter le groupe."); +define('GROUP_EDIT_TOP', "Groupes: Modification"); +define('GROUP_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier le groupe."); +define('ID_ADMIN_TOP', "Identités: Visualisation"); +define('ID_ADMIN_TITLE', "Listes des identités qui sont configurées dans cette installation d'Ortro.
Les identités sont des couples utilisateurs / mot de passe qui décrivent des utilisateurs de base de données ou d'autres ressources."); +define('ID_ADMIN_ADD_TOP', "Identités: Ajout"); +define('ID_ADMIN_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter une identité."); +define('ID_ADMIN_EDIT_TOP', "Identité: Modification"); +define('ID_ADMIN_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier l'identité."); +define('ID_ADMIN_SHARE_WITH', "Sélectionner le(s) système(s) qui vont partager cette identité:"); +define('SETTING_TITLE', "Veuillez configurer les champs ci-dessous en fonction de votre environnement."); +define('LDAP_SETTING_TITLE', "Veuillez configurer les champs ci-dessous en fonction de votre environnement."); +define('PLUGIN_TOP', "Extensions de traitement: Visualisation"); +define('PLUGIN_TITLE', "Liste des extensions de traitement qui sont configurées dans cette installation d'Ortro.
Chaque travail utilise l'une de ces extensions de traitement en fonction de ce qu'il doit accomplir."); +define('PLUGIN_ADD_TOP', "Extensions de traitement: Ajout"); +define('PLUGIN_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter une extension de traitement."); +define('PLUGIN_ADD_ARCHIVE', "Fichier contenant l'extension"); +define('PLUGIN_EDIT_TOP', "Extensions de traitement: Modification"); +define('PLUGIN_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier une extension de traitement."); +define('PLUGIN_EDIT_ENV', "Veuillez configurer les champs ci-dessous en fonction de votre environnement."); +define('NOTIFICATION_PLUGIN_TOP', "Extensions de notification: Visualisation"); +define('NOTIFICATION_PLUGIN_TITLE', "Liste des extensions de notification qui sont configurées dans cette installation de Ortro.
Les extensions de notifications permettent d'avertir les utilisateurs des résultats de l'exécution d'un traitement."); +define('NOTIFICATION_PLUGIN_ADD_TOP', "Extension de notification: Ajout"); +define('NOTIFICATION_PLUGIN_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter une extension de notification."); +define('NOTIFICATION_PLUGIN_EDIT_TOP', "Extension de notification: Modification"); +define('NOTIFICATION_PLUGIN_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier une extension de notification."); +define('WORKFLOW_TOP', "Enchaînements: Visualisation"); +define('WORKFLOW_TITLE', "Liste des enchaînements qui sont définis dans cette installation de Ortro.
Un enchaînement est une suite ordonnée d'étapes avec pour chaque étape un travail."); +define('WORKFLOW_ADD_TOP', "Enchaînements: Ajout"); +define('WORKFLOW_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter un enchaînement."); +define('WORKFLOW_EDIT_TOP', "Enchaînements: Modification"); +define('WORKFLOW_EDIT_TITLE', "Utiliser les champs ci-dessous pour modifier un enchaînement."); +define('WORKFLOW_DETAILS_TOP', "Enchaînements: Détails"); +define('FILE_MANAGER_TOP', "Gestionnaire de fichier"); +define('FILE_MANAGER_TITLE', "Utiliser les champs ci-dessous pour télécharger et gérer les fichiers dans Ortro.
Ces fichiers peuvent être utilisé comme entré pour un travail."); +define('FILE_MANAGER_DISABLED', "La possibilité de télécharger des fichiers (file_uploads) n'est pas autorisé dans votre configuration de PHP.
Veuillez mettre file_uploads=On dans votre fichier de configuration php.ini."); +define('FILTER', "Filtre"); +define('FILTER_SYSTEM', "Système:"); +define('FILTER_JOB', "Travail:"); +define('FILTER_STATUS', "Etat:"); +define('FILTER_RESULT', "Résultat:"); +define('FILTER_NOTIFY_TYPE', "Type de notification:"); +define('FILTER_NOTIFY_ON', "Notification sur:"); +define('FILTER_GROUP', "Groupe:"); +define('FILTER_USERNAME', "Nom de l'utilisateur:"); +define('FILTER_NAME', "Nom:"); +define('FILTER_MAIL', "Courriel:"); +define('FILTER_RESET_TITLE', "Ré initialisation"); +define('FILTER_APPLY_FILTER_TITLE', "Appliquer le filtre"); +define('FILTER_ALL', "--- Tout ---"); +define('FILTER_NONE', "---"); +define('FILTER_LOCKED', "Verrouiller"); +define('FILTER_RUNNING', "En cours"); +define('FILTER_WAIT', "Attente"); +define('FILTER_SUCCESS', "Succès"); +define('FILTER_ERROR', "Erreur"); +define('FILTER_START', "Début"); +define('FILTER_END', "Fin"); +define('FILTER_WORKFLOW', "Enchaînement:"); +define('FIELD_SYSTEM', "Système"); +define('FIELD_DATABASE', "Base(s) de données"); +define('FIELD_DATABASE_ONLY', "Base de données"); +define('FIELD_HOSTNAME', "Serveur"); +define('FIELD_IP', "Nom du serveur/Adresse IP"); +define('FIELD_SYSTEM_HOST', "Système / Serveur"); +define('FIELD_PASSWORD', "Mot de passe"); +define('FIELD_CONFIRM_PASSWORD', "Confirmation du mot de passe"); +define('FIELD_OLD_PASSWORD', "Ancien mot de passe"); +define('FIELD_LABEL_IDENTITY', "Nom de l'identité"); +define('FIELD_USERNAME', "Nom de l'utilisateur"); +define('FIELD_IDENTITY', "Identité"); +define('FIELD_SHARE', "Partage"); +define('FIELD_SHARED_SYSTEM', "Partagé avec les systèmes"); +define('FIELD_LABEL', "Nom"); +define('FIELD_DB_NAME_SID', "Nom de la base/Information de connexion (SID)"); +define('FIELD_PORT', "Port"); +define('FIELD_DBMS', DBMS); +define('FIELD_ADD_HOST', "Ajouter un serveur"); +define('FIELD_SELECT_SYSTEM', "--- Système ---"); +define('FIELD_SELECT_HOST', "--- Serveur ---"); +define('FIELD_SELECT_DB', "--- Base de donnée ---"); +define('FIELD_SELECT_NONE', "---"); +define('FIELD_SELECT_CATEGORY', "--- Catégorie ---"); +define('FIELD_SELECT_JOB', "--- Travail ---"); +define('FIELD_SELECT_NOTIFICATION', "--- Notification ---"); +define('FIELD_SELECT_WORKFLOW', "--- Enchaînement ---"); +define('FIELD_SELECT_LABEL', "--- Nom ---"); +define('FIELD_SELECT_ADD_A_STEP', "--- Ajouter ---"); +define('FIELD_SELECT_STEP', "--- Etape ---"); +define('FIELD_JOB', "Nom du travail"); +define('FIELD_JOB_STATUS', "Etat"); +define('FIELD_LAST_JOB_RESULT', "Dernier résultat"); +define('FIELD_LAST_EXEC_TIME', "Dernière exécution"); +define('FIELD_NEXT_EXEC_TIME', "Exécution suivante"); +define('FIELD_JOB_PROPERTIES', "Propriétés"); +define('FIELD_JOB_DESCRIPTION', "Description"); +define('FIELD_JOB_PRIORITY', "Priorité (1 - 100)"); +define('FIELD_JOB_PRIORITY_DETAILS', "Priorité"); +define('FIELD_JOB_MAX_ATTEMPT', "Nombre maximum de re-tentative sur un échec"); +define('FIELD_JOB_DELAY', "Délai entre chaque tentative (en seconde)"); +define('FIELD_SYSTEM_HOST_DB', "Système/Serveur/Base de données"); +define('FIELD_JOB_TYPE', "Type de travail"); +define('FIELD_NOTIFY_TYPE', "Type de notification"); +define('FIELD_NOTIFY_JOB_ERROR', "Erreur"); +define('FIELD_NOTIFY_JOB_SUCCESS', "Réussi"); +define('FIELD_NOTIFY_JOB_END', "Fin"); +define('FIELD_NOTIFY_JOB_START', "Début"); +define('FIELD_NOTIFY_SEND_ON', "Notification sur travail"); +define('FIELD_NOTIFY_METHOD', "Méthode de notification"); +define('FIELD_NOTIFY_DESCRIPTION', "Description"); +define('FIELD_JOB_SCHEDULE', "Enchaînement"); +define('FIELD_JOB_SCHEDULE_EVERY_5', 5); +define('FIELD_JOB_SCHEDULE_EVERY_15', 15); +define('FIELD_JOB_SCHEDULE_EVERY_30', 30); +define('FIELD_JOB_SCHEDULE_EVERY_6', 6); +define('FIELD_JOB_SCHEDULE_EVERY_12', 12); +define('FIELD_JOB_SCHEDULE_EVERY_MIN', "1 min"); +define('FIELD_JOB_SCHEDULE_EVERY_5_MIN', "5 min"); +define('FIELD_JOB_SCHEDULE_EVERY_15_MIN', "15 min"); +define('FIELD_JOB_SCHEDULE_EVERY_30_MIN', "30 min"); +define('FIELD_JOB_SCHEDULE_CUSTOM', "Spécifique"); +define('FIELD_JOB_SCHEDULE_EVERY_HOUR', "1 h"); +define('FIELD_JOB_SCHEDULE_EVERY_6_HOUR', "6 h"); +define('FIELD_JOB_SCHEDULE_EVERY_12_HOUR', "12 h"); +define('FIELD_JOB_SCHEDULE_EVERY_DAY', "Tous les jours"); +define('FIELD_JOB_SCHEDULE_EVERY_MONTH', "Tous les mois"); +define('FIELD_JOB_SCHEDULE_EVERY_DAY_OF_WEEK', "Chaque jour de la semaine"); +define('FIELD_JOB_SCHEDULE_SUNDAY', "Dimanche"); +define('FIELD_JOB_SCHEDULE_MONDAY', "Lundi"); +define('FIELD_JOB_SCHEDULE_TUESDAY', "Mardi"); +define('FIELD_JOB_SCHEDULE_WEDNEDAY', "Mercredi"); +define('FIELD_JOB_SCHEDULE_THURSDAY', "Jeudi"); +define('FIELD_JOB_SCHEDULE_FRIDAY', "Vendredi"); +define('FIELD_JOB_SCHEDULE_SATURDAY', "Samedi"); +define('FIELD_JOB_SCHEDULE_ENABLE', "Actif"); +define('FIELD_JOB_SCHEDULE_ENABLE_WORKFLOW', "Disponible pour les enchaînements"); +define('FIELD_JOB_SCHEDULE_ENABLE_JOB', "Disponible pour les travaux"); +define('FIELD_JOB_SCHEDULE_DISABLE', "Inactif"); +define('FIELD_JOB_SCHEDULE_MINUTE', "Minutes"); +define('FIELD_JOB_SCHEDULE_HOUR', "Heure"); +define('FIELD_JOB_SCHEDULE_DAY_OF_MONTH', "Jour du mois"); +define('FIELD_JOB_SCHEDULE_MONTH_OF_YEAR', "Mois dans l'année"); +define('FIELD_JOB_SCHEDULE_DAY_OF_WEEK', "Jour de la semaine"); +define('FIELD_JOB_SCHEDULE_MANUAL', "Manuel"); +define('FIELD_USER', "Utilisateur"); +define('FIELD_USER_NAME', "Nom"); +define('FIELD_USER_MAIL', "Courriel"); +define('FIELD_USER_GROUP', "Groupes"); +define('FIELD_USER_ID', "Identifiant de l'utilisateur"); +define('FIELD_USER_ACTION', "Action"); +define('FIELD_USER_COMPLETE_NAME', "Nom complet"); +define('FIELD_USER_FIND_ON_LDAP', "Recherche de l'utilisateur dans l'annuaire LDAP"); +define('FIELD_USER_SEARCH_FOR', "Critère de recherche"); +define('FIELD_USER_SEARCH_STRING', "Chaine de recherche"); +define('FIELD_USER_LANG', "Langue"); +define('FIELD_USER_AVAILABLE_GROUPS', "Groupes disponibles"); +define('FIELD_USER_MEMBER_GROUPS', "Membre des groupes"); +define('FIELD_GROUP', "Groupe"); +define('FIELD_ROLE', "Rôle"); +define('FIELD_SYSTEMS', "Système(s)"); +define('FIELD_GROUP_NAME', "Nom du groupe"); +define('FIELD_CATEGORY', "Catégorie"); +define('FIELD_PLUGIN', "Extension de traitement"); +define('FIELD_VERSION', "Version"); +define('FIELD_AUTHOR', "Auteur(s)"); +define('FIELD_DESCRIPTION', "Description"); +define('FIELD_WORKFLOW', "Enchaînement"); +define('FIELD_WORKFLOW_STATUS', "Etat"); +define('FIELD_WORKFLOW_STEP', "Etape"); +define('FIELD_WORKFLOW_JOB_TO_EXEC', "Travail à exécuter"); +define('FIELD_WORKFLOW_STEP_TO_EXEC', "Etape à exécuter"); +define('FIELD_WORKFLOW_STEP_ERROR', "Sur échec aller à l'étape"); +define('FIELD_WORKFLOW_STEP_SUCCESS', "Sur succès aller à l'étape"); +define('FIELD_UPLOAD_FILE', "Fichier à télécharger"); +define('FIELD_FILE_MANAGER', "Gestionnaire de fichier"); +define('TOOLTIP_WAIT_FOR_EXEC', "En attente de l'exécution"); +define('TOOLTIP_RUNNING', "En cours"); +define('TOOLTIP_LOCKED', "Verrouiller"); +define('TOOLTIP_JOB_RESULT', "Résultat du travail"); +define('TOOLTIP_JOB_DESCRIPTION', "Description du travail"); +define('TOOLTIP_NOTIFICATION_DETAILS', "Détails de la notification"); +define('TOOLTIP_IDENTITY_PICKER', "Sélection de l'identité"); +define('TOOLTIP_PLUGIN_DESCRIPTION', "Description de l'extension"); +define('TOOLTIP_WORKFLOW_DESCRIPTION', "Description de l'enchaînement"); +define('TOOLTIP_SUCCESS', "Succès"); +define('TOOLTIP_ERROR', "Erreur"); +define('TOOLTIP_STEP_EXEC_IMMEDIATE', "Exécuter immédiatement les étapes sélectionnées"); +define('TOOLTIP_STEP_WAIT_FOR_SCHED', "Exécuter les étapes sélectionnées comme prévu dans les paramètres des travaux"); +define('MSG_SYSTEM_NAME_REQUIRED', "Le nom du système est obligatoire."); +define('MSG_HOST_NAME_REQUIRED', "Le serveur est obligatoire."); +define('MSG_IP_REQUIRED', "Le nom du serveur/adresse IP est obligatoire."); +define('MSG_IP_NOT_VALID', "Le format de l'adresse IP n'est pas valide."); +define('MSG_SELECT_A_SYSTEM', "Veuillez sélectionner un système."); +define('MSG_SELECT_A_HOST', "Veuillez sélectionner un serveur."); +define('MSG_LABEL_REQUIRED', "Le nom est obligatoire."); +define('MSG_SID_REQUIRED', "Le SID est obligatoire."); +define('MSG_PORT_REQUIRED', "Le port est obligatoire."); +define('MSG_PORT_IS_A_NUMBER', "Le port doit être un nombre."); +define('MSG_USERNAME_REQUIRED', "Le nom de l'utilisateur est obligatoire."); +define('MSG_PASSWORD_NOT_MATCH', "Les mots de passe ne sont pas identiques."); +define('MSG_PASSWORD_REQUIRED', "Le mot de passe est obligatoire."); +define('MSG_PASSWORD_MIN_CHAR', "Le mot de passe doit avoir une longueur minimum de 6."); +define('MSG_PRIORITY_REQUIRED', "La priorité est obligatoire."); +define('MSG_PRIORITY_HAS_VALUE', "La priorité doit avoir une valeur entre 0 et 100."); +define('MSG_MAX_CHECK_ATTEMPT_IS_NUMERIC', "Le nombre maximum de tentatives doit être un nombre (mettre 0 pour ne pas avoir de re-tentative)"); +define('MSG_MAX_CHECK_ATTEMPT_REQUIRED', "Le nombre maximum de tentatives est obligatoire (mettre 0 pour ne pas avoir de re-tentative)"); +define('MSG_MAX_DELAY_IS_NUMERIC', "Le temps entre chaque tentative doit être un nombre (mettre 0 pour ne pas en tenir compte)"); +define('MSG_MAX_DELAY_REQUIRED', "Le temps entre chaque tentative est obligatoire (mettre 0 pour ne pas en tenir compte)"); +define('MSG_SELECT_A_JOB_TYPE', "Veuillez sélectionner un type de travail."); +define('MSG_SELECT_A_NOTIFICATION_TYPE', "Veuillez sélectionner un type de notification."); +define('MSG_SELECT_A_VALUE_FOR_MINUTE', "Veuillez sélectionner une valeur pour les minutes."); +define('MSG_SELECT_A_VALUE_FOR_HOUR', "Veuillez sélectionner une valeur pour les heures."); +define('MSG_SELECT_A_VALUE_FOR_DAY', "Veuillez sélectionner une valeur pour les jours."); +define('MSG_SELECT_A_VALUE_FOR_MONTH', "Veuillez sélectionner une valeur pour les mois."); +define('MSG_SELECT_A_VALUE_FOR_DAY_OF_WEEK', "Veuillez sélectionner une valeur pour les jours de la semaine."); +define('MSG_LDAP_CONNECTION_FAILED', "La connexion au serveur LDAP a échoué!
Veuillez prendre contact avec l'administrateur de l'application."); +define('MSG_LDAP_NO_MATCH_FOUND', "Aucune correspondance trouvée!"); +define('MSG_LDAP_NOT_ENABLED', "Le module LDAP n'est pas disponible dans PHP."); +define('MSG_COMPLETE_NAME_REQUIRED', "Le nom complet est obligatoire."); +define('MSG_MAIL_REQUIRED', "L'adresse de courriel est obligatoire."); +define('MSG_MAIL_NOT_VALID', "Le format de l'adresse de courriel n'est pas valide."); +define('MSG_SEARCH_FIELD_REQUIRED', "Le nom du champ pour la recherche est obligatoire."); +define('MSG_GROUP_NAME_REQUIRED', "Le nom du groupe est obligatoire."); +define('MSG_AUTHENTICATION_FAILED', "L'authentification a échoué!"); +define('MSG_PLUGIN_NO_FURTHER_CONFIGURATION', "Cette extension n'a pas de paramètres de configuration."); +define('MSG_SELECT_A_VALUE_FOR_GROUP', "Veuillez sélectionner un groupe."); +define('MSG_ADD_WORKFLOW_JOB_IS_REQUIRED', "Veuillez sélectionner un travail pour continuer."); +define('MSG_SELECT_A_WORKFLOW_OR_JOB', "Veuillez sélectionner un enchaînement ou un travail pour l'exécuter."); +define('MSG_SELECT_A_FILE', "Veuillez sélectionner un fichier."); +define('MSG_SELECT_A_VALUE_FOR_SYSTEM', "Veuillez sélectionner un système."); +define('DISPLAY_REPORTS_TOP', "Ci-dessous se trouve la liste de tous les rapports archivés."); +define('MSG_REPORTS_NOT_AVAILABLE', "Les rapports ne sont pas disponibles."); +define('MSG_DOWNLOAD', "Téléchargement"); +define('BUTTON_ORDER_BY_FILENAME', "Nom du fichier"); +define('BUTTON_ORDER_BY_DATE', "Date"); +define('BUTTON_ORDER_BY_SIZE', "Taille"); +define('DISPLAY_ARCHIVED_RESULTS_TOP', "Ci-dessous se trouve la liste de tous les résultats archivés pour"); +define('MSG_ARCHIVED_RESULTS_NOT_AVAILABLE', "Il n'y a pas de résultats archivés pour"); +define('MSG_JOB_ARCHIVED_RESULT', "Résultat"); +define('MSG_JOB_ARCHIVED_EXIT_CODE', "Code de retour"); +define('MSG_JOB_ARCHIVED_START_EXEC', "Heure de début d'exécution"); +define('MSG_JOB_ARCHIVED_END_EXEC', "Heure de fin d'exécution"); +define('MSG_FILES_NOT_FOUNDS', "Il n'y a pas de fichiers enregistrés pour ce système:"); +define('MSG_PAGE_NOT_FOUND', "Page non trouvée."); +define('FIELD_OVERWRITE_EXISTING_DB', "Supprimé la base de données existante"); +define('FIELD_DATABASE_ALREADY_EXISTS', "Le nom donné pour la base de données est déjà utilisé.
Cliquez sur le lien: Consulter/Modifier."); +define('IMPORT_EXPORT_TOP', "Outil pour sauvegarder et restaurer Ortro"); +define('IMPORT_EXPORT_TITLE', "Utiliser les champs ci-dessous pour sauvegarder/restaurer les paramètres de configuration d'Ortro."); +define('FIELD_IMPORT_SUBMIT', "Restaurer"); +define('FIELD_EXPORT_SUBMIT', "Sauvegarder"); +define('FIELD_EXPORT_DESCRIPTION', "Sauvegarder les paramètres d'Ortro"); +define('FIELD_EXPORT_SUB_DESCRIPTION', "Sauvegarde de la base de données et des fichiers de configuration (tar.gz)."); +define('FIELD_IMPORT_DESCRIPTION', "Restaurer les paramètres d'Ortro"); +define('FIELD_IMPORT_SUB_DESCRIPTION', "Sélectionner une sauvegarde qui sera restaurée."); +define('FIELD_IMPORT_SUCCESS', "Le chargement a été réalisé.
Veuillez contrôler le fichier configure.php. L'ancien fichier de configuration a été archivé dans le répertoire conf/backup.
Cliquez sur le lien: Consulter/Modifier."); +define('FIELD_EXPORT_SUCCESS', "Sauvegarde réalisée."); +define('FIELD_EXPORT_ERROR', "Erreur de la sauvegarde. Le fichier de sauvegarde est corrompu."); +define('FIELD_IMPORT_DB_NOT_SUPPORTED', "Désoler. Cette fonctionnalité n'est pas disponible avec votre type de base de données."); +define('FIELD_CHECK_NEW_SETTINGS_DESCRIPTION', "Il est important de vérifier et de modifier la nouvelle configuration des données."); +define('FIELD_CHECK_NEW_SETTINGS_LINK', "Consulter/Modifier les données"); +define('AUTODISCOVERY_TOP', "Découverte : recherche"); +define('AUTODISCOVERY_TITLE', "Utiliser cet outil pour découvrir de manière automatique les 'serveurs' de votre réseau et pour les ajouter dans un système"); +define('FIELD_AUTODISCOVERY', "Découverte"); +define('FIELD_NMAP_TARGET', "Définition de la cible : nom de serveur, adresse ip, réseau, ... séparés par des espaces.
Par exemple : scanme.example.org example.com/24 192.168.0.1 10.0.0-255.1-254"); +define('FIELD_AUTODISCOVERY_OS_DETECTION', "Permettre la détection du type de système d'exploitation."); +define('FIELD_NMAP_BINARY', "Chemin sur l'outil Nmap:"); +define('BUTTON_SCAN', "Recherche"); +define('MSG_TARGET_REQUIRED', "La définition de la cible est nécessaire."); +define('MSG_NMAP_BINARY_REQUIRED', "L'outil Nmap est nécessaire."); +define('FAILED_TO_RESOLVE', "Impossible d'effectuer la résolution du couple serveur / adresse IP."); +define('AUTODISCOVERY_ADD_TOP', "Découverte : ajout"); +define('AUTODISCOVERY_ADD_TITLE', "Utiliser les champs ci-dessous pour ajouter le serveur dans un système."); +define('FIELD_OS_DETAILS', "Système d'exploitation"); +define('YES', "Oui"); +define('NO', "Non"); +define('ASK', "Demander"); +define('FIELD_NOTIFY_JOB_END', "Fin du travail"); +define('FIELD_NOTIFY_JOB_START', "commencer à travail"); +define('DISABLE', "Inactif"); +define('ENABLE', "Actif"); + +?> \ No newline at end of file diff --git a/lang/fr/template/configure_metadata_install.php b/lang/fr/template/configure_metadata_install.php new file mode 100644 index 0000000..3c5f4a4 --- /dev/null +++ b/lang/fr/template/configure_metadata_install.php @@ -0,0 +1,60 @@ +Lors d'une connexion SSH, est ce que Ortro doit ignorer les erreurs sur la clé d'un serveur distant, abandonner immédiatement ou demander à l'utilisateur si il doit continuer ? Par défaut: non."); +define('CONF_INSTALL_ENV_LOG_LEVEL_DEBUG', DEBUG); +define('CONF_INSTALL_ENV_LOG_LEVEL_INFO', INFO); +define('CONF_INSTALL_ENV_LOG_LEVEL_ERROR', ERREUR); +define('CONF_INSTALL_ENV_LOG_LEVEL_DESCRIPTION', "Niveau de trace: DEBUG niveau maximum, ERROR niveau minimum."); +define('CONF_INSTALL_ENV_ZIP_PATH_DESCRIPTION', "Chemin absolu sur l'exécutable zip. Par défaut /usr/bin/zip."); +define('CONF_INSTALL_ENV_ZIP_THRESHOLD_DESCRIPTION', "Taille maximum pour une archive zip (en octets)"); +define('CONF_INSTALL_ENV_DATEFORMAT_DESCRIPTION', "Format de date"); +define('CONF_INSTALL_DATEFORMAT_RULE_1_0', "Le format de la date est obligatoire."); +define('CONF_INSTALL_ENV_TIMEFORMAT_DESCRIPTION', "Format de l'heure"); +define('CONF_INSTALL_ENV_DATEFORMAT_RULE_1_0', "Le format de l'heure est obligatoire."); +define('CONF_INSTALL_XMLRPC_DESCRIPTION', "Configuration du service XML-RPC"); +define('CONF_INSTALL_XMLRPC_TIMEOUT_DESCRIPTION', "Délai d'inactivité de la session (en secondes)"); +define('CONF_INSTALL_XMLRPC_TIMEOUT_RULE_1_0', "Le délai d'inactivité de la session est obligatoire."); +define('CONF_INSTALL_AUTH_DESCRIPTION', "Ortro Authentication settings"); +define('CONF_INSTALL_AUTH_DEFAULT_DESCRIPTION', "Default authentication method"); +define('CONF_INSTALL_AUTH_FALLBACK_DESCRIPTION', "Fallback authentication"); + +?> \ No newline at end of file diff --git a/lang/fr/template/configure_metadata_ldap.php b/lang/fr/template/configure_metadata_ldap.php new file mode 100644 index 0000000..ef6fe7a --- /dev/null +++ b/lang/fr/template/configure_metadata_ldap.php @@ -0,0 +1,18 @@ +Laisser vide pour une connexion anonyme (anonymous)."); +define('CONF_LDAP_BIND_PASSWORD_DESCRIPTION', "Mot de passe de connexion: Mot de passe de l'utilisateur de recherche ci-dessus.
Laisser vide pour une connexion anonyme (anonymous)."); +define('CONF_LDAP_SEARCH_ATTRIBUTE_UID_DESCRIPTION', "Attribut pour l'authentification de l'utilisateur. Par exemple l'uid ou sAMAccountName."); +define('CONF_LDAP_SEARCH_ATTRIBUTE_CN_DESCRIPTION', "Attribut contenant le nom complet de l'utilisateur. Par exemple cn."); +define('CONF_LDAP_SEARCH_ATTRIBUTE_MAIL_DESCRIPTION', "Attribut contenant l'adresse de courriel de l'utilisateur. Par exemple mail."); + +?> diff --git a/lang/fr/template/install.php b/lang/fr/template/install.php new file mode 100644 index 0000000..54c07f0 --- /dev/null +++ b/lang/fr/template/install.php @@ -0,0 +1,64 @@ +
d'ordonnancement de travaux et la supervision de systèmes / applications."); +define('INSTALL_CRONTAB_MSG_PART_1', "Appuyer sur le bouton 'Modifier la crontab' pour ajouter la ligne ci-dessus dans la crontab de"); +define('INSTALL_CRONTAB_MSG_PART_2', "utilisateur:"); +define('INSTALL_CRONTAB_MSG_PART_3', "Une copie de votre crontab actuelle sera sauvegardée dans:"); +define('INSTALL_CRONTAB_NEW', "Nouvelle crontab:"); +define('INSTALL_CRONTAB_OLD', "Ancienne crontab:"); +define('INSTALL_CRONTAB_TITLE', "Ajouter la configuration de Ortro dans la crontab."); +define('INSTALL_EXTENSIONS', "Extensions PHP"); +define('INSTALL_EXTENSIONS_ALERT', "Extension non trouvées :"); +define('INSTALL_FILE_PERMISSION', "Permissions sur les fichiers"); +define('INSTALL_FINISH_MSG_PART_1', "Ortro a été installé avec succès!"); +define('INSTALL_FINISH_MSG_PART_2', "Maintenant vous pouvez "); +define('INSTALL_FINISH_MSG_PART_3', "vous connectez"); +define('INSTALL_FINISH_MSG_PART_4', "avec l'utilisateur admin, mot de passe admin. N'oubliez pas de modifier le mot de passe rapidement."); +define('INSTALL_FINISH_MSG_PART_5', "Pour des raisons de sécurité, n'oubliez pas de supprimer le répertoire contenant l'assistant d'installation:"); +define('INSTALL_HOW_DESCRIPTION', "Pour commencer l'installation de Ortro, veuillez choisir une langue et appuyer sur le bouton 'Suivant'."); +define('INSTALL_LICENSE', "Licence GNU/GPL:"); +define('INSTALL_MENU_CRONTAB', "Crontab"); +define('INSTALL_MENU_DATABASE', "Base de données"); +define('INSTALL_MENU_FINISH', "Terminer"); +define('INSTALL_MENU_LICENSE', "License"); +define('INSTALL_MENU_PLUGINS', "Extensions"); +define('INSTALL_MENU_PRE_INSTALL_CHECK', "Vérification des pré-requis"); +define('INSTALL_MENU_SSH', SSH); +define('INSTALL_MENU_TITLE', "Etapes de l'installation"); +define('INSTALL_MENU_WELCOME', "Bienvenue"); +define('INSTALL_MSG_ACTION_CONFIGURE_FILE_NOT_FOUND', "Le fichier configure.php n'a pas été trouvé dans"); +define('INSTALL_MSG_DB_CREATED_WITH_SUCCESS', "La base de données a été crée avec succès."); +define('INSTALL_MSG_INSTALL_OK', "Les extensions ci-dessous ont été installées avec succès:"); +define('INSTALL_MSG_NO_PLUGIN_TO_INSTALL', "Il n'y a pas d'extensions à installer."); +define('INSTALL_MSG_PLUGIN_FURTHER_CONFIGURATION', "Les extensions ci-dessous nécessitent une configuration supplémentaire. Après votre connexion, effectuer leurs configurations avant de les utilisées."); +define('INSTALL_PHP', PHP); +define('INSTALL_PHP_CLI_PATH', "Chemin absolu sur PHP-CLI:"); +define('INSTALL_PHP_CLI_VERSION', "Version PHP-CLI >= 5.1.0"); +define('INSTALL_PHP_VERSION', "Version PHP >= 5.1.0"); +define('INSTALL_PLUGIN_NAME', "Nom"); +define('INSTALL_PLUGIN_VERSION', "Version"); +define('INSTALL_RDBMS', "Base de données supportées"); +define('INSTALL_RDBMS_ALERT', "Il semble que votre installation de PHP ne comporte aucune gestion de bases de données. Veuillez installer au moins le support d'un type de base et essayez de nouveau."); +define('INSTALL_SSH', SSH); +define('INSTALL_SSH_CLIENT', "Client SSH"); +define('INSTALL_SSH_CLIENT_PATH', "Chemin absolu sur le client SSH:"); +define('INSTALL_SSH_TITLE', "Génération des clés SSH privé/publique"); +define('INSTALL_WELCOME_DESCRIPTION', "Bienvenue dans Ortro"); +define('INSTALL_WRITE_PERMISSION', "autorisé en écriture"); +define('UPGRADE_CONFIGURE_NOT_FOUND', "Le fichier configure.php n'a pas été trouvé!!!"); +define('UPGRADE_DB_SCHEMA', "Mise à jour de la base de données..."); +define('UPGRADE_ERROR', "Erreur:"); +define('UPGRADE_JS', "Mise à jour des fichiers javascript..."); +define('UPGRADE_PLUGINS', "Mise à jour des extensions..."); +define('UPGRADE_REMOVE_INSTALL_DIR', "Suppression du répertoire d'installation..."); + +?> \ No newline at end of file diff --git a/lang/fr/template/menu.php b/lang/fr/template/menu.php new file mode 100644 index 0000000..66276bd --- /dev/null +++ b/lang/fr/template/menu.php @@ -0,0 +1,47 @@ + \ No newline at end of file diff --git a/lang/fr/template/plugin_common.php b/lang/fr/template/plugin_common.php new file mode 100644 index 0000000..b34d2e5 --- /dev/null +++ b/lang/fr/template/plugin_common.php @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/lang/it/js/js.php b/lang/it/js/js.php new file mode 100644 index 0000000..12f471f --- /dev/null +++ b/lang/it/js/js.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/it/plugins/database/check_tablespace/language.php b/lang/it/plugins/database/check_tablespace/language.php new file mode 100644 index 0000000..c861eb2 --- /dev/null +++ b/lang/it/plugins/database/check_tablespace/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/database/custom_query/language.php b/lang/it/plugins/database/custom_query/language.php new file mode 100644 index 0000000..69feefb --- /dev/null +++ b/lang/it/plugins/database/custom_query/language.php @@ -0,0 +1,10 @@ + Se il confronto è soddisfatto ritorna successo o errore in accordo con il campo 'Se il test è vero'"); +define('PLUGIN_DB_CUSTOM_QUERY_TITLE',"DB Custom Query"); +define('PLUGIN_DB_CUSTOM_QUERY_OPERATOR_DESCRIPTION',"Operatore"); +define('PLUGIN_DB_CUSTOM_QUERY_SUCCESS',"Successo"); +define('PLUGIN_DB_CUSTOM_QUERY_ERROR',"Errore"); +define('PLUGIN_DB_CUSTOM_QUERY_THRESHOLD_DESCRIPTION',"Soglia"); +define('PLUGIN_DB_CUSTOM_QUERY_RULE_4_0',"Soglia è obbligatorio"); +define('PLUGIN_DB_CUSTOM_QUERY_ERROR_DESCRIPTION',"Se il test è vero ritorna"); +?> \ No newline at end of file diff --git a/lang/it/plugins/database/custom_query_report/language.php b/lang/it/plugins/database/custom_query_report/language.php new file mode 100644 index 0000000..16f4139 --- /dev/null +++ b/lang/it/plugins/database/custom_query_report/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/database/execute_sql_from_file/language.php b/lang/it/plugins/database/execute_sql_from_file/language.php new file mode 100644 index 0000000..c2ed588 --- /dev/null +++ b/lang/it/plugins/database/execute_sql_from_file/language.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/lang/it/plugins/database/mysql_table_check/language.php b/lang/it/plugins/database/mysql_table_check/language.php new file mode 100644 index 0000000..f640c79 --- /dev/null +++ b/lang/it/plugins/database/mysql_table_check/language.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/lang/it/plugins/database/oracle_freespa_report/language.php b/lang/it/plugins/database/oracle_freespa_report/language.php new file mode 100644 index 0000000..2ffdae6 --- /dev/null +++ b/lang/it/plugins/database/oracle_freespa_report/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/it/plugins/database/oracle_session_report/language.php b/lang/it/plugins/database/oracle_session_report/language.php new file mode 100644 index 0000000..bc6655b --- /dev/null +++ b/lang/it/plugins/database/oracle_session_report/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/advanced_file_transfer/language.php b/lang/it/plugins/file/advanced_file_transfer/language.php new file mode 100644 index 0000000..dfa7891 --- /dev/null +++ b/lang/it/plugins/file/advanced_file_transfer/language.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/check_tail_status/language.php b/lang/it/plugins/file/check_tail_status/language.php new file mode 100644 index 0000000..6842096 --- /dev/null +++ b/lang/it/plugins/file/check_tail_status/language.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/create/language.php b/lang/it/plugins/file/create/language.php new file mode 100644 index 0000000..988d054 --- /dev/null +++ b/lang/it/plugins/file/create/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/ftp_upload/language.php b/lang/it/plugins/file/ftp_upload/language.php new file mode 100644 index 0000000..cc00b7c --- /dev/null +++ b/lang/it/plugins/file/ftp_upload/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/read_file/language.php b/lang/it/plugins/file/read_file/language.php new file mode 100644 index 0000000..ca260be --- /dev/null +++ b/lang/it/plugins/file/read_file/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/retention/language.php b/lang/it/plugins/file/retention/language.php new file mode 100644 index 0000000..aa5caeb --- /dev/null +++ b/lang/it/plugins/file/retention/language.php @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/scp/language.php b/lang/it/plugins/file/scp/language.php new file mode 100644 index 0000000..0be6f97 --- /dev/null +++ b/lang/it/plugins/file/scp/language.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/search/language.php b/lang/it/plugins/file/search/language.php new file mode 100644 index 0000000..d0707da --- /dev/null +++ b/lang/it/plugins/file/search/language.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/size_check/language.php b/lang/it/plugins/file/size_check/language.php new file mode 100644 index 0000000..bfe61a3 --- /dev/null +++ b/lang/it/plugins/file/size_check/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/it/plugins/file/watch/language.php b/lang/it/plugins/file/watch/language.php new file mode 100644 index 0000000..50699e7 --- /dev/null +++ b/lang/it/plugins/file/watch/language.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/lang/it/plugins/general/custom_script/language.php b/lang/it/plugins/general/custom_script/language.php new file mode 100644 index 0000000..fa2cdf2 --- /dev/null +++ b/lang/it/plugins/general/custom_script/language.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/lang/it/plugins/general/spreadsheet_to_db/language.php b/lang/it/plugins/general/spreadsheet_to_db/language.php new file mode 100644 index 0000000..0eb76c7 --- /dev/null +++ b/lang/it/plugins/general/spreadsheet_to_db/language.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/lang/it/plugins/general/telnet_custom_script/language.php b/lang/it/plugins/general/telnet_custom_script/language.php new file mode 100755 index 0000000..52fe2c6 --- /dev/null +++ b/lang/it/plugins/general/telnet_custom_script/language.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/lang/it/plugins/general/windows_remote_execution/language.php b/lang/it/plugins/general/windows_remote_execution/language.php new file mode 100644 index 0000000..cc71d88 --- /dev/null +++ b/lang/it/plugins/general/windows_remote_execution/language.php @@ -0,0 +1,16 @@ +(ricordarsi di inserire il nome del file)."); +define('PLUGIN_WINDOWS_REMOTE_EXECUTION_RULE_2_0', "Comando è obbligatorio"); +define('PLUGIN_WINDOWS_REMOTE_EXECUTION_TITLE', "Windows remote execution"); + +?> \ No newline at end of file diff --git a/lang/it/plugins/notification/jabber/language.php b/lang/it/plugins/notification/jabber/language.php new file mode 100644 index 0000000..79adf4b --- /dev/null +++ b/lang/it/plugins/notification/jabber/language.php @@ -0,0 +1,22 @@ +@server.com)"); +define('PLUGIN_JABBER_TITLE', "Jabber"); +define('PLUGIN_JABBER_TO_DESCRIPTION', "A: (@server.com)"); +define('PLUGIN_JABBER_TO_DESCRIPTION_DETAIL', "A:"); + +?> \ No newline at end of file diff --git a/lang/it/plugins/notification/mail/language.php b/lang/it/plugins/notification/mail/language.php new file mode 100644 index 0000000..67c0f4a --- /dev/null +++ b/lang/it/plugins/notification/mail/language.php @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/lang/it/plugins/notification/sms_ftp/language.php b/lang/it/plugins/notification/sms_ftp/language.php new file mode 100644 index 0000000..78547ef --- /dev/null +++ b/lang/it/plugins/notification/sms_ftp/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/it/plugins/notification/tibco_rvd/language.php b/lang/it/plugins/notification/tibco_rvd/language.php new file mode 100644 index 0000000..4046b8f --- /dev/null +++ b/lang/it/plugins/notification/tibco_rvd/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/it/plugins/notification/tivoli_postemsg/language.php b/lang/it/plugins/notification/tivoli_postemsg/language.php new file mode 100644 index 0000000..4491617 --- /dev/null +++ b/lang/it/plugins/notification/tivoli_postemsg/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/check_glance_status/language.php b/lang/it/plugins/system/check_glance_status/language.php new file mode 100644 index 0000000..d55e5a3 --- /dev/null +++ b/lang/it/plugins/system/check_glance_status/language.php @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/cpu_idle/language.php b/lang/it/plugins/system/cpu_idle/language.php new file mode 100644 index 0000000..c9b21e6 --- /dev/null +++ b/lang/it/plugins/system/cpu_idle/language.php @@ -0,0 +1,13 @@ +N.B. Valori bassi del tempo di idle sono indice di CPUs molto occupate."); +define('PLUGIN_CPU_IDLE_RULE_3_0', "Soglia è obbligatorio"); +define('PLUGIN_CPU_IDLE_THRESHOLD_DESCRIPTION', "Soglia"); +define('PLUGIN_CPU_IDLE_TITLE', "CPUs idle"); + +?> \ No newline at end of file diff --git a/lang/it/plugins/system/file_system_check/language.php b/lang/it/plugins/system/file_system_check/language.php new file mode 100644 index 0000000..022c926 --- /dev/null +++ b/lang/it/plugins/system/file_system_check/language.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/mem_free/language.php b/lang/it/plugins/system/mem_free/language.php new file mode 100644 index 0000000..bfd314a --- /dev/null +++ b/lang/it/plugins/system/mem_free/language.php @@ -0,0 +1,6 @@ + diff --git a/lang/it/plugins/system/ping/language.php b/lang/it/plugins/system/ping/language.php new file mode 100644 index 0000000..e472f0a --- /dev/null +++ b/lang/it/plugins/system/ping/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/service_check/language.php b/lang/it/plugins/system/service_check/language.php new file mode 100644 index 0000000..85efaeb --- /dev/null +++ b/lang/it/plugins/system/service_check/language.php @@ -0,0 +1,14 @@ + diff --git a/lang/it/plugins/system/solaris_metadevice_check/language.php b/lang/it/plugins/system/solaris_metadevice_check/language.php new file mode 100644 index 0000000..6570fd5 --- /dev/null +++ b/lang/it/plugins/system/solaris_metadevice_check/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/solaris_svc_check/language.php b/lang/it/plugins/system/solaris_svc_check/language.php new file mode 100644 index 0000000..a86c8e2 --- /dev/null +++ b/lang/it/plugins/system/solaris_svc_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/solaris_zfs_scrub_check/language.php b/lang/it/plugins/system/solaris_zfs_scrub_check/language.php new file mode 100644 index 0000000..8156a27 --- /dev/null +++ b/lang/it/plugins/system/solaris_zfs_scrub_check/language.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/lang/it/plugins/system/solaris_zpool_check/language.php b/lang/it/plugins/system/solaris_zpool_check/language.php new file mode 100644 index 0000000..9903b19 --- /dev/null +++ b/lang/it/plugins/system/solaris_zpool_check/language.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/lang/it/plugins/www/check_uri_response_code/language.php b/lang/it/plugins/www/check_uri_response_code/language.php new file mode 100644 index 0000000..88835de --- /dev/null +++ b/lang/it/plugins/www/check_uri_response_code/language.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/lang/it/plugins/www/http_download_file/language.php b/lang/it/plugins/www/http_download_file/language.php new file mode 100644 index 0000000..2b63d44 --- /dev/null +++ b/lang/it/plugins/www/http_download_file/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/it/plugins/www/testgen4web_simpletest/language.php b/lang/it/plugins/www/testgen4web_simpletest/language.php new file mode 100644 index 0000000..f3a1459 --- /dev/null +++ b/lang/it/plugins/www/testgen4web_simpletest/language.php @@ -0,0 +1,22 @@ +Sostituire username e password dell'identità presenti nel codice con e"); +define('PLUGIN_TEST4WEB_RULE_5_0', "Il codice xml è obbligatorio"); +define('PLUGIN_TEST4WEB_TYPE', "Scelta dell'output"); +define('PLUGIN_TEST4WEB_DETAILS', "Rapporto dettagliato"); +define('PLUGIN_TEST4WEB_ONLY_TIME', "Solo tempo d'esecuzione"); +define('PLUGIN_TEST4WEB_THRESHOLD_DESCRIPTION', "Timeout per il test di navigazione in secondi (Lasciare zero per infinito)"); +define('PLUGIN_TEST4WEB_RULE_7_0', "Timeout è obbligatorio"); +define('PLUGIN_TEST4WEB_RULE_7_1', "Timeout deve essere un numero"); + +?> \ No newline at end of file diff --git a/lang/it/plugins/www/webservice_soapui/language.php b/lang/it/plugins/www/webservice_soapui/language.php new file mode 100644 index 0000000..baaacd9 --- /dev/null +++ b/lang/it/plugins/www/webservice_soapui/language.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/lang/it/plugins/www/webtest_selenium/language.php b/lang/it/plugins/www/webtest_selenium/language.php new file mode 100644 index 0000000..fb90426 --- /dev/null +++ b/lang/it/plugins/www/webtest_selenium/language.php @@ -0,0 +1,18 @@ +Sostituire username e password dell' identità presenti nel codice con e"); +define('PLUGIN_WEBTEST_SELENIUM_RULE_3_0', "Il codice dello script è obbligatorio"); + +?> \ No newline at end of file diff --git a/lang/it/plugins/www/webtest_slimdog/language.php b/lang/it/plugins/www/webtest_slimdog/language.php new file mode 100644 index 0000000..081029a --- /dev/null +++ b/lang/it/plugins/www/webtest_slimdog/language.php @@ -0,0 +1,15 @@ +Sostituire username e password dell' identità presenti nel codice con e"); +define('PLUGIN_WEBTEST_SLIMDOG_RULE_2_0', "Il codice dello script è obbligatorio"); + +?> \ No newline at end of file diff --git a/lang/it/template/action_msg.php b/lang/it/template/action_msg.php new file mode 100644 index 0000000..033d994 --- /dev/null +++ b/lang/it/template/action_msg.php @@ -0,0 +1,105 @@ +La dimensione massima per l'upload è:"); +define('MSG_ACTION_REMOVE_ALL_NOTIFICATIONS', "Rimuovere tutte le notifiche associate a questo job."); +define('MSG_ACTION_REMOVE_IDENTITY_FIRST', "I job(s) elencati di seguito sono associati a questa identità. Rimuovere prima questi job(s)."); +define('MSG_ACTION_REMOVE_JOB_FIRST', "I job(s) elencati di seguito sono associati a questo plugin. Rimuovere prima questi job(s)."); +define('MSG_ACTION_REMOVE_NOTIFICATION_FIRST', "Le notiche elencate di seguito sono associate a questo plugin. Rimuovere prima queste notifiche."); +define('MSG_ACTION_REMOVE_USER_FIRST', "Gli utenti elencati di seguito sono associati a questo gruppo. Rimuovere prima questi utenti."); +define('MSG_ACTION_STEP_ADDED', "Step aggiunto con successo."); +define('MSG_ACTION_STRANGE_STATUS', "Stato sconosciuto... Contattare l'ammistratore."); +define('MSG_ACTION_SYSTEM_ADDED', "Sistema aggiunto con successo."); +define('MSG_ACTION_SYSTEM_ALREADY_USED', "Un sistema con lo stesso name è già in uso"); +define('MSG_ACTION_SYSTEM_DELETED', "Sistema rimosso con successo."); +define('MSG_ACTION_SYSTEM_HOSTNAME_ALREADY_USED', "La relazione Sistema <-> host è già in uso"); +define('MSG_ACTION_SYSTEM_REMOVE_JOB_FIRST', "I job(s) elencati di seguito sono associati a questo sistema. Rimuovere prima questi job(s)."); +define('MSG_ACTION_SYSTEM_MODIFIED', "Nome del sistema modificato con successo."); +define('MSG_ACTION_USER_ADDED', "Utente aggiunto con successo."); +define('MSG_ACTION_USER_DELETED', "Utente rimossa con successo."); +define('MSG_ACTION_USER_DELETED_FROM_GROUP', "Utente rimosso dal gruppo con successo."); +define('MSG_ACTION_USER_IN_GROUP_ADDED', "Utente aggiunto al gruppo con successo."); +define('MSG_ACTION_USER_MODIFIED', "Impostazioni dell'utente modificate con successo."); +define('MSG_ACTION_USERNAME_ALREADY_USED', "Username già in uso"); +define('MSG_PERMISSION_DENIED', "Permesso negato."); +define('MSG_LOGOUT', "Logout effettuato con successo."); +define('MSG_IDENTITY_PICK', "Seleziona"); +define('FIELD_IDENTITY_PICK', "Selezionare l'identità da utilizzare:"); +define('FIELD_IDENTITY_PICK_TITLE', "Seleziona identità"); +define('MSG_IDENTITY_NOT_FOUND', "Nessuna identità disponibile
per il sistema specificato"); +define('MSG_ACTION_FILE_UPLOAD_SUCCESS', "Upload effettuato con successo."); +define('MSG_ACTION_FILE_DELETED_SUCCESS', "File cancellato con successo."); +define('MSG_ACTION_FILE_DELETED_ERROR', "Si è verificato un errore durante la rimozione del file."); +define('MSG_ACTION_MIN_VERSION_REQUIRED', "La verione minima di Ortro richiesta per questo plugin è:"); +define('MSG_GD_LIB_NOT_ENABLED', "Impossibile creare l'immagine.
Nell'installazione di PHP non risulta abilitato il supporto alla libreria GD."); +define('MSG_EXECUTION_ABORTED', "Esecuzione interrotta."); +define('MSG_ACTION_SYSTEM_HOST_LOCKED',"Sistema o host bloccato... Sbloccarlo."); +define('MSG_ACTION_SYSTEM_STATUS_UPDATED', "Stato del sistema modificato con successo."); +define('MSG_CALENDAR_REQUIRED', "Definire un calendario"); +define('MSG_ACTION_CALENDAR_ADDED', "Calendario aggiunto con successo."); +define('MSG_ACTION_CALENDAR_MODIFIED', "Calendario modificato con successo."); +define('MSG_ACTION_CALENDAR_DELETED', "Calendario rimosso con successo."); +define('MSG_ACTION_CALENDAR_COPIED', "Calendario copiato con successo."); +define('MSG_ACTION_REMOVE_CALENDAR_FIRST', "I job(s) elencati di seguito sono associati con questo calendario. Rimuovere prima questi job(s)."); +define('FIELD_CALENDAR_PICK', "Selezionare il calendario da utilizzare:"); +define('FIELD_CALENDAR_PICK_TITLE', "Seleziona calendario"); +?> \ No newline at end of file diff --git a/lang/it/template/common.php b/lang/it/template/common.php new file mode 100644 index 0000000..96e8baa --- /dev/null +++ b/lang/it/template/common.php @@ -0,0 +1,394 @@ +
+ un framework open source progettato per semplificare le attività

+ relative al job scheduling ed al monitoraggio di sistemi/applicazioni."); +define('JS_NOT_ENABLED', "Javascript non è abilitato.
+ Ortro utilizza JavaScript e potrebbe non funzionare correttamente se non abilitato.
+ Abilitare l'esecuzione di JavaScript e ricaricare questa pagina."); +define('HEADER_PROFILE_DESCRIPTION', "Profilo"); +define('HEADER_PROFILE_TOOLTIP', "Modifica il tuo profilo"); +define('HEADER_LOGOUT', "Logout"); +define('TITLE', "Ortro"); +define('ACTION_TITLE', "Azioni"); +define('ACTION_LOCK_UNLOCK', "Blocca/sblocca barra degli strumenti"); +define('ACTION_RELOAD_DESCRIPTION', "Ricarica questa pagina"); +define('ACTION_PREV_PAGE_DESCRIPTION', "Torna alla pagina precedente"); +define('ACTION_NEXT_PAGE_DESCRIPTION', "Vai alla prossima pagina"); +define('ACTION_EDIT_DESCRIPTION', "Modifica"); +define('ACTION_DELETE_DESCRIPTION', "Cancella"); +define('ACTION_DETAIL_DESCRIPTION', "Dettagli"); +define('ACTION_COPY_DESCRIPTION', "Copia"); +define('ACTION_GROUP_DESCRIPTION', "Gruppi"); +define('ACTION_ADD_DESCRIPTION', "Aggiungi"); +define('ACTION_LOCK_DESCRIPTION', "Blocca"); +define('ACTION_UNLOCK_DESCRIPTION', "Sblocca"); +define('ACTION_RUN_DESCRIPTION', "Esegui"); +define('ACTION_PREV_STEP_DESCRIPTION', "Torna allo step precedente"); +define('ACTION_NEXT_STEP_DESCRIPTION', "Vai allo step successivo"); +define('ACTION_KILL_DESCRIPTION', "Interrompi"); +define('REFRESH_TITLE', "Aggiornamento:"); +define('REFRESH_MANUAL', "Manuale"); +define('REFRESH_EVERY_15', "Ogni 15 sec."); +define('REFRESH_EVERY_30', "Ogni 30 sec."); +define('REFRESH_EVERY_60', "Ogni 60 sec."); +define('REFRESH_EVERY_180', "Ogni 180 sec."); +define('BUTTON_ADD', "Aggiungi"); +define('BUTTON_APPLY', "Applica"); +define('BUTTON_SEARCH', "Ricerca"); +define('BUTTON_ADD_IN_GROUP', "Aggiungi al gruppo"); +define('BUTTON_REMOVE_FROM_GROUP', "Rimuovi dal gruppo"); +define('BUTTON_SAVE_SETTING', "Salva le impostazioni"); +define('BUTTON_INSTALL', "Installa"); +define('BUTTON_LOGIN', "Login"); +define('BUTTON_CHANGE_PASSWORD', "Cambia password"); +define('SYSTEM_TOP', "Sistemi: elenco"); +define('SYSTEM_TITLE', "Di seguito la lista di tutti i Sistemi configurati in questa installazione di Ortro.
I Sistemi sono contenitori che consentono il raggruppamento di un insieme di Host."); +define('SYSTEM_ADD_TOP', "Sistemi: aggiungi"); +define('SYSTEM_ADD_TITLE', "Utilizza il modulo seguente per aggiungere un Sistema."); +define('SYSTEM_EDIT_TOP', "Sistemi: modifica"); +define('SYSTEM_EDIT_TITLE', "Utilizza il modulo seguente per modificare un Sistema."); +define('SYSTEM_NAME', "Nome Sistema"); +define('DATABASES_TOP', "Database: elenco"); +define('DATABASES_TITLE', "Di seguito la lista di tutti i Databases monitorati o utilizzati per la generazione di reports in questa installazione di Ortro.
+ Ogni Database è associato con un singolo Host"); +define('DATABASE_ADD_TOP', "Database: aggiungi"); +define('DATABASE_ADD_TITLE', "Utilizza il modulo di seguito per associare un Database con un Host"); +define('DATABASE_EDIT_TOP', "Database: modifica"); +define('DATABASE_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni del database."); +define('DATABASE_DETAILS_TOP', "Database: dettagli"); +define('HOST_TOP', "Hosts: elenco"); +define('HOST_TITLE', "Di seguito la lista di tutti gli Hosts configurati in questa installazione di Ortro.
+ Gli Hosts sono i server dove vengono eseguiti Jobs, ogni Host è associato ad un Sistema"); +define('HOST_ADD_TOP', "Hosts: aggiungi"); +define('HOST_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere un Host ad un Sistema."); +define('HOST_EDIT_TOP', "Hosts: modifica"); +define('HOST_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni dell'host."); +define('JOB_TOP', "Jobs: elenco"); +define('JOB_TITLE', "Di seguito la lista di tutti i Jobs configurati in questa installazione di Ortro.
+ I Jobs sono le unità di lavoro, ogni Job viene eseguito sull'Host specificato."); +define('JOB_ADD_TOP', "Jobs: aggiungi"); +define('JOB_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere un job."); +define('JOB_EDIT_TOP', "Jobs: modifica"); +define('JOB_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni del job."); +define('JOB_DETAILS_TOP', "Jobs: dettagli"); +define('NOTIFICATION_TOP', "Notifiche: elenco"); +define('NOTIFICATION_TITLE', "Di seguito la lista di tutte Notifiche configurate in questa installazione di Ortro.
+ Ogni Notifica è associata con un Job e il relativo invio è funzione dello stato di completamento del Job."); +define('NOTIFICATION_ADD_TOP', "Notifiche: aggiungi"); +define('NOTIFICATION_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere una Notifica."); +define('NOTIFICATION_EDIT_TOP', "Notifiche: modifica"); +define('NOTIFICATION_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni della Notifica."); +define('NOTIFICATION_DETAILS_TOP', "Notifiche: dettagli"); +define('USER_TOP', "Utenti: elenco"); +define('USER_TITLE', "Di seguito la lista di tutti gli Utenti autorizzati per l'accesso a Ortro.
+ I privelegi degli Utenti sono definiti dalla relativa associazione ai Gruppi"); +define('USER_ADD_TOP', "Utenti: aggiungi"); +define('USER_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere un Utente."); +define('USER_EDIT_TOP', "Utenti: modifica"); +define('USER_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni dell'Utente"); +define('USER_DETAILS_TOP', "Utenti: dettagli"); +define('USER_GROUP_EDIT_TOP', "Associazione gruppi: modifica"); +define('USER_GROUP_EDIT_TITLE', "Utilizza il modulo di seguito per modificare l'associazione ai gruppi."); +define('GROUP_TOP', "Gruppi: elenco"); +define('GROUP_TITLE', "Di seguito la lista di tutti i Gruppi configurati in questa installazione di Ortro.
+ L'associazione con un Gruppo definisce le azioni che un Utente può effettuare."); +define('GROUP_ADD_TOP', "Gruppi: aggiungi"); +define('GROUP_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere un Gruppo."); +define('GROUP_EDIT_TOP', "Gruppi: modifica"); +define('GROUP_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni del Gruppo"); +define('ID_ADMIN_TOP', "Gestione Identità: elenco"); +define('ID_ADMIN_TITLE', "Di seguito la lista di tutte le Identità configurate in questa installazione di Ortro.
+ Le Identità sono le credenziali memorizzate utilizzate per effettuare l'accesso ai Databases e alle altre risorse associate con un Job"); +define('ID_ADMIN_ADD_TOP', "Gestione Identità: aggiungi"); +define('ID_ADMIN_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere una nuova Identità ad un Sistema e condividerlo con altri."); +define('ID_ADMIN_EDIT_TOP', "Gestione Identità: modifica"); +define('ID_ADMIN_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni dell'Identità."); +define('ID_ADMIN_SHARE_WITH', "Seleziona il sistema(i) con cui vuoi condividere l'Identità"); +define('SETTING_TITLE', "Compila i campi sottostanti adeguatamente al tuo ambiente."); +define('LDAP_SETTING_TITLE', "Compila i campi sottostanti adeguatamente per il tuo sistema."); +define('PLUGIN_TOP', "Plugin: elenco"); +define('PLUGIN_TITLE', "Ecco la lista dei Plugin configurati in questa installazione di Ortro.
+ Ogni Job configurato utilizza un Plugin."); +define('PLUGIN_ADD_TOP', "Plugin: aggiungi"); +define('PLUGIN_ADD_TITLE', "Utilizza il modulo sottostante per installare il Plugin."); +define('PLUGIN_ADD_ARCHIVE', "Archivio Plugin"); +define('PLUGIN_EDIT_TOP', "Plugin: modifica"); +define('PLUGIN_EDIT_TITLE', "Utilizza il modulo sottostante per modificare le impostazioni del Plugin."); +define('PLUGIN_EDIT_ENV', "Compila i campi sottostanti in relazione al tuo ambiente."); +define('NOTIFICATION_PLUGIN_TOP', "Plugin di notifica: elenco"); +define('NOTIFICATION_PLUGIN_TITLE', "Ecco la lista di tutti i Plugin di Notifica configurati in questa installazione di Ortro.
+ I Plugin di Notifica permetto di definire la modalità con cui un utente può essere notificato sul completanto di Job."); +define('NOTIFICATION_PLUGIN_ADD_TOP', "Plugin di Notifica: aggiungi"); +define('NOTIFICATION_PLUGIN_ADD_TITLE', "Utilizza il modulo sottostante per installare il plugin"); +define('NOTIFICATION_PLUGIN_EDIT_TOP', "Plugin di notifica: modifica"); +define('NOTIFICATION_PLUGIN_EDIT_TITLE', "Utilizza il modulo sottostante per modificare le impostazioni del Plugin di Notifica."); +define('WORKFLOW_TOP', "Workflows: elenco"); +define('WORKFLOW_TITLE', "Di seguito la lista di tutti i Workflows configurati in questa installazione di Ortro.
+ Un Workflow è una sequenza condizionale di Jobs."); +define('WORKFLOW_ADD_TOP', "Workflows: aggiungi"); +define('WORKFLOW_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere un Workflow."); +define('WORKFLOW_EDIT_TOP', "Workflows: modifica"); +define('WORKFLOW_EDIT_TITLE', "Utilizza il modulo di seguito per modificare le impostazioni del Workflow."); +define('WORKFLOW_DETAILS_TOP', "Workflows: dettagli"); +define('FILE_MANAGER_TOP', "Gestione file"); +define('FILE_MANAGER_TITLE', "Utilizza il modulo di seguito per gestire i files in Ortro."); +define('FILE_MANAGER_DISABLED', "Sembra che l'upload dei file sia disabilitato.
Verificare la configurazione del file php.ini"); +define('FILTER', "Filtro"); +define('FILTER_SYSTEM', "Sistema:"); +define('FILTER_JOB', "Job:"); +define('FILTER_STATUS', "Stato:"); +define('FILTER_RESULT', "Risultato:"); +define('FILTER_NOTIFY_TYPE', "Tipologia Notifica:"); +define('FILTER_NOTIFY_ON', "Notifica se:"); +define('FILTER_GROUP', "Gruppo:"); +define('FILTER_USERNAME', "Username:"); +define('FILTER_NAME', "Nome:"); +define('FILTER_MAIL', "Mail:"); +define('FILTER_RESET_TITLE', "Azzera"); +define('FILTER_APPLY_FILTER_TITLE', "Applica Filtro"); +define('FILTER_ALL', "--- Tutti ---"); +define('FILTER_NONE', "---"); +define('FILTER_LOCKED', "Bloccato"); +define('FILTER_RUNNING', "In esecuzione"); +define('FILTER_WAIT', "In attesa"); +define('FILTER_SUCCESS', "Successo"); +define('FILTER_ERROR', "Errore"); +define('FILTER_START', "Inizio"); +define('FILTER_END', "Fine"); +define('FILTER_WORKFLOW', "Workflow:"); +define('FIELD_SYSTEM', "Sistema"); +define('FIELD_DATABASE', "Database(s)"); +define('FIELD_DATABASE_ONLY', "Database"); +define('FIELD_HOSTNAME', "Host"); +define('FIELD_IP', "Hostname/IP"); +define('FIELD_SYSTEM_HOST', "Sistema / Host"); +define('FIELD_PASSWORD', "Password"); +define('FIELD_CONFIRM_PASSWORD', "Conferma password"); +define('FIELD_OLD_PASSWORD', "Vecchia password"); +define('FIELD_LABEL_IDENTITY', "Etichetta identità"); +define('FIELD_USERNAME', "Username"); +define('FIELD_IDENTITY', "Identità"); +define('FIELD_SHARE', "Condividi"); +define('FIELD_SHARED_SYSTEM', "Condivisa con il sistema(i)"); +define('FIELD_LABEL', "Etichetta"); +define('FIELD_DB_NAME_SID', "Nome DB/SID"); +define('FIELD_PORT', "Porta"); +define('FIELD_DBMS', DBMS); +define('FIELD_ADD_HOST', "Aggiungi Host"); +define('FIELD_SELECT_SYSTEM', "--- Sistema ---"); +define('FIELD_SELECT_HOST', "--- Host ---"); +define('FIELD_SELECT_DB', "--- DB ---"); +define('FIELD_SELECT_NONE', "---"); +define('FIELD_SELECT_CATEGORY', "--- Categoria ---"); +define('FIELD_SELECT_JOB', "--- Job ---"); +define('FIELD_SELECT_NOTIFICATION', "--- Notifica ---"); +define('FIELD_SELECT_WORKFLOW', "--- Workflow ---"); +define('FIELD_SELECT_LABEL', "--- Etichetta ---"); +define('FIELD_SELECT_ADD_A_STEP', "--- Aggiungi ---"); +define('FIELD_SELECT_STEP', "--- Step ---"); +define('FIELD_JOB', "Job"); +define('FIELD_JOB_STATUS', "Stato"); +define('FIELD_LAST_JOB_RESULT', "Ultimo risultato"); +define('FIELD_LAST_EXEC_TIME', "Ultima esecuzione"); +define('FIELD_NEXT_EXEC_TIME', "Prossima esecuzione"); +define('FIELD_JOB_PROPERTIES', "Proprietà"); +define('FIELD_JOB_DESCRIPTION', "Descrizione"); +define('FIELD_JOB_PRIORITY', "Priorità (1 - 100)"); +define('FIELD_JOB_PRIORITY_DETAILS', "Priorità"); +define('FIELD_JOB_MAX_ATTEMPT', "Numero massimo di tentativi in caso di errore"); +define('FIELD_JOB_DELAY', "Tempo di attesa per la riesecuzione del job in caso di errore (secondi)"); +define('FIELD_SYSTEM_HOST_DB', "Sistema/Host/Database"); +define('FIELD_JOB_TYPE', "Tipologia del Job"); +define('FIELD_NOTIFY_TYPE', "Tipologia notifica"); +define('FIELD_NOTIFY_JOB_ERROR', "Errore"); +define('FIELD_NOTIFY_JOB_SUCCESS', "Successo"); +define('FIELD_NOTIFY_JOB_END', "Fine"); +define('FIELD_NOTIFY_JOB_START', "Inizio"); +define('FIELD_NOTIFY_SEND_ON', "Invia notifica in caso di job"); +define('FIELD_NOTIFY_METHOD', "Metodo di notifica"); +define('FIELD_NOTIFY_DESCRIPTION', "Descrizione"); +define('FIELD_JOB_SCHEDULE', "Schedulazione"); +define('FIELD_JOB_SCHEDULE_EVERY_5', "Ogni 5"); +define('FIELD_JOB_SCHEDULE_EVERY_15', "Ogni 15"); +define('FIELD_JOB_SCHEDULE_EVERY_30', "Ogni 30"); +define('FIELD_JOB_SCHEDULE_EVERY_6', "Ogni 6"); +define('FIELD_JOB_SCHEDULE_EVERY_12', "Ogni 12"); +define('FIELD_JOB_SCHEDULE_EVERY_MIN', "Ogni minuto"); +define('FIELD_JOB_SCHEDULE_EVERY_5_MIN', "Ogni 5 minuti"); +define('FIELD_JOB_SCHEDULE_EVERY_15_MIN', "Ogni 15 minuti"); +define('FIELD_JOB_SCHEDULE_EVERY_30_MIN', "Ogni 30 minuti"); +define('FIELD_JOB_SCHEDULE_CUSTOM', "Personalizzato"); +define('FIELD_JOB_SCHEDULE_EVERY_HOUR', "Ogni ora"); +define('FIELD_JOB_SCHEDULE_EVERY_6_HOUR', "Ogni 6 ore"); +define('FIELD_JOB_SCHEDULE_EVERY_12_HOUR', "Ogni 12 ore"); +define('FIELD_JOB_SCHEDULE_EVERY_DAY', "Ogni giorno"); +define('FIELD_JOB_SCHEDULE_EVERY_MONTH', "Ogni mese"); +define('FIELD_JOB_SCHEDULE_EVERY_DAY_OF_WEEK', "Ogni giorno della settimana"); +define('FIELD_JOB_SCHEDULE_SUNDAY', "Domenica"); +define('FIELD_JOB_SCHEDULE_MONDAY', "Lunedì"); +define('FIELD_JOB_SCHEDULE_TUESDAY', "Martedì"); +define('FIELD_JOB_SCHEDULE_WEDNEDAY', "Mercoledì"); +define('FIELD_JOB_SCHEDULE_THURSDAY', "Giovedì"); +define('FIELD_JOB_SCHEDULE_FRIDAY', "Venerdì"); +define('FIELD_JOB_SCHEDULE_SATURDAY', "Sabato"); +define('FIELD_JOB_SCHEDULE_ENABLE', "Abilitata"); +define('FIELD_JOB_SCHEDULE_ENABLE_WORKFLOW', "Abilitata solo per i workflow"); +define('FIELD_JOB_SCHEDULE_ENABLE_JOB', "Abilitata solo per i job"); +define('FIELD_JOB_SCHEDULE_DISABLE', "Disabilitata"); +define('FIELD_JOB_SCHEDULE_MINUTE', "Minuti"); +define('FIELD_JOB_SCHEDULE_HOUR', "Ora"); +define('FIELD_JOB_SCHEDULE_DAY_OF_MONTH', "Giorno del mese"); +define('FIELD_JOB_SCHEDULE_MONTH_OF_YEAR', "Mese dell'anno"); +define('FIELD_JOB_SCHEDULE_DAY_OF_WEEK', "Giorno della settimana"); +define('FIELD_JOB_SCHEDULE_MANUAL', "Manuale"); +define('FIELD_USER', "Utente"); +define('FIELD_USER_NAME', "Nome"); +define('FIELD_USER_MAIL', "Mail"); +define('FIELD_USER_GROUP', "Gruppo"); +define('FIELD_USER_ID', "ID Utente"); +define('FIELD_USER_ACTION', "Azione"); +define('FIELD_USER_COMPLETE_NAME', "Nome completo"); +define('FIELD_USER_FIND_ON_LDAP', "Ricerca un utente su LDAP"); +define('FIELD_USER_SEARCH_FOR', "Ricerca per"); +define('FIELD_USER_SEARCH_STRING', "Stringa da ricercare"); +define('FIELD_USER_LANG', "Lingua"); +define('FIELD_USER_AVAILABLE_GROUPS', "Gruppi disponibili"); +define('FIELD_USER_MEMBER_GROUPS', "Gruppi a cui appartiene"); +define('FIELD_GROUP', "Gruppo"); +define('FIELD_ROLE', "Ruolo"); +define('FIELD_SYSTEMS', "Sistema(i)"); +define('FIELD_GROUP_NAME', "Nome Gruppo"); +define('FIELD_CATEGORY', "Categoria"); +define('FIELD_PLUGIN', "Plugin"); +define('FIELD_VERSION', "Versione"); +define('FIELD_AUTHOR', "Autore(i)"); +define('FIELD_DESCRIPTION', "Descrizione"); +define('FIELD_WORKFLOW', "Workflow"); +define('FIELD_WORKFLOW_STATUS', "Stato"); +define('FIELD_WORKFLOW_STEP', "Step"); +define('FIELD_WORKFLOW_JOB_TO_EXEC', "Job da eseguire"); +define('FIELD_WORKFLOW_STEP_TO_EXEC', "Step da eseguire"); +define('FIELD_WORKFLOW_STEP_ERROR', "In caso di errore vai allo step"); +define('FIELD_WORKFLOW_STEP_SUCCESS', "In caso di successo vai allo step"); +define('FIELD_UPLOAD_FILE', "File di cui effettuare l'upload"); +define('FIELD_FILE_MANAGER', "Gestione file"); +define('TOOLTIP_WAIT_FOR_EXEC', "In attesa di esecuzione"); +define('TOOLTIP_RUNNING', "In esecuzione"); +define('TOOLTIP_LOCKED', "Bloccato"); +define('TOOLTIP_JOB_RESULT', "Risultato del Job"); +define('TOOLTIP_JOB_DESCRIPTION', "Descrizione del Job"); +define('TOOLTIP_NOTIFICATION_DETAILS', "Dettagli notifica"); +define('TOOLTIP_IDENTITY_PICKER', "Seleziona Identità"); +define('TOOLTIP_PLUGIN_DESCRIPTION', "Descrizione del Plugin"); +define('TOOLTIP_WORKFLOW_DESCRIPTION', "Descrizione del Workflow"); +define('TOOLTIP_SUCCESS', "Successo"); +define('TOOLTIP_ERROR', "Errore"); +define('TOOLTIP_STEP_EXEC_IMMEDIATE', "Esegue lo step selezionato immediadamente"); +define('TOOLTIP_STEP_WAIT_FOR_SCHED', "Esegue lo step selezionato in accordo con la schedulazione del job"); +define('MSG_SYSTEM_NAME_REQUIRED', "Il nome del sistema è obbligatorio"); +define('MSG_HOST_NAME_REQUIRED', "Host è obbligatorio"); +define('MSG_IP_REQUIRED', "Hostname/IP è obbligatorio"); +define('MSG_IP_NOT_VALID', "IP formato non valido"); +define('MSG_SELECT_A_SYSTEM', "Selezionare un sistema"); +define('MSG_SELECT_A_HOST', "Selezionare un host"); +define('MSG_LABEL_REQUIRED', "Etichetta è obbligatorio"); +define('MSG_SID_REQUIRED', "SID è obbligatorio"); +define('MSG_PORT_REQUIRED', "Porta è obbligatorio"); +define('MSG_PORT_IS_A_NUMBER', "Porta deve essere un numero"); +define('MSG_USERNAME_REQUIRED', "Username è obbligatorio"); +define('MSG_PASSWORD_NOT_MATCH', "Le passwords non corrispondono"); +define('MSG_PASSWORD_REQUIRED', "Password è obbligatorio"); +define('MSG_PASSWORD_MIN_CHAR', "Password deve essere almeno di sei caratteri."); +define('MSG_PRIORITY_REQUIRED', "Priorità è obbligatorio"); +define('MSG_PRIORITY_HAS_VALUE', "Priorità deve avere un valore compreso tra 0 e 100"); +define('MSG_MAX_CHECK_ATTEMPT_IS_NUMERIC', "Numero massimo di tentativi deve essere un numero (Lasciare 0 per disabilitare)"); +define('MSG_MAX_CHECK_ATTEMPT_REQUIRED', "Numero massimo di tentativi è obbligatorio (Lasciare 0 per disabilitare)"); +define('MSG_MAX_DELAY_IS_NUMERIC', "Tempo di attesa deve essere un numero(Lasciare 0 per disabilitare)"); +define('MSG_MAX_DELAY_REQUIRED', "Tempo di attesa è obbligatorio (Lasciare 0 per disabilitare)"); +define('MSG_SELECT_A_JOB_TYPE', "Selezionare una tipologia di job"); +define('MSG_SELECT_A_NOTIFICATION_TYPE', "Selezionare un metodo di notifica"); +define('MSG_SELECT_A_NOTIFICATION_ON', "Selezionare un evento di notifica"); +define('MSG_SELECT_A_VALUE_FOR_MINUTE', "Selezionare un valore per minuti"); +define('MSG_SELECT_A_VALUE_FOR_HOUR', "Selezionare un valore per ore"); +define('MSG_SELECT_A_VALUE_FOR_DAY', "Selezionare un valore per giorno"); +define('MSG_SELECT_A_VALUE_FOR_MONTH', "Selezionare un valore per mese"); +define('MSG_SELECT_A_VALUE_FOR_DAY_OF_WEEK', "Selezionare un valore per giorno della settimana"); +define('MSG_LDAP_CONNECTION_FAILED', "Connessione al server LDAP fallita!!!
Contattare l'amministratore di sistema."); +define('MSG_LDAP_NO_MATCH_FOUND', "Nessuna corrispondenza trovata!!!"); +define('MSG_LDAP_NOT_ENABLED', "ldap module for PHP not enabled."); +define('MSG_COMPLETE_NAME_REQUIRED', "Nome completo è obbligatorio"); +define('MSG_MAIL_REQUIRED', "Mail è obbligatorio"); +define('MSG_MAIL_NOT_VALID', "Mail: formato non valido"); +define('MSG_SEARCH_FIELD_REQUIRED', "Il campo di ricerca è obbligatorio"); +define('MSG_GROUP_NAME_REQUIRED', "Nome Gruppo è obbligatorio"); +define('MSG_AUTHENTICATION_FAILED', "Autenticazione fallita!!!"); +define('MSG_PLUGIN_NO_FURTHER_CONFIGURATION', "Questo plugin non richiede ulteriori configurazioni"); +define('MSG_SELECT_A_VALUE_FOR_GROUP', "Selezionare almeno un gruppo"); +define('MSG_ADD_WORKFLOW_JOB_IS_REQUIRED', "Definire almeno un job prima di procedere."); +define('MSG_SELECT_A_WORKFLOW_OR_JOB', "Selezionare un job da eseguire"); +define('MSG_SELECT_A_FILE', "Selezionare un file"); +define('MSG_SELECT_A_VALUE_FOR_SYSTEM', "Selezionare almeno un sistema"); +define('DISPLAY_REPORTS_TOP', "Di seguito tutti i reports archiviati"); +define('MSG_REPORTS_NOT_AVAILABLE', "Nessun report archiviato."); +define('MSG_DOWNLOAD', "Download"); +define('BUTTON_ORDER_BY_FILENAME', "Nome file"); +define('BUTTON_ORDER_BY_DATE', "Data"); +define('BUTTON_ORDER_BY_SIZE', "Dimensione"); +define('DISPLAY_ARCHIVED_RESULTS_TOP', "Di seguito la lista di tutti i risultati archiviati per"); +define('MSG_ARCHIVED_RESULTS_NOT_AVAILABLE', "Non ci sono risultati archiviati per"); +define('MSG_JOB_ARCHIVED_RESULT', "Risultato"); +define('MSG_JOB_ARCHIVED_EXIT_CODE', "Exit code"); +define('MSG_JOB_ARCHIVED_START_EXEC', "Orario inizio esecuzione"); +define('MSG_JOB_ARCHIVED_END_EXEC', "Orario fine esecuzione"); +define('MSG_FILES_NOT_FOUNDS', "Attualmente non ci sono files per il sistema:"); +define('MSG_PAGE_NOT_FOUND', "Pagina non trovata."); +define('FIELD_OVERWRITE_EXISTING_DB', "Sovrascrivi il database se esiste."); +define('FIELD_DATABASE_ALREADY_EXISTS', "Un database con lo stesso nome già esiste.
Ma i file di configurazione sono stati importati.
Clicca sul link: Controlla/Modifica."); +define('IMPORT_EXPORT_TOP', "Import e Export Tool"); +define('IMPORT_EXPORT_TITLE', "Utilizza i moduli di seguito per effettuare l'import/export delle impostazioni di Ortro."); +define('FIELD_IMPORT_SUBMIT', "Import"); +define('FIELD_EXPORT_SUBMIT', "Export"); +define('FIELD_EXPORT_DESCRIPTION', "Export delle impostazioni di Ortro."); +define('FIELD_EXPORT_SUB_DESCRIPTION', "Effettua il backup del database e dei files di configurazione (tar.gz)"); +define('FIELD_IMPORT_DESCRIPTION', "Import delle impostazioni di Ortro."); +define('FIELD_IMPORT_SUB_DESCRIPTION', "Selezionare un backup da ripristinare."); +define('FIELD_IMPORT_SUCCESS', "Import effettuato con successo.
Verificare il file configure.php. I vecchi files di configurazione sono stati salvati nella directory conf/backup.
Clicca sul link: Controlla/Modifica."); +define('FIELD_EXPORT_SUCCESS', "Export effettauto con successo"); +define('FIELD_EXPORT_ERROR', "Export fallito, il file di backup è corrotto."); +define('FIELD_IMPORT_DB_NOT_SUPPORTED', "Siamo spiacenti ma questa funzionalità non è supportata dal database in uso."); +define('FIELD_CHECK_NEW_SETTINGS_DESCRIPTION', "E' importante controllare ed eventualmente modificare i dati di configurazione."); +define('FIELD_CHECK_NEW_SETTINGS_LINK', "Controlla/Modifica dati"); +define('AUTODISCOVERY_TOP', "Autodiscovery: scansione"); +define('AUTODISCOVERY_TITLE', "Utilizza questo tool per effettuare l'autodiscovery degli Hosts presenti nella tua rete ed aggiungerli successivamente ad un Sistema."); +define('FIELD_AUTODISCOVERY', "Autodiscovery"); +define('FIELD_NMAP_TARGET', "Specifica del target: è possibile utilizzare hostnames, IP addresses, networks, ecc. separati da spazio
Es: scanme.example.org example.com/24 192.168.0.1 10.0.0-255.1-254"); +define('FIELD_AUTODISCOVERY_OS_DETECTION', "Abilita il rilevamento dettagliato dell'OS."); +define('FIELD_NMAP_BINARY', "Path dell'eseguibile Nmap:"); +define('BUTTON_SCAN', "Scansione"); +define('MSG_TARGET_REQUIRED', "Specifica del target è obbligatorio"); +define('MSG_NMAP_BINARY_REQUIRED', "L'eseguibile Nmap è obbligatorio"); +define('FAILED_TO_RESOLVE', "Impossibile risolvere l'hostname/IP specificato:"); +define('AUTODISCOVERY_ADD_TOP', "Autodiscovery: aggiungi"); +define('AUTODISCOVERY_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere gli Hosts ad un Sistema."); +define('FIELD_OS_DETAILS', "Sistema Operativo"); +define('YES', "Si"); +define('NO', "No"); +define('ASK', "Chiedi"); +define('DISABLE', "Disabilita"); +define('ENABLE', "Abilita"); +define('CALENDAR_TOP', "Calendari: elenco"); +define('CALENDAR_TITLE', "Di seguito la lista di tutte i calendari configurati in questa installazione di Ortro.
I calendari sono utilizzati per la personalizzazione della scheluzione dei jobs."); +define('CALENDAR_ADD_TOP', "Calendari: aggiungi"); +define('CALENDAR_ADD_TITLE', "Utilizza il modulo di seguito per aggiungere un calendario."); +define('CALENDAR_EDIT_TOP', "Calendari: modifica"); +define('CALENDAR_EDIT_TITLE', "Utilizza il modulo di seguito per modificare un calendario."); +define('CALENDAR_LABEL', "Calendario"); +define('CALENDAR_SHARE_WITH', "Seleziona il sistema(i) con cui vuoi condividere questo calendario:"); +define('MSG_CALENDAR_REQUIRED', "Calendario è obbligatorio"); +?> \ No newline at end of file diff --git a/lang/it/template/configure_metadata_install.php b/lang/it/template/configure_metadata_install.php new file mode 100644 index 0000000..b989899 --- /dev/null +++ b/lang/it/template/configure_metadata_install.php @@ -0,0 +1,60 @@ + Specifica se ignorare gli errori con la chive host del server in fase di connessione,
uscire immediatamente, oppure chiedere all'utente se continuare. (Default: no)"); +define('CONF_INSTALL_ENV_LOG_LEVEL_DEBUG', DEBUG); +define('CONF_INSTALL_ENV_LOG_LEVEL_INFO', INFO); +define('CONF_INSTALL_ENV_LOG_LEVEL_ERROR', ERROR); +define('CONF_INSTALL_ENV_LOG_LEVEL_DESCRIPTION', "Livello verbosità del Log"); +define('CONF_INSTALL_ENV_ZIP_PATH_DESCRIPTION', "Il percorso assoluto del programma zip. Default è /usr/bin/zip"); +define('CONF_INSTALL_ENV_ZIP_THRESHOLD_DESCRIPTION', "Se abilitata la modalità di archiviazione, i files saranno compressi se la loro grandezza supereranno il valore specificato (byte)"); +define('CONF_INSTALL_ENV_DATEFORMAT_DESCRIPTION', "Formato della data"); +define('CONF_INSTALL_DATEFORMAT_RULE_1_0', "Formato della data è obbligatorio"); +define('CONF_INSTALL_ENV_TIMEFORMAT_DESCRIPTION', "Formato dell' Orario"); +define('CONF_INSTALL_ENV_DATEFORMAT_RULE_1_0', "Orario è obbligatorio"); +define('CONF_INSTALL_XMLRPC_DESCRIPTION', "Configurazione dei servizi XML-RPC"); +define('CONF_INSTALL_XMLRPC_TIMEOUT_DESCRIPTION', "Timeout della sessione (secondi)."); +define('CONF_INSTALL_XMLRPC_TIMEOUT_RULE_1_0', "Timeout della sessione è obbligatorio."); +define('CONF_INSTALL_AUTH_DESCRIPTION',"Configurazione autenticazione"); +define('CONF_INSTALL_AUTH_DEFAULT_DESCRIPTION',"Modalità di autenticazione"); +define('CONF_INSTALL_AUTH_FALLBACK_DESCRIPTION',"Fallback dall'autenticazione"); +define('CONF_INSTALL_ENV_JOB_TIMEOUT_DESCRIPTION', "Valore di timeout per i jobs (minuti). Lascia 0 per disabilitare."); +define('CONF_INSTALL_ENV_JOB_TIMEOUT_RULE_1_0', "Il timeout per il job è obbligatorio."); +?> \ No newline at end of file diff --git a/lang/it/template/configure_metadata_ldap.php b/lang/it/template/configure_metadata_ldap.php new file mode 100644 index 0000000..226f8d3 --- /dev/null +++ b/lang/it/template/configure_metadata_ldap.php @@ -0,0 +1,19 @@ + (lascia in bianco per una ricerca anonima). Eg. cn"); +define('CONF_LDAP_BIND_PASSWORD_DESCRIPTION', "Bind Password: Se necessaria l'autenticazione per ricercare gli utenti, utilizzare questa password
(lasciare in bianco per ricerca anonima)."); +define('CONF_LDAP_SEARCH_ATTRIBUTE_UID_DESCRIPTION', "L'attributo in LDAP che caratterizza il nome per login dell'utente. Es. 'uid' o 'sAMAccountName'
(per ActiveDirectory)"); +define('CONF_LDAP_SEARCH_ATTRIBUTE_CN_DESCRIPTION', "L'attributo in LDAP che caratterizza il nome completo. Es. 'cn'"); +define('CONF_LDAP_SEARCH_ATTRIBUTE_MAIL_DESCRIPTION', "L'attributo in LDAP che caratterizza la mail. Es. 'mail'"); + +?> \ No newline at end of file diff --git a/lang/it/template/install.php b/lang/it/template/install.php new file mode 100644 index 0000000..6b098a3 --- /dev/null +++ b/lang/it/template/install.php @@ -0,0 +1,65 @@ + + relative al job scheduling ed al monitoraggio di sistemi/applicazioni."); +define('INSTALL_CRONTAB_MSG_PART_1', "Aggiungere la seguente linea al crontab dell'utente"); +define('INSTALL_CRONTAB_MSG_PART_2', ":"); +define('INSTALL_CRONTAB_MSG_PART_3', "Cliccare sul bottone 'Modifica crontab' per modificare automaticamente il crontab.
Una copia del crontab attuale dovrebbe essere salvata in:"); +define('INSTALL_CRONTAB_NEW', "Nuovo crontab:"); +define('INSTALL_CRONTAB_OLD', "Vecchio crontab:"); +define('INSTALL_CRONTAB_TITLE', "Aggiungi Ortro al crontab"); +define('INSTALL_EXTENSIONS', "PHP Extensions"); +define('INSTALL_EXTENSIONS_ALERT', "Estensioni non trovate:"); +define('INSTALL_FILE_PERMISSION', "Permessi sui files"); +define('INSTALL_FINISH_MSG_PART_1', "Ortro è stato installato con successo."); +define('INSTALL_FINISH_MSG_PART_2', "Ora puoi effettuare il "); +define('INSTALL_FINISH_MSG_PART_3', "login"); +define('INSTALL_FINISH_MSG_PART_4', " con admin/admin"); +define('INSTALL_FINISH_MSG_PART_5', "Per motivi di sicurezza non dimenticare di rimuovere la cartella di installazione:"); +define('INSTALL_HOW_DESCRIPTION', "Per installare Ortro sul tuo sistema, seleziona la lingua di default e premi sul bottone 'Avanti'"); +define('INSTALL_LICENSE', "Licenza GNU/GPL:"); +define('INSTALL_MENU_CRONTAB', "Crontab"); +define('INSTALL_MENU_DATABASE', "Database"); +define('INSTALL_MENU_FINISH', "Fine"); +define('INSTALL_MENU_LICENSE', "Licenza"); +define('INSTALL_MENU_PLUGINS', "Plugins"); +define('INSTALL_MENU_PRE_INSTALL_CHECK', "Verifica Pre-Installazione"); +define('INSTALL_MENU_SSH', SSH); +define('INSTALL_MENU_TITLE', "Passi dell'installazione"); +define('INSTALL_MENU_WELCOME', "Benvenuto"); +define('INSTALL_MSG_ACTION_CONFIGURE_FILE_NOT_FOUND', "Configure.php non trovato in"); +define('INSTALL_MSG_DB_CREATED_WITH_SUCCESS', "Database creato con successo"); +define('INSTALL_MSG_INSTALL_OK', "I plugins riportati di seguito sono stati installati con successo:"); +define('INSTALL_MSG_NO_PLUGIN_TO_INSTALL', "Non ci sono plugins da installare."); +define('INSTALL_MSG_PLUGIN_FURTHER_CONFIGURATION', "I plugins riportati di seguito richiedono ulteriore configurazione, puoi configurarli dopo aver effettuato il login."); +define('INSTALL_PHP', PHP); +define('INSTALL_PHP_CLI_PATH', "Percorso assoluto di PHP-cli :"); +define('INSTALL_PHP_CLI_VERSION', "Versione PHP cli >= 5.1.0"); +define('INSTALL_PHP_VERSION', "Versione PHP >= 5.1.0"); +define('INSTALL_PLUGIN_NAME', "Nome"); +define('INSTALL_PLUGIN_VERSION', "Versione"); +define('INSTALL_RDBMS', "RDBMS Supportati"); +define('INSTALL_RDBMS_ALERT', "Sembra che la tua installazione di php non supporti nessun database. Verifica e riprova."); +define('INSTALL_SSH', SSH); +define('INSTALL_SSH_CLIENT', "Client SSH"); +define('INSTALL_SSH_CLIENT_PATH', "Percorso assoluto del client SSH:"); +define('INSTALL_SSH_TITLE', "Genera le chiavi ssh pubblica e privata"); +define('INSTALL_WELCOME_DESCRIPTION', "Benvenuti in Ortro"); +define('INSTALL_WRITE_PERMISSION', "è scrivibile"); +define('UPGRADE_CONFIGURE_NOT_FOUND', "configure.php non trovato!!!"); +define('UPGRADE_DB_SCHEMA', "Aggiornamento database..."); +define('UPGRADE_ERROR', "ERRORE:"); +define('UPGRADE_JS', "Aggiornamento files javascript..."); +define('UPGRADE_PLUGINS', "Aggiornamento plugins..."); +define('UPGRADE_REMOVE_INSTALL_DIR', "Rimuovo la directory di installazione..."); + +?> \ No newline at end of file diff --git a/lang/it/template/menu.php b/lang/it/template/menu.php new file mode 100644 index 0000000..702eef4 --- /dev/null +++ b/lang/it/template/menu.php @@ -0,0 +1,49 @@ + \ No newline at end of file diff --git a/lang/it/template/plugin_common.php b/lang/it/template/plugin_common.php new file mode 100644 index 0000000..df3ff2e --- /dev/null +++ b/lang/it/template/plugin_common.php @@ -0,0 +1,26 @@ + 80 , https -> 443)"); +define('PLUGIN_HTTP_PROTOCOL', "Il protocollo da utilizzare"); +define('PLUGIN_IDENTITY', "Identità"); +define('PLUGIN_IDENTITY_RULE', "Identità è obbligatorio"); +define('PLUGIN_METADATA_CONFIGURATION', "Configurazione del plugin"); +define('PLUGIN_PORT', "La porta utilizzata per connettersi alla macchina remota (Lasciare in bianco per la porta predefinita di ssh:22)"); +define('PLUGIN_QUERY', "Query"); +define('PLUGIN_QUERY_RULE', "Query è obbligatorio"); +define('PLUGIN_REQUIRED_PREFIX', "Obbligatorio:"); +define('PLUGIN_RETENTION', "Periodo di archiviazione dei risultati (giorni)"); +define('PLUGIN_USER', "Utente utilizato per collegarsi alla macchina remota."); +define('PLUGIN_USER_RULE', "Utente è obbligatorio"); + +?> \ No newline at end of file diff --git a/lib/Pear/Archive/Tar.php b/lib/Pear/Archive/Tar.php new file mode 100644 index 0000000..5758fd8 --- /dev/null +++ b/lib/Pear/Archive/Tar.php @@ -0,0 +1,1830 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Tar.php,v 1.39 2006/12/22 19:20:08 cellog Exp $ + +require_once 'PEAR.php'; + + +define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001); +define ('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); + +/** +* Creates a (compressed) Tar archive +* +* @author Vincent Blavet +* @version $Revision: 1.39 $ +* @package Archive +*/ +class Archive_Tar extends PEAR +{ + /** + * @var string Name of the Tar + */ + var $_tarname=''; + + /** + * @var boolean if true, the Tar file will be gzipped + */ + var $_compress=false; + + /** + * @var string Type of compression : 'none', 'gz' or 'bz2' + */ + var $_compress_type='none'; + + /** + * @var string Explode separator + */ + var $_separator=' '; + + /** + * @var file descriptor + */ + var $_file=0; + + /** + * @var string Local Tar name of a remote Tar (http:// or ftp://) + */ + var $_temp_tarname=''; + + /** + * @var object PEAR_Error object + */ + var $error_object=NULL; + + // {{{ constructor + /** + * Archive_Tar Class constructor. This flavour of the constructor only + * declare a new Archive_Tar object, identifying it by the name of the + * tar file. + * If the compress argument is set the tar will be read or created as a + * gzip or bz2 compressed TAR file. + * + * @param string $p_tarname The name of the tar archive to create + * @param string $p_compress can be null, 'gz' or 'bz2'. This + * parameter indicates if gzip or bz2 compression + * is required. For compatibility reason the + * boolean value 'true' means 'gz'. + * @access public + */ + function Archive_Tar($p_tarname, $p_compress = null) + { + $this->PEAR(); + $this->_compress = false; + $this->_compress_type = 'none'; + if (($p_compress === null) || ($p_compress == '')) { + if (@file_exists($p_tarname)) { + if ($fp = @fopen($p_tarname, "rb")) { + // look for gzip magic cookie + $data = fread($fp, 2); + fclose($fp); + if ($data == "\37\213") { + $this->_compress = true; + $this->_compress_type = 'gz'; + // No sure it's enought for a magic code .... + } elseif ($data == "BZ") { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + // probably a remote file or some file accessible + // through a stream interface + if (substr($p_tarname, -2) == 'gz') { + $this->_compress = true; + $this->_compress_type = 'gz'; + } elseif ((substr($p_tarname, -3) == 'bz2') || + (substr($p_tarname, -2) == 'bz')) { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + if (($p_compress === true) || ($p_compress == 'gz')) { + $this->_compress = true; + $this->_compress_type = 'gz'; + } else if ($p_compress == 'bz2') { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } else { + die("Unsupported compression type '$p_compress'\n". + "Supported types are 'gz' and 'bz2'.\n"); + return false; + } + } + $this->_tarname = $p_tarname; + if ($this->_compress) { // assert zlib or bz2 extension support + if ($this->_compress_type == 'gz') + $extname = 'zlib'; + else if ($this->_compress_type == 'bz2') + $extname = 'bz2'; + + if (!extension_loaded($extname)) { + PEAR::loadExtension($extname); + } + if (!extension_loaded($extname)) { + die("The extension '$extname' couldn't be found.\n". + "Please make sure your version of PHP was built ". + "with '$extname' support.\n"); + return false; + } + } + } + // }}} + + // {{{ destructor + function _Archive_Tar() + { + $this->_close(); + // ----- Look for a local copy to delete + if ($this->_temp_tarname != '') + @unlink($this->_temp_tarname); + $this->_PEAR(); + } + // }}} + + // {{{ create() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If a file with the same name exist and is writable, it is replaced + * by the new tar. + * The method return false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * For each directory added in the archive, the files and + * sub-directories are also added. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a + * single string with names separated by a single + * blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function create($p_filelist) + { + return $this->createModify($p_filelist, '', ''); + } + // }}} + + // {{{ add() + /** + * This method add the files / directories that are listed in $p_filelist in + * the archive. If the archive does not exist it is created. + * The method return false and a PEAR error text. + * The files and directories listed are only added at the end of the archive, + * even if a file with the same name is already archived. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a + * single string with names separated by a single + * blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function add($p_filelist) + { + return $this->addModify($p_filelist, '', ''); + } + // }}} + + // {{{ extract() + function extract($p_path='') + { + return $this->extractModify($p_path, ''); + } + // }}} + + // {{{ listContent() + function listContent() + { + $v_list_detail = array(); + + if ($this->_openRead()) { + if (!$this->_extractList('', $v_list_detail, "list", '', '')) { + unset($v_list_detail); + $v_list_detail = 0; + } + $this->_close(); + } + + return $v_list_detail; + } + // }}} + + // {{{ createModify() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If the file already exists and is writable, it is replaced by the + * new tar. It is a create and not an add. If the file exists and is + * read-only or is a directory it is not replaced. The method return + * false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * See also addModify() method for file adding properties. + * + * @param array $p_filelist An array of filenames and directory names, + * or a single string with names separated by + * a single blank space. + * @param string $p_add_dir A string which contains a path to be added + * to the memorized path of each element in + * the list. + * @param string $p_remove_dir A string which contains a path to be + * removed from the memorized path of each + * element in the list, when relevant. + * @param array $exclude_filelist An array which contains the filenames and directory names to exclude + * @return boolean true on success, false on error. + * @access public + * @see addModify() + */ + function createModify($p_filelist, $p_add_dir, $p_remove_dir='', $exclude_file_list=array()) + { + $v_result = true; + if ($exclude_file_list=='') + $exclude_file_list = array(); + + if (!$this->_openWrite()) + return false; + + if ($p_filelist != '') { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode($this->_separator, $p_filelist); + else { + $this->_cleanFile(); + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir,$exclude_file_list); + } + + if ($v_result) { + $this->_writeFooter(); + $this->_close(); + } else + $this->_cleanFile(); + + return $v_result; + } + // }}} + + // {{{ addModify() + /** + * This method add the files / directories listed in $p_filelist at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * If a file/dir is already in the archive it will only be added at the + * end of the archive. There is no update of the existing archived + * file/dir. However while extracting the archive, the last file will + * replace the first one. This results in a none optimization of the + * archive size. + * If a file/dir does not exist the file/dir is ignored. However an + * error text is send to PEAR error. + * If a file/dir is not readable the file/dir is ignored. However an + * error text is send to PEAR error. + * + * @param array $p_filelist An array of filenames and directory + * names, or a single string with names + * separated by a single blank space. + * @param string $p_add_dir A string which contains a path to be + * added to the memorized path of each + * element in the list. + * @param string $p_remove_dir A string which contains a path to be + * removed from the memorized path of + * each element in the list, when + * relevant. + * @return true on success, false on error. + * @access public + */ + function addModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!$this->_isArchive()) + $v_result = $this->createModify($p_filelist, $p_add_dir, + $p_remove_dir); + else { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode($this->_separator, $p_filelist); + else { + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); + } + + return $v_result; + } + // }}} + + // {{{ addString() + /** + * This method add a single string as a file at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * + * @param string $p_filename A string which contains the full + * filename path that will be associated + * with the string. + * @param string $p_string The content of the file added in + * the archive. + * @return true on success, false on error. + * @access public + */ + function addString($p_filename, $p_string) + { + $v_result = true; + + if (!$this->_isArchive()) { + if (!$this->_openWrite()) { + return false; + } + $this->_close(); + } + + if (!$this->_openAppend()) + return false; + + // Need to check the get back to the temporary file ? .... + $v_result = $this->_addString($p_filename, $p_string); + + $this->_writeFooter(); + + $this->_close(); + + return $v_result; + } + // }}} + + // {{{ extractModify() + /** + * This method extract all the content of the archive in the directory + * indicated by $p_path. When relevant the memorized path of the + * files/dir can be modified by removing the $p_remove_path path at the + * beginning of the file/dir path. + * While extracting a file, if the directory path does not exists it is + * created. + * While extracting a file, if the file already exists it is replaced + * without looking for last modification date. + * While extracting a file, if the file already exists and is write + * protected, the extraction is aborted. + * While extracting a file, if a directory with the same name already + * exists, the extraction is aborted. + * While extracting a directory, if a file with the same name already + * exists, the extraction is aborted. + * While extracting a file/directory if the destination directory exist + * and is write protected, or does not exist but can not be created, + * the extraction is aborted. + * If after extraction an extracted file does not show the correct + * stored file size, the extraction is aborted. + * When the extraction is aborted, a PEAR error text is set and false + * is returned. However the result can be a partial extraction that may + * need to be manually cleaned. + * + * @param string $p_path The path of the directory where the + * files/dir need to by extracted. + * @param string $p_remove_path Part of the memorized path that can be + * removed if present at the beginning of + * the file/dir path. + * @return boolean true on success, false on error. + * @access public + * @see extractList() + */ + function extractModify($p_path, $p_remove_path) + { + $v_result = true; + $v_list_detail = array(); + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, + "complete", 0, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access public + */ + function extractInString($p_filename) + { + if ($this->_openRead()) { + $v_result = $this->_extractInString($p_filename); + $this->_close(); + } else { + $v_result = NULL; + } + + return $v_result; + } + // }}} + + // {{{ extractList() + /** + * This method extract from the archive only the files indicated in the + * $p_filelist. These files are extracted in the current directory or + * in the directory indicated by the optional $p_path parameter. + * If indicated the $p_remove_path can be used in the same way as it is + * used in extractModify() method. + * @param array $p_filelist An array of filenames and directory names, + * or a single string with names separated + * by a single blank space. + * @param string $p_path The path of the directory where the + * files/dir need to by extracted. + * @param string $p_remove_path Part of the memorized path that can be + * removed if present at the beginning of + * the file/dir path. + * @return true on success, false on error. + * @access public + * @see extractModify() + */ + function extractList($p_filelist, $p_path='', $p_remove_path='') + { + $v_result = true; + $v_list_detail = array(); + + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode($this->_separator, $p_filelist); + else { + $this->_error('Invalid string list'); + return false; + } + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, "partial", + $v_list, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ setAttribute() + /** + * This method set specific attributes of the archive. It uses a variable + * list of parameters, in the format attribute code + attribute values : + * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ','); + * @param mixed $argv variable list of attributes and values + * @return true on success, false on error. + * @access public + */ + function setAttribute() + { + $v_result = true; + + // ----- Get the number of variable list of arguments + if (($v_size = func_num_args()) == 0) { + return true; + } + + // ----- Get the arguments + $v_att_list = &func_get_args(); + + // ----- Read the attributes + $i=0; + while ($i<$v_size) { + + // ----- Look for next option + switch ($v_att_list[$i]) { + // ----- Look for options that request a string value + case ARCHIVE_TAR_ATT_SEPARATOR : + // ----- Check the number of parameters + if (($i+1) >= $v_size) { + $this->_error('Invalid number of parameters for ' + .'attribute ARCHIVE_TAR_ATT_SEPARATOR'); + return false; + } + + // ----- Get the value + $this->_separator = $v_att_list[$i+1]; + $i++; + break; + + default : + $this->_error('Unknow attribute code '.$v_att_list[$i].''); + return false; + } + + // ----- Next attribute + $i++; + } + + return $v_result; + } + // }}} + + // {{{ _error() + function _error($p_message) + { + if (isset($this) && is_a($this, 'PEAR')) { + $this->error_object = &$this->raiseError($p_message, null, null, null, null); + } else { + $this->error_object = &PEAR::raiseError($p_message, null, null, null, null); + } + } + // }}} + + // {{{ _warning() + function _warning($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _isArchive() + function _isArchive($p_filename=NULL) + { + if ($p_filename == NULL) { + $p_filename = $this->_tarname; + } + clearstatcache(); + return @is_file($p_filename); + } + // }}} + + // {{{ _openWrite() + function _openWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "wb9"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "wb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "wb"); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in write mode \'' + .$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openRead() + function _openRead() + { + if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { + + // ----- Look if a local copy need to be done + if ($this->_temp_tarname == '') { + $this->_temp_tarname = uniqid('tar').'.tmp'; + if (!$v_file_from = @fopen($this->_tarname, 'rb')) { + $this->_error('Unable to open in read mode \'' + .$this->_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { + $this->_error('Unable to open in write mode \'' + .$this->_temp_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + while ($v_data = @fread($v_file_from, 1024)) + @fwrite($v_file_to, $v_data); + @fclose($v_file_from); + @fclose($v_file_to); + } + + // ----- File to open if the local copy + $v_filename = $this->_temp_tarname; + + } else + // ----- File to open if the normal Tar file + $v_filename = $this->_tarname; + + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($v_filename, "rb"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($v_filename, "rb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($v_filename, "rb"); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read mode \''.$v_filename.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openReadWrite() + function _openReadWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "r+b"); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read/write mode \'' + .$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _close() + function _close() + { + //if (isset($this->_file)) { + if (is_resource($this->_file)) { + if ($this->_compress_type == 'gz') + @gzclose($this->_file); + else if ($this->_compress_type == 'bz2') + @bzclose($this->_file); + else if ($this->_compress_type == 'none') + @fclose($this->_file); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + $this->_file = 0; + } + + // ----- Look if a local copy need to be erase + // Note that it might be interesting to keep the url for a time : ToDo + if ($this->_temp_tarname != '') { + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } + + return true; + } + // }}} + + // {{{ _cleanFile() + function _cleanFile() + { + $this->_close(); + + // ----- Look for a local copy + if ($this->_temp_tarname != '') { + // ----- Remove the local copy but not the remote tarname + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } else { + // ----- Remove the local tarname file + @unlink($this->_tarname); + } + $this->_tarname = ''; + + return true; + } + // }}} + + // {{{ _writeBlock() + function _writeBlock($p_binary_data, $p_len=null) + { + if (is_resource($this->_file)) { + if ($p_len === null) { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + } else { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data, $p_len); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + } + } + return true; + } + // }}} + + // {{{ _readBlock() + function _readBlock() + { + $v_block = null; + if (is_resource($this->_file)) { + if ($this->_compress_type == 'gz') + $v_block = @gzread($this->_file, 512); + else if ($this->_compress_type == 'bz2') + $v_block = @bzread($this->_file, 512); + else if ($this->_compress_type == 'none') + $v_block = @fread($this->_file, 512); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + } + return $v_block; + } + // }}} + + // {{{ _jumpBlock() + function _jumpBlock($p_len=null) + { + if (is_resource($this->_file)) { + if ($p_len === null) + $p_len = 1; + + if ($this->_compress_type == 'gz') { + @gzseek($this->_file, gztell($this->_file)+($p_len*512)); + } + else if ($this->_compress_type == 'bz2') { + // ----- Replace missing bztell() and bzseek() + for ($i=0; $i<$p_len; $i++) + $this->_readBlock(); + } else if ($this->_compress_type == 'none') + @fseek($this->_file, ftell($this->_file)+($p_len*512)); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + } + return true; + } + // }}} + + // {{{ _writeFooter() + function _writeFooter() + { + if (is_resource($this->_file)) { + // ----- Write the last 0 filled block for end of archive + $v_binary_data = pack('a1024', ''); + $this->_writeBlock($v_binary_data); + } + return true; + } + // }}} + + // {{{ _addList() + function _addList($p_list, $p_add_dir, $p_remove_dir, $exclude_file_list=array()) + { + $v_result=true; + $v_header = array(); + + // ----- Remove potential windows directory separator + $p_add_dir = $this->_translateWinPath($p_add_dir); + $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); + + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if (sizeof($p_list) == 0) + return true; + + foreach ($p_list as $v_filename) { + if (!$v_result) { + break; + } + + // ----- Skip the current tar name + if ($v_filename == $this->_tarname) + continue; + + if (in_array(basename($v_filename),$exclude_file_list)) + continue; + + if ($v_filename == '') + continue; + + if (!file_exists($v_filename)) { + $this->_warning("File '$v_filename' does not exist"); + continue; + } + + // ----- Add the file or directory header + if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) + return false; + + if (@is_dir($v_filename)) { + if (!($p_hdir = opendir($v_filename))) { + $this->_warning("Directory '$v_filename' can not be read"); + continue; + } + while (false !== ($p_hitem = readdir($p_hdir))) { + if (($p_hitem != '.') && ($p_hitem != '..')) { + if ($v_filename != ".") + $p_temp_list[0] = $v_filename.'/'.$p_hitem; + else + $p_temp_list[0] = $p_hitem; + + $v_result = $this->_addList($p_temp_list, + $p_add_dir, + $p_remove_dir, + $exclude_file_list); + } + } + + unset($p_temp_list); + unset($p_hdir); + unset($p_hitem); + } + } + + return $v_result; + } + // }}} + + // {{{ _addFile() + function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + $v_stored_filename = $p_filename; + if (strcmp($p_filename, $p_remove_dir) == 0) { + return true; + } + if ($p_remove_dir != '') { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= '/'; + + if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) + $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); + } + $v_stored_filename = $this->_translateWinPath($v_stored_filename); + if ($p_add_dir != '') { + if (substr($p_add_dir, -1) == '/') + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir.'/'.$v_stored_filename; + } + + $v_stored_filename = $this->_pathReduction($v_stored_filename); + + if ($this->_isArchive($p_filename)) { + if (($v_file = @fopen($p_filename, "rb")) == 0) { + $this->_warning("Unable to open file '".$p_filename + ."' in binary read mode"); + return true; + } + + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + + while (($v_buffer = fread($v_file, 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + fclose($v_file); + + } else { + // ----- Only header for dir + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + } + + return true; + } + // }}} + + // {{{ _addString() + function _addString($p_filename, $p_string) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + + if (!$this->_writeHeaderBlock($p_filename, strlen($p_string), + time(), 384, "", 0, 0)) + return false; + + $i=0; + while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _writeHeader() + function _writeHeader($p_filename, $p_stored_filename) + { + if ($p_stored_filename == '') + $p_stored_filename = $p_filename; + $v_reduce_filename = $this->_pathReduction($p_stored_filename); + + if (strlen($v_reduce_filename) > 99) { + if (!$this->_writeLongHeader($v_reduce_filename)) + return false; + } + + $v_info = stat($p_filename); + $v_uid = sprintf("%6s ", DecOct($v_info[4])); + $v_gid = sprintf("%6s ", DecOct($v_info[5])); + $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename))); + + $v_mtime = sprintf("%11s", DecOct(filemtime($p_filename))); + + if (@is_dir($p_filename)) { + $v_typeflag = "5"; + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_typeflag = ''; + clearstatcache(); + $v_size = sprintf("%11s ", DecOct(filesize($p_filename))); + } + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", + $v_reduce_filename, $v_perms, $v_uid, + $v_gid, $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", + $v_typeflag, $v_linkname, $v_magic, + $v_version, $v_uname, $v_gname, + $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeHeaderBlock() + function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0, + $p_type='', $p_uid=0, $p_gid=0) + { + $p_filename = $this->_pathReduction($p_filename); + + if (strlen($p_filename) > 99) { + if (!$this->_writeLongHeader($p_filename)) + return false; + } + + if ($p_type == "5") { + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_size = sprintf("%11s ", DecOct($p_size)); + } + + $v_uid = sprintf("%6s ", DecOct($p_uid)); + $v_gid = sprintf("%6s ", DecOct($p_gid)); + $v_perms = sprintf("%6s ", DecOct($p_perms)); + + $v_mtime = sprintf("%11s", DecOct($p_mtime)); + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", + $p_filename, $v_perms, $v_uid, $v_gid, + $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", + $p_type, $v_linkname, $v_magic, + $v_version, $v_uname, $v_gname, + $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeLongHeader() + function _writeLongHeader($p_filename) + { + $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); + + $v_typeflag = 'L'; + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", + '././@LongLink', 0, 0, 0, $v_size, 0); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", + $v_typeflag, $v_linkname, $v_magic, + $v_version, $v_uname, $v_gname, + $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + // ----- Write the filename as content of the block + $i=0; + while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _readHeader() + function _readHeader($v_binary_data, &$v_header) + { + if (strlen($v_binary_data)==0) { + $v_header['filename'] = ''; + return true; + } + + if (strlen($v_binary_data) != 512) { + $v_header['filename'] = ''; + $this->_error('Invalid block size : '.strlen($v_binary_data)); + return false; + } + + if (!is_array($v_header)) { + $v_header = array(); + } + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156; $i<512; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + + $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" + ."a8checksum/a1typeflag/a100link/a6magic/a2version/" + ."a32uname/a32gname/a8devmajor/a8devminor", + $v_binary_data); + + // ----- Extract the checksum + $v_header['checksum'] = OctDec(trim($v_data['checksum'])); + if ($v_header['checksum'] != $v_checksum) { + $v_header['filename'] = ''; + + // ----- Look for last block (empty block) + if (($v_checksum == 256) && ($v_header['checksum'] == 0)) + return true; + + $this->_error('Invalid checksum for file "'.$v_data['filename'] + .'" : '.$v_checksum.' calculated, ' + .$v_header['checksum'].' expected'); + return false; + } + + // ----- Extract the properties + $v_header['filename'] = trim($v_data['filename']); + if ($this->_maliciousFilename($v_header['filename'])) { + $this->_error('Malicious .tar detected, file "' . $v_header['filename'] . + '" will not install in desired directory tree'); + return false; + } + $v_header['mode'] = OctDec(trim($v_data['mode'])); + $v_header['uid'] = OctDec(trim($v_data['uid'])); + $v_header['gid'] = OctDec(trim($v_data['gid'])); + $v_header['size'] = OctDec(trim($v_data['size'])); + $v_header['mtime'] = OctDec(trim($v_data['mtime'])); + if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { + $v_header['size'] = 0; + } + $v_header['link'] = trim($v_data['link']); + /* ----- All these fields are removed form the header because + they do not carry interesting info + $v_header[magic] = trim($v_data[magic]); + $v_header[version] = trim($v_data[version]); + $v_header[uname] = trim($v_data[uname]); + $v_header[gname] = trim($v_data[gname]); + $v_header[devmajor] = trim($v_data[devmajor]); + $v_header[devminor] = trim($v_data[devminor]); + */ + + return true; + } + // }}} + + // {{{ _maliciousFilename() + /** + * Detect and report a malicious file name + * + * @param string $file + * @return bool + * @access private + */ + function _maliciousFilename($file) + { + if (strpos($file, '/../') !== false) { + return true; + } + if (strpos($file, '../') === 0) { + return true; + } + return false; + } + // }}} + + // {{{ _readLongHeader() + function _readLongHeader(&$v_header) + { + $v_filename = ''; + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + + // ----- Read the next header + $v_binary_data = $this->_readBlock(); + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + $v_header['filename'] = $v_filename; + if ($this->_maliciousFilename($v_filename)) { + $this->_error('Malicious .tar detected, file "' . $v_filename . + '" will not install in desired directory tree'); + return false; + } + + return true; + } + // }}} + + // {{{ _extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access private + */ + function _extractInString($p_filename) + { + $v_result_str = ""; + + While (strlen($v_binary_data = $this->_readBlock()) != 0) + { + if (!$this->_readHeader($v_binary_data, $v_header)) + return NULL; + + if ($v_header['filename'] == '') + continue; + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return NULL; + } + + if ($v_header['filename'] == $p_filename) { + if ($v_header['typeflag'] == "5") { + $this->_error('Unable to extract in string a directory ' + .'entry {'.$v_header['filename'].'}'); + return NULL; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_result_str .= $this->_readBlock(); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_result_str .= substr($v_content, 0, + ($v_header['size'] % 512)); + } + return $v_result_str; + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } + + return NULL; + } + // }}} + + // {{{ _extractList() + function _extractList($p_path, &$p_list_detail, $p_mode, + $p_file_list, $p_remove_path) + { + $v_result=true; + $v_nb = 0; + $v_extract_all = true; + $v_listing = false; + + $p_path = $this->_translateWinPath($p_path, false); + if ($p_path == '' || (substr($p_path, 0, 1) != '/' + && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) { + $p_path = "./".$p_path; + } + $p_remove_path = $this->_translateWinPath($p_remove_path); + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) + $p_remove_path .= '/'; + $p_remove_path_size = strlen($p_remove_path); + + switch ($p_mode) { + case "complete" : + $v_extract_all = TRUE; + $v_listing = FALSE; + break; + case "partial" : + $v_extract_all = FALSE; + $v_listing = FALSE; + break; + case "list" : + $v_extract_all = FALSE; + $v_listing = TRUE; + break; + default : + $this->_error('Invalid extract mode ('.$p_mode.')'); + return false; + } + + clearstatcache(); + + while (strlen($v_binary_data = $this->_readBlock()) != 0) + { + $v_extract_file = FALSE; + $v_extraction_stopped = 0; + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + if ($v_header['filename'] == '') { + continue; + } + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return false; + } + + if ((!$v_extract_all) && (is_array($p_file_list))) { + // ----- By default no unzip if the file is not found + $v_extract_file = false; + + for ($i=0; $i strlen($p_file_list[$i])) + && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) + == $p_file_list[$i])) { + $v_extract_file = TRUE; + break; + } + } + + // ----- It is a file, so compare the file names + elseif ($p_file_list[$i] == $v_header['filename']) { + $v_extract_file = TRUE; + break; + } + } + } else { + $v_extract_file = TRUE; + } + + // ----- Look if this file need to be extracted + if (($v_extract_file) && (!$v_listing)) + { + if (($p_remove_path != '') + && (substr($v_header['filename'], 0, $p_remove_path_size) + == $p_remove_path)) + $v_header['filename'] = substr($v_header['filename'], + $p_remove_path_size); + if (($p_path != './') && ($p_path != '/')) { + while (substr($p_path, -1) == '/') + $p_path = substr($p_path, 0, strlen($p_path)-1); + + if (substr($v_header['filename'], 0, 1) == '/') + $v_header['filename'] = $p_path.$v_header['filename']; + else + $v_header['filename'] = $p_path.'/'.$v_header['filename']; + } + if (file_exists($v_header['filename'])) { + if ( (@is_dir($v_header['filename'])) + && ($v_header['typeflag'] == '')) { + $this->_error('File '.$v_header['filename'] + .' already exists as a directory'); + return false; + } + if ( ($this->_isArchive($v_header['filename'])) + && ($v_header['typeflag'] == "5")) { + $this->_error('Directory '.$v_header['filename'] + .' already exists as a file'); + return false; + } + if (!is_writeable($v_header['filename'])) { + $this->_error('File '.$v_header['filename'] + .' already exists and is write protected'); + return false; + } + if (filemtime($v_header['filename']) > $v_header['mtime']) { + // To be completed : An error or silent no replace ? + } + } + + // ----- Check the directory availability and create it if necessary + elseif (($v_result + = $this->_dirCheck(($v_header['typeflag'] == "5" + ?$v_header['filename'] + :dirname($v_header['filename'])))) != 1) { + $this->_error('Unable to create path for '.$v_header['filename']); + return false; + } + + if ($v_extract_file) { + if ($v_header['typeflag'] == "5") { + if (!@file_exists($v_header['filename'])) { + if (!@mkdir($v_header['filename'], 0777)) { + $this->_error('Unable to create directory {' + .$v_header['filename'].'}'); + return false; + } + } + } elseif ($v_header['typeflag'] == "2") { + if (!@symlink($v_header['link'], $v_header['filename'])) { + $this->_error('Unable to extract symbolic link {' + .$v_header['filename'].'}'); + return false; + } + } else { + if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { + $this->_error('Error while opening {'.$v_header['filename'] + .'} in write binary mode'); + return false; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, 512); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); + } + + @fclose($v_dest_file); + + // ----- Change the file mode, mtime + @touch($v_header['filename'], $v_header['mtime']); + if ($v_header['mode'] & 0111) { + // make file executable, obey umask + $mode = fileperms($v_header['filename']) | (~umask() & 0111); + @chmod($v_header['filename'], $mode); + } + } + + // ----- Check the file size + clearstatcache(); + if (filesize($v_header['filename']) != $v_header['size']) { + $this->_error('Extracted file '.$v_header['filename'] + .' does not have the correct file size \'' + .filesize($v_header['filename']) + .'\' ('.$v_header['size'] + .' expected). Archive may be corrupted.'); + return false; + } + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + + /* TBC : Seems to be unused ... + if ($this->_compress) + $v_end_of_file = @gzeof($this->_file); + else + $v_end_of_file = @feof($this->_file); + */ + + if ($v_listing || $v_extract_file || $v_extraction_stopped) { + // ----- Log extracted files + if (($v_file_dir = dirname($v_header['filename'])) + == $v_header['filename']) + $v_file_dir = ''; + if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) + $v_file_dir = '/'; + + $p_list_detail[$v_nb++] = $v_header; + if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { + return true; + } + } + } + + return true; + } + // }}} + + // {{{ _openAppend() + function _openAppend() + { + if (filesize($this->_tarname) == 0) + return $this->_openWrite(); + + if ($this->_compress) { + $this->_close(); + + if (!@rename($this->_tarname, $this->_tarname.".tmp")) { + $this->_error('Error while renaming \''.$this->_tarname + .'\' to temporary file \''.$this->_tarname + .'.tmp\''); + return false; + } + + if ($this->_compress_type == 'gz') + $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb"); + elseif ($this->_compress_type == 'bz2') + $v_temp_tar = @bzopen($this->_tarname.".tmp", "rb"); + + if ($v_temp_tar == 0) { + $this->_error('Unable to open file \''.$this->_tarname + .'.tmp\' in binary read mode'); + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if (!$this->_openWrite()) { + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if ($this->_compress_type == 'gz') { + while (!@gzeof($v_temp_tar)) { + $v_buffer = @gzread($v_temp_tar, 512); + if ($v_buffer == ARCHIVE_TAR_END_BLOCK) { + // do not copy end blocks, we will re-make them + // after appending + continue; + } + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + @gzclose($v_temp_tar); + } + elseif ($this->_compress_type == 'bz2') { + while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) { + if ($v_buffer == ARCHIVE_TAR_END_BLOCK) { + continue; + } + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + @bzclose($v_temp_tar); + } + + if (!@unlink($this->_tarname.".tmp")) { + $this->_error('Error while deleting temporary file \'' + .$this->_tarname.'.tmp\''); + } + + } else { + // ----- For not compressed tar, just add files before the last + // one or two 512 bytes block + if (!$this->_openReadWrite()) + return false; + + clearstatcache(); + $v_size = filesize($this->_tarname); + + // We might have zero, one or two end blocks. + // The standard is two, but we should try to handle + // other cases. + fseek($this->_file, $v_size - 1024); + if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { + fseek($this->_file, $v_size - 1024); + } + elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { + fseek($this->_file, $v_size - 512); + } + } + + return true; + } + // }}} + + // {{{ _append() + function _append($p_filelist, $p_add_dir='', $p_remove_dir='') + { + if (!$this->_openAppend()) + return false; + + if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) + $this->_writeFooter(); + + $this->_close(); + + return true; + } + // }}} + + // {{{ _dirCheck() + + /** + * Check if a directory exists and create it (including parent + * dirs) if not. + * + * @param string $p_dir directory to check + * + * @return bool TRUE if the directory exists or was created + */ + function _dirCheck($p_dir) + { + clearstatcache(); + if ((@is_dir($p_dir)) || ($p_dir == '')) + return true; + + $p_parent_dir = dirname($p_dir); + + if (($p_parent_dir != $p_dir) && + ($p_parent_dir != '') && + (!$this->_dirCheck($p_parent_dir))) + return false; + + if (!@mkdir($p_dir, 0777)) { + $this->_error("Unable to create directory '$p_dir'"); + return false; + } + + return true; + } + + // }}} + + // {{{ _pathReduction() + + /** + * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar", + * rand emove double slashes. + * + * @param string $p_dir path to reduce + * + * @return string reduced path + * + * @access private + * + */ + function _pathReduction($p_dir) + { + $v_result = ''; + + // ----- Look for not empty path + if ($p_dir != '') { + // ----- Explode path by directory names + $v_list = explode('/', $p_dir); + + // ----- Study directories from last to first + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + // ----- Ignore it and ignore the $i-1 + $i--; + } + else if ( ($v_list[$i] == '') + && ($i!=(sizeof($v_list)-1)) + && ($i!=0)) { + // ----- Ignore only the double '//' in path, + // but not the first and last / + } else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/' + .$v_result:''); + } + } + } + $v_result = strtr($v_result, '\\', '/'); + return $v_result; + } + + // }}} + + // {{{ _translateWinPath() + function _translateWinPath($p_path, $p_remove_disk_letter=true) + { + if (defined('OS_WINDOWS') && OS_WINDOWS) { + // ----- Look for potential disk letter + if ( ($p_remove_disk_letter) + && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // }}} + +} +?> diff --git a/lib/Pear/Auth.php b/lib/Pear/Auth.php new file mode 100644 index 0000000..0c8540f --- /dev/null +++ b/lib/Pear/Auth.php @@ -0,0 +1,1365 @@ + + * @author Adam Ashley + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Auth.php,v 1.123 2008/04/04 03:50:26 aashley Exp $ + * @link http://pear.php.net/package/Auth + */ + +/** + * Returned if session exceeds idle time + */ +define('AUTH_IDLED', -1); +/** + * Returned if session has expired + */ +define('AUTH_EXPIRED', -2); +/** + * Returned if container is unable to authenticate user/password pair + */ +define('AUTH_WRONG_LOGIN', -3); +/** + * Returned if a container method is not supported. + */ +define('AUTH_METHOD_NOT_SUPPORTED', -4); +/** + * Returned if new Advanced security system detects a breach + */ +define('AUTH_SECURITY_BREACH', -5); +/** + * Returned if checkAuthCallback says session should not continue. + */ +define('AUTH_CALLBACK_ABORT', -6); + +/** + * Auth Log level - INFO + */ +define('AUTH_LOG_INFO', 6); +/** + * Auth Log level - DEBUG + */ +define('AUTH_LOG_DEBUG', 7); + +/** + * Auth Advanced Security - IP Checks + */ +define('AUTH_ADV_IPCHECK', 1); +/** + * Auth Advanced Security - User Agent Checks + */ +define('AUTH_ADV_USERAGENT', 2); +/** + * Auth Advanced Security - Challenge Response + */ +define('AUTH_ADV_CHALLENGE', 3); + + +/** + * PEAR::Auth + * + * The PEAR::Auth class provides methods for creating an + * authentication system using PHP. + * + * @category Authentication + * @package Auth + * @author Martin Jansen + * @author Adam Ashley + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version Release: 1.6.1 File: $Revision: 1.123 $ + * @link http://pear.php.net/package/Auth + */ +class Auth { + + // {{{ properties + + /** + * Auth lifetime in seconds + * + * If this variable is set to 0, auth never expires + * + * @var integer + * @see setExpire(), checkAuth() + */ + var $expire = 0; + + /** + * Has the auth session expired? + * + * @var bool + * @see checkAuth() + */ + var $expired = false; + + /** + * Maximum idletime in seconds + * + * The difference to $expire is, that the idletime gets + * refreshed each time checkAuth() is called. If this + * variable is set to 0, idletime is never checked. + * + * @var integer + * @see setIdle(), checkAuth() + */ + var $idle = 0; + + /** + * Is the maximum idletime over? + * + * @var boolean + * @see checkAuth() + */ + var $idled = false; + + /** + * Storage object + * + * @var object + * @see Auth(), validateLogin() + */ + var $storage = ''; + + /** + * User-defined function that creates the login screen + * + * @var string + */ + var $loginFunction = ''; + + /** + * Should the login form be displayed + * + * @var bool + * @see setShowlogin() + */ + var $showLogin = true; + + /** + * Is Login Allowed from this page + * + * @var bool + * @see setAllowLogin + */ + var $allowLogin = true; + + /** + * Current authentication status + * + * @var string + */ + var $status = ''; + + /** + * Username + * + * @var string + */ + var $username = ''; + + /** + * Password + * + * @var string + */ + var $password = ''; + + /** + * checkAuth callback function name + * + * @var string + * @see setCheckAuthCallback() + */ + var $checkAuthCallback = ''; + + /** + * Login callback function name + * + * @var string + * @see setLoginCallback() + */ + var $loginCallback = ''; + + /** + * Failed Login callback function name + * + * @var string + * @see setFailedLoginCallback() + */ + var $loginFailedCallback = ''; + + /** + * Logout callback function name + * + * @var string + * @see setLogoutCallback() + */ + var $logoutCallback = ''; + + /** + * Auth session-array name + * + * @var string + */ + var $_sessionName = '_authsession'; + + /** + * Package Version + * + * @var string + */ + var $version = "@version@"; + + /** + * Flag to use advanced security + * When set extra checks will be made to see if the + * user's IP or useragent have changed across requests. + * Turned off by default to preserve BC. + * + * @var mixed Boolean to turn all advanced security options on or off + * Array containing named values turning specific advanced + * security features on or off individually + * array( + * AUTH_ADV_IPCHECK => true, + * AUTH_ADV_USERAGENT => true, + * AUTH_ADV_CHALLENGE => true, + * ); + */ + var $advancedsecurity = false; + + /** + * Username key in POST array + * + * @var string + */ + var $_postUsername = 'username'; + + /** + * Password key in POST array + * + * @var string + */ + var $_postPassword = 'password'; + + /** + * Holds a reference to the session auth variable + * @var array + */ + var $session; + + /** + * Holds a reference to the global server variable + * @var array + */ + var $server; + + /** + * Holds a reference to the global post variable + * @var array + */ + var $post; + + /** + * Holds a reference to the global cookie variable + * @var array + */ + var $cookie; + + /** + * A hash to hold various superglobals as reference + * @var array + */ + var $authdata; + + /** + * How many times has checkAuth been called + * @var int + */ + var $authChecks = 0; + + /** + * PEAR::Log object + * + * @var object Log + */ + var $logger = null; + + /** + * Whether to enable logging of behaviour + * + * @var boolean + */ + var $enableLogging = false; + + /** + * Whether to regenerate session id everytime start is called + * + * @var boolean + */ + var $regenerateSessionId = false; + + // }}} + // {{{ Auth() [constructor] + + /** + * Constructor + * + * Set up the storage driver. + * + * @param string Type of the storage driver + * @param mixed Additional options for the storage driver + * (example: if you are using DB as the storage + * driver, you have to pass the dsn string here) + * + * @param string Name of the function that creates the login form + * @param boolean Should the login form be displayed if neccessary? + * @return void + */ + function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true) + { + $this->applyAuthOptions($options); + + // Start the session suppress error if already started + if(!session_id()){ + @session_start(); + if(!session_id()) { + // Throw error + include_once 'PEAR.php'; + PEAR::throwError('Session could not be started by Auth, ' + .'possibly headers are already sent, try putting ' + .'ob_start in the beginning of your script'); + } + } + + // Make Sure Auth session variable is there + if(!isset($_SESSION[$this->_sessionName])) { + $_SESSION[$this->_sessionName] = array(); + } + + // Assign Some globals to internal references, this will replace _importGlobalVariable + $this->session =& $_SESSION[$this->_sessionName]; + $this->server =& $_SERVER; + $this->post =& $_POST; + $this->cookie =& $_COOKIE; + + if ($loginFunction != '' && is_callable($loginFunction)) { + $this->loginFunction = $loginFunction; + } + + if (is_bool($showLogin)) { + $this->showLogin = $showLogin; + } + + if (is_object($storageDriver)) { + $this->storage =& $storageDriver; + // Pass a reference to auth to the container, ugly but works + // this is used by the DB container to use method setAuthData not staticaly. + $this->storage->_auth_obj =& $this; + } else { + // $this->storage = $this->_factory($storageDriver, $options); + // + $this->storage_driver = $storageDriver; + $this->storage_options =& $options; + } + } + + // }}} + // {{{ applyAuthOptions() + + /** + * Set the Auth options + * + * Some options which are Auth specific will be applied + * the rest will be left for usage by the container + * + * @param array An array of Auth options + * @return array The options which were not applied + * @access private + */ + function &applyAuthOptions(&$options) + { + if(is_array($options)){ + if (!empty($options['sessionName'])) { + $this->_sessionName = $options['sessionName']; + unset($options['sessionName']); + } + if (isset($options['allowLogin'])) { + $this->allowLogin = $options['allowLogin']; + unset($options['allowLogin']); + } + if (!empty($options['postUsername'])) { + $this->_postUsername = $options['postUsername']; + unset($options['postUsername']); + } + if (!empty($options['postPassword'])) { + $this->_postPassword = $options['postPassword']; + unset($options['postPassword']); + } + if (isset($options['advancedsecurity'])) { + $this->advancedsecurity = $options['advancedsecurity']; + unset($options['advancedsecurity']); + } + if (isset($options['enableLogging'])) { + $this->enableLogging = $options['enableLogging']; + unset($options['enableLogging']); + } + if (isset($options['regenerateSessionId']) && is_bool($options['regenerateSessionId'])) { + $this->regenerateSessionId = $options['regenerateSessionId']; + } + } + return($options); + } + + // }}} + // {{{ _loadStorage() + + /** + * Load Storage Driver if not already loaded + * + * Suspend storage instantiation to make Auth lighter to use + * for calls which do not require login + * + * @return bool True if the conainer is loaded, false if the container + * is already loaded + * @access private + */ + function _loadStorage() + { + if(!is_object($this->storage)) { + $this->storage =& $this->_factory($this->storage_driver, + $this->storage_options); + $this->storage->_auth_obj =& $this; + $this->log('Loaded storage container ('.$this->storage_driver.')', AUTH_LOG_DEBUG); + return(true); + } + return(false); + } + + // }}} + // {{{ _factory() + + /** + * Return a storage driver based on $driver and $options + * + * @static + * @param string $driver Type of storage class to return + * @param string $options Optional parameters for the storage class + * @return object Object Storage object + * @access private + */ + function &_factory($driver, $options = '') + { + $storage_class = 'Auth_Container_' . $driver; + include_once 'Auth/Container/' . $driver . '.php'; + $obj =& new $storage_class($options); + return $obj; + } + + // }}} + // {{{ assignData() + + /** + * Assign data from login form to internal values + * + * This function takes the values for username and password + * from $HTTP_POST_VARS/$_POST and assigns them to internal variables. + * If you wish to use another source apart from $HTTP_POST_VARS/$_POST, + * you have to derive this function. + * + * @global $HTTP_POST_VARS, $_POST + * @see Auth + * @return void + * @access private + */ + function assignData() + { + $this->log('Auth::assignData() called.', AUTH_LOG_DEBUG); + + if ( isset($this->post[$this->_postUsername]) + && $this->post[$this->_postUsername] != '') { + $this->username = (get_magic_quotes_gpc() == 1 + ? stripslashes($this->post[$this->_postUsername]) + : $this->post[$this->_postUsername]); + } + if ( isset($this->post[$this->_postPassword]) + && $this->post[$this->_postPassword] != '') { + $this->password = (get_magic_quotes_gpc() == 1 + ? stripslashes($this->post[$this->_postPassword]) + : $this->post[$this->_postPassword] ); + } + } + + // }}} + // {{{ start() + + /** + * Start new auth session + * + * @return void + * @access public + */ + function start() + { + $this->log('Auth::start() called.', AUTH_LOG_DEBUG); + + // #10729 - Regenerate session id here if we are generating it on every + // page load. + if ($this->regenerateSessionId) { + session_regenerate_id(true); + } + + $this->assignData(); + if (!$this->checkAuth() && $this->allowLogin) { + $this->login(); + } + } + + // }}} + // {{{ login() + + /** + * Login function + * + * @return void + * @access private + */ + function login() + { + $this->log('Auth::login() called.', AUTH_LOG_DEBUG); + + $login_ok = false; + $this->_loadStorage(); + + // Check if using challenge response + (isset($this->post['authsecret']) && $this->post['authsecret'] == 1) + ? $usingChap = true + : $usingChap = false; + + + // When the user has already entered a username, we have to validate it. + if (!empty($this->username)) { + if (true === $this->storage->fetchData($this->username, $this->password, $usingChap)) { + $this->session['challengekey'] = md5($this->username.$this->password); + $login_ok = true; + $this->log('Successful login.', AUTH_LOG_INFO); + } + } + + if (!empty($this->username) && $login_ok) { + $this->setAuth($this->username); + if (is_callable($this->loginCallback)) { + $this->log('Calling loginCallback ('.$this->loginCallback.').', AUTH_LOG_DEBUG); + call_user_func_array($this->loginCallback, array($this->username, &$this)); + } + } + + // If the login failed or the user entered no username, + // output the login screen again. + if (!empty($this->username) && !$login_ok) { + $this->log('Incorrect login.', AUTH_LOG_INFO); + $this->status = AUTH_WRONG_LOGIN; + if (is_callable($this->loginFailedCallback)) { + $this->log('Calling loginFailedCallback ('.$this->loginFailedCallback.').', AUTH_LOG_DEBUG); + call_user_func_array($this->loginFailedCallback, array($this->username, &$this)); + } + } + + if ((empty($this->username) || !$login_ok) && $this->showLogin) { + $this->log('Rendering Login Form.', AUTH_LOG_INFO); + if (is_callable($this->loginFunction)) { + $this->log('Calling loginFunction ('.$this->loginFunction.').', AUTH_LOG_DEBUG); + call_user_func_array($this->loginFunction, array($this->username, $this->status, &$this)); + } else { + // BC fix Auth used to use drawLogin for this + // call is sub classes implement this + if (is_callable(array($this, 'drawLogin'))) { + $this->log('Calling Auth::drawLogin()', AUTH_LOG_DEBUG); + return $this->drawLogin($this->username, $this); + } + + $this->log('Using default Auth_Frontend_Html', AUTH_LOG_DEBUG); + + // New Login form + include_once 'Auth/Frontend/Html.php'; + return Auth_Frontend_Html::render($this, $this->username); + } + } else { + return; + } + } + + // }}} + // {{{ setExpire() + + /** + * Set the maximum expire time + * + * @param integer time in seconds + * @param bool add time to current expire time or not + * @return void + * @access public + */ + function setExpire($time, $add = false) + { + $add ? $this->expire += $time : $this->expire = $time; + } + + // }}} + // {{{ setIdle() + + /** + * Set the maximum idle time + * + * @param integer time in seconds + * @param bool add time to current maximum idle time or not + * @return void + * @access public + */ + function setIdle($time, $add = false) + { + $add ? $this->idle += $time : $this->idle = $time; + } + + // }}} + // {{{ setSessionName() + + /** + * Set name of the session to a customized value. + * + * If you are using multiple instances of PEAR::Auth + * on the same domain, you can change the name of + * session per application via this function. + * This will chnage the name of the session variable + * auth uses to store it's data in the session + * + * @param string New name for the session + * @return void + * @access public + */ + function setSessionName($name = 'session') + { + $this->_sessionName = '_auth_'.$name; + // Make Sure Auth session variable is there + if(!isset($_SESSION[$this->_sessionName])) { + $_SESSION[$this->_sessionName] = array(); + } + $this->session =& $_SESSION[$this->_sessionName]; + } + + // }}} + // {{{ setShowLogin() + + /** + * Should the login form be displayed if neccessary? + * + * @param bool show login form or not + * @return void + * @access public + */ + function setShowLogin($showLogin = true) + { + $this->showLogin = $showLogin; + } + + // }}} + // {{{ setAllowLogin() + + /** + * Should the login form be displayed if neccessary? + * + * @param bool show login form or not + * @return void + * @access public + */ + function setAllowLogin($allowLogin = true) + { + $this->allowLogin = $allowLogin; + } + + // }}} + // {{{ setCheckAuthCallback() + + /** + * Register a callback function to be called whenever the validity of the login is checked + * The function will receive two parameters, the username and a reference to the auth object. + * + * @param string callback function name + * @return void + * @access public + * @since Method available since Release 1.4.3 + */ + function setCheckAuthCallback($checkAuthCallback) + { + $this->checkAuthCallback = $checkAuthCallback; + } + + // }}} + // {{{ setLoginCallback() + + /** + * Register a callback function to be called on user login. + * The function will receive two parameters, the username and a reference to the auth object. + * + * @param string callback function name + * @return void + * @see setLogoutCallback() + * @access public + */ + function setLoginCallback($loginCallback) + { + $this->loginCallback = $loginCallback; + } + + // }}} + // {{{ setFailedLoginCallback() + + /** + * Register a callback function to be called on failed user login. + * The function will receive two parameters, the username and a reference to the auth object. + * + * @param string callback function name + * @return void + * @access public + */ + function setFailedLoginCallback($loginFailedCallback) + { + $this->loginFailedCallback = $loginFailedCallback; + } + + // }}} + // {{{ setLogoutCallback() + + /** + * Register a callback function to be called on user logout. + * The function will receive three parameters, the username and a reference to the auth object. + * + * @param string callback function name + * @return void + * @see setLoginCallback() + * @access public + */ + function setLogoutCallback($logoutCallback) + { + $this->logoutCallback = $logoutCallback; + } + + // }}} + // {{{ setAuthData() + + /** + * Register additional information that is to be stored + * in the session. + * + * @param string Name of the data field + * @param mixed Value of the data field + * @param boolean Should existing data be overwritten? (default + * is true) + * @return void + * @access public + */ + function setAuthData($name, $value, $overwrite = true) + { + if (!empty($this->session['data'][$name]) && $overwrite == false) { + return; + } + $this->session['data'][$name] = $value; + } + + // }}} + // {{{ getAuthData() + + /** + * Get additional information that is stored in the session. + * + * If no value for the first parameter is passed, the method will + * return all data that is currently stored. + * + * @param string Name of the data field + * @return mixed Value of the data field. + * @access public + */ + function getAuthData($name = null) + { + if (!isset($this->session['data'])) { + return null; + } + if(!isset($name)) { + return $this->session['data']; + } + if (isset($name) && isset($this->session['data'][$name])) { + return $this->session['data'][$name]; + } + return null; + } + + // }}} + // {{{ setAuth() + + /** + * Register variable in a session telling that the user + * has logged in successfully + * + * @param string Username + * @return void + * @access public + */ + function setAuth($username) + { + $this->log('Auth::setAuth() called.', AUTH_LOG_DEBUG); + + // #10729 - Regenerate session id here only if generating at login only + // Don't do it if we are regenerating on every request so we don't + // regenerate it twice in one request. + if (!$this->regenerateSessionId) { + // #2021 - Change the session id to avoid session fixation attacks php 4.3.3 > + session_regenerate_id(true); + } + + if (!isset($this->session) || !is_array($this->session)) { + $this->session = array(); + } + + if (!isset($this->session['data'])) { + $this->session['data'] = array(); + } + + $this->session['sessionip'] = isset($this->server['REMOTE_ADDR']) + ? $this->server['REMOTE_ADDR'] + : ''; + $this->session['sessionuseragent'] = isset($this->server['HTTP_USER_AGENT']) + ? $this->server['HTTP_USER_AGENT'] + : ''; + $this->session['sessionforwardedfor'] = isset($this->server['HTTP_X_FORWARDED_FOR']) + ? $this->server['HTTP_X_FORWARDED_FOR'] + : ''; + + // This should be set by the container to something more safe + // Like md5(passwd.microtime) + if(empty($this->session['challengekey'])) { + $this->session['challengekey'] = md5($username.microtime()); + } + + $this->session['challengecookie'] = md5($this->session['challengekey'].microtime()); + setcookie('authchallenge', $this->session['challengecookie'], 0, '/'); + + $this->session['registered'] = true; + $this->session['username'] = $username; + $this->session['timestamp'] = time(); + $this->session['idle'] = time(); + } + + // }}} + // {{{ setAdvancedSecurity() + + /** + * Enables advanced security checks + * + * Currently only ip change and useragent change + * are detected + * @todo Add challenge cookies - Create a cookie which changes every time + * and contains some challenge key which the server can verify with + * a session var cookie might need to be crypted (user pass) + * @param bool Enable or disable + * @return void + * @access public + */ + function setAdvancedSecurity($flag=true) + { + $this->advancedsecurity = $flag; + } + + // }}} + // {{{ checkAuth() + + /** + * Checks if there is a session with valid auth information. + * + * @access public + * @return boolean Whether or not the user is authenticated. + */ + function checkAuth() + { + $this->log('Auth::checkAuth() called.', AUTH_LOG_DEBUG); + $this->authChecks++; + if (isset($this->session)) { + // Check if authentication session is expired + if ( $this->expire > 0 + && isset($this->session['timestamp']) + && ($this->session['timestamp'] + $this->expire) < time()) { + $this->log('Session Expired', AUTH_LOG_INFO); + $this->expired = true; + $this->status = AUTH_EXPIRED; + $this->logout(); + return false; + } + + // Check if maximum idle time is reached + if ( $this->idle > 0 + && isset($this->session['idle']) + && ($this->session['idle'] + $this->idle) < time()) { + $this->log('Session Idle Time Reached', AUTH_LOG_INFO); + $this->idled = true; + $this->status = AUTH_IDLED; + $this->logout(); + return false; + } + + if ( isset($this->session['registered']) + && isset($this->session['username']) + && $this->session['registered'] == true + && $this->session['username'] != '') { + Auth::updateIdle(); + + if ($this->_isAdvancedSecurityEnabled()) { + $this->log('Advanced Security Mode Enabled.', AUTH_LOG_DEBUG); + + // Only Generate the challenge once + if ( $this->authChecks == 1 + && $this->_isAdvancedSecurityEnabled(AUTH_ADV_CHALLENGE)) { + $this->log('Generating new Challenge Cookie.', AUTH_LOG_DEBUG); + $this->session['challengecookieold'] = $this->session['challengecookie']; + $this->session['challengecookie'] = md5($this->session['challengekey'].microtime()); + setcookie('authchallenge', $this->session['challengecookie'], 0, '/'); + } + + // Check for ip change + if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_IPCHECK) + && isset($this->server['REMOTE_ADDR']) + && $this->session['sessionip'] != $this->server['REMOTE_ADDR']) { + $this->log('Security Breach. Remote IP Address changed.', AUTH_LOG_INFO); + // Check if the IP of the user has changed, if so we + // assume a man in the middle attack and log him out + $this->expired = true; + $this->status = AUTH_SECURITY_BREACH; + $this->logout(); + return false; + } + + // Check for ip change (if connected via proxy) + if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_IPCHECK) + && isset($this->server['HTTP_X_FORWARDED_FOR']) + && $this->session['sessionforwardedfor'] != $this->server['HTTP_X_FORWARDED_FOR']) { + $this->log('Security Breach. Forwarded For IP Address changed.', AUTH_LOG_INFO); + // Check if the IP of the user connecting via proxy has + // changed, if so we assume a man in the middle attack + // and log him out. + $this->expired = true; + $this->status = AUTH_SECURITY_BREACH; + $this->logout(); + return false; + } + + // Check for useragent change + if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_USERAGENT) + && isset($this->server['HTTP_USER_AGENT']) + && $this->session['sessionuseragent'] != $this->server['HTTP_USER_AGENT']) { + $this->log('Security Breach. User Agent changed.', AUTH_LOG_INFO); + // Check if the User-Agent of the user has changed, if + // so we assume a man in the middle attack and log him out + $this->expired = true; + $this->status = AUTH_SECURITY_BREACH; + $this->logout(); + return false; + } + + // Check challenge cookie here, if challengecookieold is not set + // this is the first time and check is skipped + // TODO when user open two pages similtaneuly (open in new window,open + // in tab) auth breach is caused find out a way around that if possible + if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_CHALLENGE) + && isset($this->session['challengecookieold']) + && $this->session['challengecookieold'] != $this->cookie['authchallenge']) { + $this->log('Security Breach. Challenge Cookie mismatch.', AUTH_LOG_INFO); + $this->expired = true; + $this->status = AUTH_SECURITY_BREACH; + $this->logout(); + $this->login(); + return false; + } + } + + if (is_callable($this->checkAuthCallback)) { + $this->log('Calling checkAuthCallback ('.$this->checkAuthCallback.').', AUTH_LOG_DEBUG); + $checkCallback = call_user_func_array($this->checkAuthCallback, array($this->username, &$this)); + if ($checkCallback == false) { + $this->log('checkAuthCallback failed.', AUTH_LOG_INFO); + $this->expired = true; + $this->status = AUTH_CALLBACK_ABORT; + $this->logout(); + return false; + } + } + + $this->log('Session OK.', AUTH_LOG_INFO); + return true; + } + } else { + $this->log('Unable to locate session storage.', AUTH_LOG_DEBUG); + return false; + } + $this->log('No login session.', AUTH_LOG_DEBUG); + return false; + } + + // }}} + // {{{ staticCheckAuth() [static] + + /** + * Statically checks if there is a session with valid auth information. + * + * @access public + * @see checkAuth + * @return boolean Whether or not the user is authenticated. + * @static + */ + function staticCheckAuth($options = null) + { + static $staticAuth; + if(!isset($staticAuth)) { + $staticAuth = new Auth('null', $options); + } + $staticAuth->log('Auth::staticCheckAuth() called', AUTH_LOG_DEBUG); + return $staticAuth->checkAuth(); + } + + // }}} + // {{{ getAuth() + + /** + * Has the user been authenticated? + * + * Is there a valid login session. Previously this was different from + * checkAuth() but now it is just an alias. + * + * @access public + * @return bool True if the user is logged in, otherwise false. + */ + function getAuth() + { + $this->log('Auth::getAuth() called.', AUTH_LOG_DEBUG); + return $this->checkAuth(); + } + + // }}} + // {{{ logout() + + /** + * Logout function + * + * This function clears any auth tokens in the currently + * active session and executes the logout callback function, + * if any + * + * @access public + * @return void + */ + function logout() + { + $this->log('Auth::logout() called.', AUTH_LOG_DEBUG); + + if (is_callable($this->logoutCallback) && isset($this->session['username'])) { + $this->log('Calling logoutCallback ('.$this->logoutCallback.').', AUTH_LOG_DEBUG); + call_user_func_array($this->logoutCallback, array($this->session['username'], &$this)); + } + + $this->username = ''; + $this->password = ''; + + $this->session = null; + } + + // }}} + // {{{ updateIdle() + + /** + * Update the idletime + * + * @access private + * @return void + */ + function updateIdle() + { + $this->session['idle'] = time(); + } + + // }}} + // {{{ getUsername() + + /** + * Get the username + * + * @return string + * @access public + */ + function getUsername() + { + if (isset($this->session['username'])) { + return($this->session['username']); + } + return(''); + } + + // }}} + // {{{ getStatus() + + /** + * Get the current status + * + * @return string + * @access public + */ + function getStatus() + { + return $this->status; + } + + // }}} + // {{{ getPostUsernameField() + + /** + * Gets the post varible used for the username + * + * @return string + * @access public + */ + function getPostUsernameField() + { + return($this->_postUsername); + } + + // }}} + // {{{ getPostPasswordField() + + /** + * Gets the post varible used for the username + * + * @return string + * @access public + */ + function getPostPasswordField() + { + return($this->_postPassword); + } + + // }}} + // {{{ sessionValidThru() + + /** + * Returns the time up to the session is valid + * + * @access public + * @return integer + */ + function sessionValidThru() + { + if (!isset($this->session['idle'])) { + return 0; + } + if ($this->idle == 0) { + return 0; + } + return ($this->session['idle'] + $this->idle); + } + + // }}} + // {{{ listUsers() + + /** + * List all users that are currently available in the storage + * container + * + * @access public + * @return array + */ + function listUsers() + { + $this->log('Auth::listUsers() called.', AUTH_LOG_DEBUG); + $this->_loadStorage(); + return $this->storage->listUsers(); + } + + // }}} + // {{{ addUser() + + /** + * Add user to the storage container + * + * @access public + * @param string Username + * @param string Password + * @param mixed Additional parameters + * @return mixed True on success, PEAR error object on error + * and AUTH_METHOD_NOT_SUPPORTED otherwise. + */ + function addUser($username, $password, $additional = '') + { + $this->log('Auth::addUser() called.', AUTH_LOG_DEBUG); + $this->_loadStorage(); + return $this->storage->addUser($username, $password, $additional); + } + + // }}} + // {{{ removeUser() + + /** + * Remove user from the storage container + * + * @access public + * @param string Username + * @return mixed True on success, PEAR error object on error + * and AUTH_METHOD_NOT_SUPPORTED otherwise. + */ + function removeUser($username) + { + $this->log('Auth::removeUser() called.', AUTH_LOG_DEBUG); + $this->_loadStorage(); + return $this->storage->removeUser($username); + } + + // }}} + // {{{ changePassword() + + /** + * Change password for user in the storage container + * + * @access public + * @param string Username + * @param string The new password + * @return mixed True on success, PEAR error object on error + * and AUTH_METHOD_NOT_SUPPORTED otherwise. + */ + function changePassword($username, $password) + { + $this->log('Auth::changePassword() called', AUTH_LOG_DEBUG); + $this->_loadStorage(); + return $this->storage->changePassword($username, $password); + } + + // }}} + // {{{ log() + + /** + * Log a message from the Auth system + * + * @access public + * @param string The message to log + * @param string The log level to log the message under. See the Log documentation for more info. + * @return boolean + */ + function log($message, $level = AUTH_LOG_DEBUG) + { + if (!$this->enableLogging) return false; + + $this->_loadLogger(); + + $this->logger->log('AUTH: '.$message, $level); + } + + // }}} + // {{{ _loadLogger() + + /** + * Load Log object if not already loaded + * + * Suspend logger instantiation to make Auth lighter to use + * for calls which do not require logging + * + * @return bool True if the logger is loaded, false if the logger + * is already loaded + * @access private + */ + function _loadLogger() + { + if(is_null($this->logger)) { + if (!class_exists('Log')) { + include_once 'Log.php'; + } + $this->logger =& Log::singleton('null', + null, + 'auth['.getmypid().']', + array(), + AUTH_LOG_DEBUG); + return(true); + } + return(false); + } + + // }}} + // {{{ attachLogObserver() + + /** + * Attach an Observer to the Auth Log Source + * + * @param object Log_Observer A Log Observer instance + * @return boolean + */ + function attachLogObserver(&$observer) { + + $this->_loadLogger(); + + return $this->logger->attach($observer); + + } + + // }}} + // {{{ _isAdvancedSecurityEnabled() + + /** + * Is advanced security enabled? + * + * Pass one of the Advanced Security constants as the first parameter + * to check if that advanced security check is enabled. + * + * @param integer + * @return boolean + */ + function _isAdvancedSecurityEnabled($feature = null) { + + if (is_null($feature)) { + + if ($this->advancedsecurity === true) + return true; + + if ( is_array($this->advancedsecurity) + && in_array(true, $this->advancedsecurity, true)) + return true; + + return false; + + } else { + + if (is_array($this->advancedsecurity)) { + + if ( isset($this->advancedsecurity[$feature]) + && $this->advancedsecurity[$feature] == true) + return true; + + return false; + + } + + return (bool)$this->advancedsecurity; + + } + + } + + // }}} + +} +?> diff --git a/lib/Pear/Auth/Auth.php b/lib/Pear/Auth/Auth.php new file mode 100644 index 0000000..78c7f5d --- /dev/null +++ b/lib/Pear/Auth/Auth.php @@ -0,0 +1,30 @@ + + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Auth.php,v 1.4 2006/03/02 06:53:08 aashley Exp $ + * @link http://pear.php.net/package/Auth + * @deprecated File deprecated since Release 1.2.0 + */ + +/** + * Include Auth package + */ +require_once 'Auth.php'; + +?> diff --git a/lib/Pear/Auth/Container.php b/lib/Pear/Auth/Container.php new file mode 100644 index 0000000..75d66d3 --- /dev/null +++ b/lib/Pear/Auth/Container.php @@ -0,0 +1,262 @@ + + * @author Adam Ashley + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Container.php,v 1.28 2007/06/12 03:11:26 aashley Exp $ + * @link http://pear.php.net/package/Auth + */ + +/** + * Storage class for fetching login data + * + * @category Authentication + * @package Auth + * @author Martin Jansen + * @author Adam Ashley + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version Release: 1.6.1 File: $Revision: 1.28 $ + * @link http://pear.php.net/package/Auth + */ +class Auth_Container +{ + + // {{{ properties + + /** + * User that is currently selected from the storage container. + * + * @access public + */ + var $activeUser = ""; + + /** + * The Auth object this container is attached to. + * + * @access public + */ + var $_auth_obj = null; + + // }}} + // {{{ Auth_Container() [constructor] + + /** + * Constructor + * + * Has to be overwritten by each storage class + * + * @access public + */ + function Auth_Container() + { + } + + // }}} + // {{{ fetchData() + + /** + * Fetch data from storage container + * + * Has to be overwritten by each storage class + * + * @access public + */ + function fetchData($username, $password, $isChallengeResponse=false) + { + $this->log('Auth_Container::fetchData() called.', AUTH_LOG_DEBUG); + } + + // }}} + // {{{ verifyPassword() + + /** + * Crypt and verfiy the entered password + * + * @param string Entered password + * @param string Password from the data container (usually this password + * is already encrypted. + * @param string Type of algorithm with which the password from + * the container has been crypted. (md5, crypt etc.) + * Defaults to "md5". + * @return bool True, if the passwords match + */ + function verifyPassword($password1, $password2, $cryptType = "md5") + { + $this->log('Auth_Container::verifyPassword() called.', AUTH_LOG_DEBUG); + switch ($cryptType) { + case "crypt" : + return ((string)crypt($password1, $password2) === (string)$password2); + break; + case "none" : + case "" : + return ((string)$password1 === (string)$password2); + break; + case "md5" : + return ((string)md5($password1) === (string)$password2); + break; + default : + if (function_exists($cryptType)) { + return ((string)$cryptType($password1) === (string)$password2); + } elseif (method_exists($this,$cryptType)) { + return ((string)$this->$cryptType($password1) === (string)$password2); + } else { + return false; + } + break; + } + } + + // }}} + // {{{ supportsChallengeResponse() + + /** + * Returns true if the container supports Challenge Response + * password authentication + */ + function supportsChallengeResponse() + { + return(false); + } + + // }}} + // {{{ getCryptType() + + /** + * Returns the crypt current crypt type of the container + * + * @return string + */ + function getCryptType() + { + return(''); + } + + // }}} + // {{{ listUsers() + + /** + * List all users that are available from the storage container + */ + function listUsers() + { + $this->log('Auth_Container::listUsers() called.', AUTH_LOG_DEBUG); + return AUTH_METHOD_NOT_SUPPORTED; + } + + // }}} + // {{{ getUser() + + /** + * Returns a user assoc array + * + * Containers which want should overide this + * + * @param string The username + */ + function getUser($username) + { + $this->log('Auth_Container::getUser() called.', AUTH_LOG_DEBUG); + $users = $this->listUsers(); + if ($users === AUTH_METHOD_NOT_SUPPORTED) { + return AUTH_METHOD_NOT_SUPPORTED; + } + for ($i=0; $c = count($users), $i<$c; $i++) { + if ($users[$i]['username'] == $username) { + return $users[$i]; + } + } + return false; + } + + // }}} + // {{{ addUser() + + /** + * Add a new user to the storage container + * + * @param string Username + * @param string Password + * @param array Additional information + * + * @return boolean + */ + function addUser($username, $password, $additional=null) + { + $this->log('Auth_Container::addUser() called.', AUTH_LOG_DEBUG); + return AUTH_METHOD_NOT_SUPPORTED; + } + + // }}} + // {{{ removeUser() + + /** + * Remove user from the storage container + * + * @param string Username + */ + function removeUser($username) + { + $this->log('Auth_Container::removeUser() called.', AUTH_LOG_DEBUG); + return AUTH_METHOD_NOT_SUPPORTED; + } + + // }}} + // {{{ changePassword() + + /** + * Change password for user in the storage container + * + * @param string Username + * @param string The new password + */ + function changePassword($username, $password) + { + $this->log('Auth_Container::changePassword() called.', AUTH_LOG_DEBUG); + return AUTH_METHOD_NOT_SUPPORTED; + } + + // }}} + // {{{ log() + + /** + * Log a message to the Auth log + * + * @param string The message + * @param int + * @return boolean + */ + function log($message, $level = AUTH_LOG_DEBUG) { + + if (is_null($this->_auth_obj)) { + + return false; + + } else { + + return $this->_auth_obj->log($message, $level); + + } + + } + + // }}} + +} + +?> diff --git a/lib/Pear/Auth/Container/CAS.php b/lib/Pear/Auth/Container/CAS.php new file mode 100644 index 0000000..c83f7a5 --- /dev/null +++ b/lib/Pear/Auth/Container/CAS.php @@ -0,0 +1,169 @@ + + * @copyright Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/package/Auth + * @since File available since Release 1.6.1 + */ + +/** + * Include Auth_Container base class + */ +require_once "Auth/Container.php"; + + +require_once "CAS.php"; +/** + * Containers for authenticate against a CAS service. + * CAS provides enterprise single sign on service. + * + * Further options may be available and can be found on the CAS site at + * http://www.ja-sig.org/products/cas/ + * + * This class require the phpCAS client available on the phpCAS site at + * http://www.ja-sig.org/wiki/display/CASC/phpCAS + * + * This acts as gateway so not authenticated users are redirect to + * the CAS login service form. + * + * To use this storage containers, you have to use the + * following syntax: + * + * true, + * 'server_version'=> CAS_VERSION_2_0,// the version of the CAS server + * 'server_hostname'=> 'your_domain',// the hostname of the CAS server + * 'server_port'=> '8443',// the port the CAS server is running on + * 'server_uri'=> 'cas',// the URI the CAS server is responding on + * 'curl_opt_ssl_version'=>3 + * ); + * + * $myauth = new Auth('CAS', $params); + * + * $myauth->logger = &Log::factory('file', '/tmp/out.log', 'TEST'); + * + * if ($myauth->checkAuth()) { + * echo 'User ' . $myauth->getUsername() . ' login with success'; + * } else { + * //Required to force login, simulate user login. + * $myauth->post['username'] = 'fake'; + * //Start process authentication + * $myauth->start(); + * } + * ?> + * + * + * @category Authentication + * @package Auth + * @author Luca Corbo + * @copyright Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/package/Auth + * @since File available since Release 1.6.1 + */ +class Auth_Container_CAS extends Auth_Container +{ + + // {{{ properties + + /** + * Options for the class + * @var array + * @access private + */ + var $_options = array( + 'server_version'=> CAS_VERSION_2_0,// the version of the CAS server + 'server_hostname'=> 'localhost',// the hostname of the CAS server + 'server_port'=> '443',// the port the CAS server is running on + 'server_uri'=> '',// the URI the CAS server is responding on + 'curl_opt_ssl_version'=> 0 //The SSL version (2 or 3) to use. + //By default PHP will try to determine this itself, + //although in some cases this must be set manually. + + ); + + // }}} + // {{{ Auth_Container_CAS() [constructor] + + /** + * Constructor of the container class + * + * @param $options, associative array with cas options features + * @see $_options + */ + function Auth_Container_CAS($options) + { + //Check for valid options + foreach ($options as $key => $value) { + $this->_options[$key] = $value; + } + + } + + // }}} + + // {{{ fetchData() + + /** + * Checks if the user is authenticated (use the gateway feature). + * If the user is not authenticated, halt by redirecting to the CAS server. + * + * @param string Username + * @param string Password + * @return mixed true on success + */ + function fetchData($username = null, $password = null) + { + $this->log('Auth_Container_CAS::fetchData() called.', AUTH_LOG_DEBUG); + + phpCAS::client($this->_options['server_version'], + $this->_options['server_hostname'], + intval($this->_options['server_port']), + $this->_options['server_uri'], + false); + + // check for specified SSL version (2 or 3) to use with curl + if ($this->_options['curl_opt_ssl_version'] != 0) { + phpCAS::setExtraCurlOption(CURLOPT_SSLVERSION, + $this->_options['curl_opt_ssl_version']); + } + + phpCAS::setNoCasServerValidation(); + + $this->log('Trying to login at: ' . phpCAS::getServerLoginURL(), AUTH_LOG_DEBUG); + phpCAS::forceAuthentication(); + + $this->log('Override fake username with cas user:' . phpCAS::getUser(), AUTH_LOG_DEBUG); + $this->_auth_obj->username = phpCAS::getUser(); + return true; + } +} +?> diff --git a/lib/Pear/Auth/Container/LDAP.php b/lib/Pear/Auth/Container/LDAP.php new file mode 100644 index 0000000..b3cf9ee --- /dev/null +++ b/lib/Pear/Auth/Container/LDAP.php @@ -0,0 +1,766 @@ + + * @author Adam Ashley + * @author Hugues Peeters + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: LDAP.php,v 1.43 2007/06/12 03:11:26 aashley Exp $ + * @link http://pear.php.net/package/Auth + */ + +/** + * Include Auth_Container base class + */ +require_once "Auth/Container.php"; +/** + * Include PEAR package for error handling + */ +require_once "PEAR.php"; + +/** + * Storage driver for fetching login data from LDAP + * + * This class is heavily based on the DB and File containers. By default it + * connects to localhost:389 and searches for uid=$username with the scope + * "sub". If no search base is specified, it will try to determine it via + * the namingContexts attribute. It takes its parameters in a hash, connects + * to the ldap server, binds anonymously, searches for the user, and tries + * to bind as the user with the supplied password. When a group was set, it + * will look for group membership of the authenticated user. If all goes + * well the authentication was successful. + * + * Parameters: + * + * host: localhost (default), ldap.netsols.de or 127.0.0.1 + * port: 389 (default) or 636 or whereever your server runs + * url: ldap://localhost:389/ + * useful for ldaps://, works only with openldap2 ? + * it will be preferred over host and port + * version: LDAP version to use, ususally 2 (default) or 3, + * must be an integer! + * referrals: If set, determines whether the LDAP library automatically + * follows referrals returned by LDAP servers or not. Possible + * values are true (default) or false. + * binddn: If set, searching for user will be done after binding + * as this user, if not set the bind will be anonymous. + * This is reported to make the container work with MS + * Active Directory, but should work with any server that + * is configured this way. + * This has to be a complete dn for now (basedn and + * userdn will not be appended). + * bindpw: The password to use for binding with binddn + * basedn: the base dn of your server + * userdn: gets prepended to basedn when searching for user + * userscope: Scope for user searching: one, sub (default), or base + * userattr: the user attribute to search for (default: uid) + * userfilter: filter that will be added to the search filter + * this way: (&(userattr=username)(userfilter)) + * default: (objectClass=posixAccount) + * attributes: array of additional attributes to fetch from entry. + * these will added to auth data and can be retrieved via + * Auth::getAuthData(). An empty array will fetch all attributes, + * array('') will fetch no attributes at all (default) + * If you add 'dn' as a value to this array, the users DN that was + * used for binding will be added to auth data as well. + * attrformat: The returned format of the additional data defined in the + * 'attributes' option. Two formats are available. + * LDAP returns data formatted in a + * multidimensional array where each array starts with a + * 'count' element providing the number of attributes in the + * entry, or the number of values for attributes. When set + * to this format, the only way to retrieve data from the + * Auth object is by calling getAuthData('attributes'). + * AUTH returns data formatted in a + * structure more compliant with other Auth Containers, + * where each attribute element can be directly called by + * getAuthData() method from Auth. + * For compatibily with previous LDAP container versions, + * the default format is LDAP. + * groupdn: gets prepended to basedn when searching for group + * groupattr: the group attribute to search for (default: cn) + * groupfilter: filter that will be added to the search filter when + * searching for a group: + * (&(groupattr=group)(memberattr=username)(groupfilter)) + * default: (objectClass=groupOfUniqueNames) + * memberattr : the attribute of the group object where the user dn + * may be found (default: uniqueMember) + * memberisdn: whether the memberattr is the dn of the user (default) + * or the value of userattr (usually uid) + * group: the name of group to search for + * groupscope: Scope for group searching: one, sub (default), or base + * start_tls: enable/disable the use of START_TLS encrypted connection + * (default: false) + * debug: Enable/Disable debugging output (default: false) + * try_all: Whether to try all user accounts returned from the search + * or just the first one. (default: false) + * + * To use this storage container, you have to use the following syntax: + * + * 'localhost', + * 'port' => '389', + * 'version' => 3, + * 'basedn' => 'o=netsols,c=de', + * 'userattr' => 'uid' + * 'binddn' => 'cn=admin,o=netsols,c=de', + * 'bindpw' => 'password')); + * + * $a2 = new Auth('LDAP', array( + * 'url' => 'ldaps://ldap.netsols.de', + * 'basedn' => 'o=netsols,c=de', + * 'userscope' => 'one', + * 'userdn' => 'ou=People', + * 'groupdn' => 'ou=Groups', + * 'groupfilter' => '(objectClass=posixGroup)', + * 'memberattr' => 'memberUid', + * 'memberisdn' => false, + * 'group' => 'admin' + * )); + * + * $a3 = new Auth('LDAP', array( + * 'host' => 'ldap.netsols.de', + * 'port' => 389, + * 'version' => 3, + * 'referrals' => false, + * 'basedn' => 'dc=netsols,dc=de', + * 'binddn' => 'cn=Jan Wagner,cn=Users,dc=netsols,dc=de', + * 'bindpw' => 'password', + * 'userattr' => 'samAccountName', + * 'userfilter' => '(objectClass=user)', + * 'attributes' => array(''), + * 'group' => 'testing', + * 'groupattr' => 'samAccountName', + * 'groupfilter' => '(objectClass=group)', + * 'memberattr' => 'member', + * 'memberisdn' => true, + * 'groupdn' => 'cn=Users', + * 'groupscope' => 'one', + * 'debug' => true); + * + * The parameter values have to correspond + * to the ones for your LDAP server of course. + * + * When talking to a Microsoft ActiveDirectory server you have to + * use 'samaccountname' as the 'userattr' and follow special rules + * to translate the ActiveDirectory directory names into 'basedn'. + * The 'basedn' for the default 'Users' folder on an ActiveDirectory + * server for the ActiveDirectory Domain (which is not related to + * its DNS name) "win2000.example.org" would be: + * "CN=Users, DC=win2000, DC=example, DC=org' + * where every component of the domain name becomes a DC attribute + * of its own. If you want to use a custom users folder you have to + * replace "CN=Users" with a sequence of "OU" attributes that specify + * the path to your custom folder in reverse order. + * So the ActiveDirectory folder + * "win2000.example.org\Custom\Accounts" + * would become + * "OU=Accounts, OU=Custom, DC=win2000, DC=example, DC=org' + * + * It seems that binding anonymously to an Active Directory + * is not allowed, so you have to set binddn and bindpw for + * user searching. + * + * LDAP Referrals need to be set to false for AD to work sometimes. + * + * Example a3 shows a full blown and tested example for connection to + * Windows 2000 Active Directory with group mebership checking + * + * Note also that if you want an encrypted connection to an MS LDAP + * server, then, on your webserver, you must specify + * TLS_REQCERT never + * in /etc/ldap/ldap.conf or in the webserver user's ~/.ldaprc (which + * may or may not be read depending on your configuration). + * + * + * @category Authentication + * @package Auth + * @author Jan Wagner + * @author Adam Ashley + * @author Hugues Peeters + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version Release: 1.6.1 File: $Revision: 1.43 $ + * @link http://pear.php.net/package/Auth + */ +class Auth_Container_LDAP extends Auth_Container +{ + + // {{{ properties + + /** + * Options for the class + * @var array + */ + var $options = array(); + + /** + * Connection ID of LDAP Link + * @var string + */ + var $conn_id = false; + + // }}} + + // {{{ Auth_Container_LDAP() [constructor] + + /** + * Constructor of the container class + * + * @param $params, associative hash with host,port,basedn and userattr key + * @return object Returns an error object if something went wrong + */ + function Auth_Container_LDAP($params) + { + if (false === extension_loaded('ldap')) { + return PEAR::raiseError('Auth_Container_LDAP: LDAP Extension not loaded', + 41, PEAR_ERROR_DIE); + } + + $this->_setDefaults(); + + if (is_array($params)) { + $this->_parseOptions($params); + } + } + + // }}} + // {{{ _prepare() + + /** + * Prepare LDAP connection + * + * This function checks if we have already opened a connection to + * the LDAP server. If that's not the case, a new connection is opened. + * + * @access private + * @return mixed True or a PEAR error object. + */ + function _prepare() + { + if (!$this->_isValidLink()) { + $res = $this->_connect(); + if (PEAR::isError($res)) { + return $res; + } + } + return true; + } + + // }}} + // {{{ _connect() + + /** + * Connect to the LDAP server using the global options + * + * @access private + * @return object Returns a PEAR error object if an error occurs. + */ + function _connect() + { + $this->log('Auth_Container_LDAP::_connect() called.', AUTH_LOG_DEBUG); + // connect + if (isset($this->options['url']) && $this->options['url'] != '') { + $this->log('Connecting with URL', AUTH_LOG_DEBUG); + $conn_params = array($this->options['url']); + } else { + $this->log('Connecting with host:port', AUTH_LOG_DEBUG); + $conn_params = array($this->options['host'], $this->options['port']); + } + + if (($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) { + $this->log('Connection to server failed.', AUTH_LOG_DEBUG); + $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG); + return PEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41); + } + $this->log('Successfully connected to server', AUTH_LOG_DEBUG); + + // switch LDAP version + if (is_numeric($this->options['version']) && $this->options['version'] > 2) { + $this->log("Switching to LDAP version {$this->options['version']}", AUTH_LOG_DEBUG); + @ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $this->options['version']); + + // start TLS if available + if (isset($this->options['start_tls']) && $this->options['start_tls']) { + $this->log("Starting TLS session", AUTH_LOG_DEBUG); + if (@ldap_start_tls($this->conn_id) === false) { + $this->log('Could not start TLS session', AUTH_LOG_DEBUG); + $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG); + return PEAR::raiseError('Auth_Container_LDAP: Could not start tls.', 41); + } + } + } + + // switch LDAP referrals + if (is_bool($this->options['referrals'])) { + $this->log("Switching LDAP referrals to " . (($this->options['referrals']) ? 'true' : 'false'), AUTH_LOG_DEBUG); + if (@ldap_set_option($this->conn_id, LDAP_OPT_REFERRALS, $this->options['referrals']) === false) { + $this->log('Could not change LDAP referrals options', AUTH_LOG_DEBUG); + $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG); + } + } + + // bind with credentials or anonymously + if (strlen($this->options['binddn']) && strlen($this->options['bindpw'])) { + $this->log('Binding with credentials', AUTH_LOG_DEBUG); + $bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']); + } else { + $this->log('Binding anonymously', AUTH_LOG_DEBUG); + $bind_params = array($this->conn_id); + } + + // bind for searching + if ((@call_user_func_array('ldap_bind', $bind_params)) === false) { + $this->log('Bind failed', AUTH_LOG_DEBUG); + $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG); + $this->_disconnect(); + return PEAR::raiseError("Auth_Container_LDAP: Could not bind to LDAP server.", 41); + } + $this->log('Binding was successful', AUTH_LOG_DEBUG); + + return true; + } + + // }}} + // {{{ _disconnect() + + /** + * Disconnects (unbinds) from ldap server + * + * @access private + */ + function _disconnect() + { + $this->log('Auth_Container_LDAP::_disconnect() called.', AUTH_LOG_DEBUG); + if ($this->_isValidLink()) { + $this->log('disconnecting from server'); + @ldap_unbind($this->conn_id); + } + } + + // }}} + // {{{ _getBaseDN() + + /** + * Tries to find Basedn via namingContext Attribute + * + * @access private + */ + function _getBaseDN() + { + $this->log('Auth_Container_LDAP::_getBaseDN() called.', AUTH_LOG_DEBUG); + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + if ($this->options['basedn'] == "" && $this->_isValidLink()) { + $this->log("basedn not set, searching via namingContexts.", AUTH_LOG_DEBUG); + + $result_id = @ldap_read($this->conn_id, "", "(objectclass=*)", array("namingContexts")); + + if (@ldap_count_entries($this->conn_id, $result_id) == 1) { + + $this->log("got result for namingContexts", AUTH_LOG_DEBUG); + + $entry_id = @ldap_first_entry($this->conn_id, $result_id); + $attrs = @ldap_get_attributes($this->conn_id, $entry_id); + $basedn = $attrs['namingContexts'][0]; + + if ($basedn != "") { + $this->log("result for namingContexts was $basedn", AUTH_LOG_DEBUG); + $this->options['basedn'] = $basedn; + } + } + @ldap_free_result($result_id); + } + + // if base ist still not set, raise error + if ($this->options['basedn'] == "") { + return PEAR::raiseError("Auth_Container_LDAP: LDAP search base not specified!", 41); + } + return true; + } + + // }}} + // {{{ _isValidLink() + + /** + * determines whether there is a valid ldap conenction or not + * + * @accessd private + * @return boolean + */ + function _isValidLink() + { + if (is_resource($this->conn_id)) { + if (get_resource_type($this->conn_id) == 'ldap link') { + return true; + } + } + return false; + } + + // }}} + // {{{ _setDefaults() + + /** + * Set some default options + * + * @access private + */ + function _setDefaults() + { + $this->options['url'] = ''; + $this->options['host'] = 'localhost'; + $this->options['port'] = '389'; + $this->options['version'] = 2; + $this->options['referrals'] = true; + $this->options['binddn'] = ''; + $this->options['bindpw'] = ''; + $this->options['basedn'] = ''; + $this->options['userdn'] = ''; + $this->options['userscope'] = 'sub'; + $this->options['userattr'] = 'uid'; + $this->options['userfilter'] = '(objectClass=posixAccount)'; + $this->options['attributes'] = array(''); // no attributes + $this->options['attrformat'] = 'AUTH'; // returns attribute like other Auth containers + $this->options['group'] = ''; + $this->options['groupdn'] = ''; + $this->options['groupscope'] = 'sub'; + $this->options['groupattr'] = 'cn'; + $this->options['groupfilter'] = '(objectClass=groupOfUniqueNames)'; + $this->options['memberattr'] = 'uniqueMember'; + $this->options['memberisdn'] = true; + $this->options['start_tls'] = false; + $this->options['debug'] = false; + $this->options['try_all'] = false; // Try all user ids returned not just the first one + } + + // }}} + // {{{ _parseOptions() + + /** + * Parse options passed to the container class + * + * @access private + * @param array + */ + function _parseOptions($array) + { + $array = $this->_setV12OptionsToV13($array); + + foreach ($array as $key => $value) { + if (array_key_exists($key, $this->options)) { + if ($key == 'attributes') { + if (is_array($value)) { + $this->options[$key] = $value; + } else { + $this->options[$key] = explode(',', $value); + } + } else { + $this->options[$key] = $value; + } + } + } + } + + // }}} + // {{{ _setV12OptionsToV13() + + /** + * Adapt deprecated options from Auth 1.2 LDAP to Auth 1.3 LDAP + * + * @author Hugues Peeters + * @access private + * @param array + * @return array + */ + function _setV12OptionsToV13($array) + { + if (isset($array['useroc'])) + $array['userfilter'] = "(objectClass=".$array['useroc'].")"; + if (isset($array['groupoc'])) + $array['groupfilter'] = "(objectClass=".$array['groupoc'].")"; + if (isset($array['scope'])) + $array['userscope'] = $array['scope']; + + return $array; + } + + // }}} + // {{{ _scope2function() + + /** + * Get search function for scope + * + * @param string scope + * @return string ldap search function + */ + function _scope2function($scope) + { + switch($scope) { + case 'one': + $function = 'ldap_list'; + break; + case 'base': + $function = 'ldap_read'; + break; + default: + $function = 'ldap_search'; + break; + } + return $function; + } + + // }}} + // {{{ fetchData() + + /** + * Fetch data from LDAP server + * + * Searches the LDAP server for the given username/password + * combination. Escapes all LDAP meta characters in username + * before performing the query. + * + * @param string Username + * @param string Password + * @return boolean + */ + function fetchData($username, $password) + { + $this->log('Auth_Container_LDAP::fetchData() called.', AUTH_LOG_DEBUG); + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + $err = $this->_getBaseDN(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + // UTF8 Encode username for LDAPv3 + if (@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver == 3) { + $this->log('UTF8 encoding username for LDAPv3', AUTH_LOG_DEBUG); + $username = utf8_encode($username); + } + + // make search filter + $filter = sprintf('(&(%s=%s)%s)', + $this->options['userattr'], + $this->_quoteFilterString($username), + $this->options['userfilter']); + + // make search base dn + $search_basedn = $this->options['userdn']; + if ($search_basedn != '' && substr($search_basedn, -1) != ',') { + $search_basedn .= ','; + } + $search_basedn .= $this->options['basedn']; + + // attributes + $searchAttributes = $this->options['attributes']; + + // make functions params array + $func_params = array($this->conn_id, $search_basedn, $filter, $searchAttributes); + + // search function to use + $func_name = $this->_scope2function($this->options['userscope']); + + $this->log("Searching with $func_name and filter $filter in $search_basedn", AUTH_LOG_DEBUG); + + // search + if (($result_id = @call_user_func_array($func_name, $func_params)) === false) { + $this->log('User not found', AUTH_LOG_DEBUG); + } elseif (@ldap_count_entries($this->conn_id, $result_id) >= 1) { // did we get some possible results? + + $this->log('User(s) found', AUTH_LOG_DEBUG); + + $first = true; + $entry_id = null; + + do { + + // then get the user dn + if ($first) { + $entry_id = @ldap_first_entry($this->conn_id, $result_id); + $first = false; + } else { + $entry_id = @ldap_next_entry($this->conn_id, $entry_id); + if ($entry_id === false) + break; + } + $user_dn = @ldap_get_dn($this->conn_id, $entry_id); + + // as the dn is not fetched as an attribute, we save it anyway + if (is_array($searchAttributes) && in_array('dn', $searchAttributes)) { + $this->log('Saving DN to AuthData', AUTH_LOG_DEBUG); + $this->_auth_obj->setAuthData('dn', $user_dn); + } + + // fetch attributes + if ($attributes = @ldap_get_attributes($this->conn_id, $entry_id)) { + + if (is_array($attributes) && isset($attributes['count']) && + $attributes['count'] > 0) { + + // ldap_get_attributes() returns a specific multi dimensional array + // format containing all the attributes and where each array starts + // with a 'count' element providing the number of attributes in the + // entry, or the number of values for attribute. For compatibility + // reasons, it remains the default format returned by LDAP container + // setAuthData(). + // The code below optionally returns attributes in another format, + // more compliant with other Auth containers, where each attribute + // element are directly set in the 'authData' list. This option is + // enabled by setting 'attrformat' to + // 'AUTH' in the 'options' array. + // eg. $this->options['attrformat'] = 'AUTH' + + if ( strtoupper($this->options['attrformat']) == 'AUTH' ) { + $this->log('Saving attributes to Auth data in AUTH format', AUTH_LOG_DEBUG); + unset ($attributes['count']); + foreach ($attributes as $attributeName => $attributeValue ) { + if (is_int($attributeName)) continue; + if (is_array($attributeValue) && isset($attributeValue['count'])) { + unset ($attributeValue['count']); + } + if (count($attributeValue)<=1) $attributeValue = $attributeValue[0]; + $this->log('Storing additional field: '.$attributeName, AUTH_LOG_DEBUG); + $this->_auth_obj->setAuthData($attributeName, $attributeValue); + } + } + else + { + $this->log('Saving attributes to Auth data in LDAP format', AUTH_LOG_DEBUG); + $this->_auth_obj->setAuthData('attributes', $attributes); + } + } + } + @ldap_free_result($result_id); + + // need to catch an empty password as openldap seems to return TRUE + // if anonymous binding is allowed + if ($password != "") { + $this->log("Bind as $user_dn", AUTH_LOG_DEBUG); + + // try binding as this user with the supplied password + if (@ldap_bind($this->conn_id, $user_dn, $password)) { + $this->log('Bind successful', AUTH_LOG_DEBUG); + + // check group if appropiate + if (strlen($this->options['group'])) { + // decide whether memberattr value is a dn or the username + $this->log('Checking group membership', AUTH_LOG_DEBUG); + $return = $this->checkGroup(($this->options['memberisdn']) ? $user_dn : $username); + $this->_disconnect(); + return $return; + } else { + $this->log('Authenticated', AUTH_LOG_DEBUG); + $this->_disconnect(); + return true; // user authenticated + } // checkGroup + } // bind + } // non-empty password + } while ($this->options['try_all'] == true); // interate through entries + } // get results + // default + $this->log('NOT authenticated!', AUTH_LOG_DEBUG); + $this->_disconnect(); + return false; + } + + // }}} + // {{{ checkGroup() + + /** + * Validate group membership + * + * Searches the LDAP server for group membership of the + * supplied username. Quotes all LDAP filter meta characters in + * the user name before querying the LDAP server. + * + * @param string Distinguished Name of the authenticated User + * @return boolean + */ + function checkGroup($user) + { + $this->log('Auth_Container_LDAP::checkGroup() called.', AUTH_LOG_DEBUG); + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + // make filter + $filter = sprintf('(&(%s=%s)(%s=%s)%s)', + $this->options['groupattr'], + $this->options['group'], + $this->options['memberattr'], + $this->_quoteFilterString($user), + $this->options['groupfilter']); + + // make search base dn + $search_basedn = $this->options['groupdn']; + if ($search_basedn != '' && substr($search_basedn, -1) != ',') { + $search_basedn .= ','; + } + $search_basedn .= $this->options['basedn']; + + $func_params = array($this->conn_id, $search_basedn, $filter, + array($this->options['memberattr'])); + $func_name = $this->_scope2function($this->options['groupscope']); + + $this->log("Searching with $func_name and filter $filter in $search_basedn", AUTH_LOG_DEBUG); + + // search + if (($result_id = @call_user_func_array($func_name, $func_params)) != false) { + if (@ldap_count_entries($this->conn_id, $result_id) == 1) { + @ldap_free_result($result_id); + $this->log('User is member of group', AUTH_LOG_DEBUG); + return true; + } + } + // default + $this->log('User is NOT member of group', AUTH_LOG_DEBUG); + return false; + } + + // }}} + // {{{ _quoteFilterString() + + /** + * Escapes LDAP filter special characters as defined in RFC 2254. + * + * @access private + * @param string Filter String + */ + function _quoteFilterString($filter_str) + { + $metas = array( '\\', '*', '(', ')', "\x00"); + $quoted_metas = array('\\\\', '\*', '\(', '\)', "\\\x00"); + return str_replace($metas, $quoted_metas, $filter_str); + } + + // }}} + +} + +?> diff --git a/lib/Pear/Auth/Container/MDB2.php b/lib/Pear/Auth/Container/MDB2.php new file mode 100644 index 0000000..2ad0ff0 --- /dev/null +++ b/lib/Pear/Auth/Container/MDB2.php @@ -0,0 +1,624 @@ + + * @author Adam Ashley + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: MDB2.php,v 1.24 2008/04/04 07:57:02 aashley Exp $ + * @link http://pear.php.net/package/Auth + * @since File available since Release 1.3.0 + */ + +/** + * Include Auth_Container base class + */ +require_once 'Auth/Container.php'; +/** + * Include PEAR MDB2 package + */ +require_once 'MDB2.php'; + +/** + * Storage driver for fetching login data from a database + * + * This storage driver can use all databases which are supported + * by the PEAR MDB2 abstraction layer to fetch login data. + * + * @category Authentication + * @package Auth + * @author Lorenzo Alberton + * @author Adam Ashley + * @copyright 2001-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version Release: 1.6.1 File: $Revision: 1.24 $ + * @link http://pear.php.net/package/Auth + * @since Class available since Release 1.3.0 + */ +class Auth_Container_MDB2 extends Auth_Container +{ + + // {{{ properties + + /** + * Additional options for the storage container + * @var array + */ + var $options = array(); + + /** + * MDB object + * @var object + */ + var $db = null; + var $dsn = ''; + + /** + * User that is currently selected from the DB. + * @var string + */ + var $activeUser = ''; + + // }}} + // {{{ Auth_Container_MDB2() [constructor] + + /** + * Constructor of the container class + * + * Initate connection to the database via PEAR::MDB2 + * + * @param string Connection data or MDB2 object + * @return object Returns an error object if something went wrong + */ + function Auth_Container_MDB2($dsn) + { + $this->_setDefaults(); + + if (is_array($dsn)) { + $this->_parseOptions($dsn); + if (empty($this->options['dsn'])) { + PEAR::raiseError('No connection parameters specified!'); + } + } else { + $this->options['dsn'] = $dsn; + } + } + + // }}} + // {{{ _connect() + + /** + * Connect to database by using the given DSN string + * + * @access private + * @param mixed DSN string | array | mdb object + * @return mixed Object on error, otherwise bool + */ + function _connect($dsn) + { + $this->log('Auth_Container_MDB2::_connect() called.', AUTH_LOG_DEBUG); + if (is_string($dsn) || is_array($dsn)) { + $this->db =& MDB2::connect($dsn, $this->options['db_options']); + } elseif (is_subclass_of($dsn, 'MDB2_Driver_Common')) { + $this->db = $dsn; + } elseif (is_object($dsn) && MDB2::isError($dsn)) { + return PEAR::raiseError($dsn->getMessage(), $dsn->code); + } else { + return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__, + 41, + PEAR_ERROR_RETURN, + null, + null + ); + + } + + if (MDB2::isError($this->db) || PEAR::isError($this->db)) { + return PEAR::raiseError($this->db->getMessage(), $this->db->code); + } + + if ($this->options['auto_quote']) { + if (strpos('.', $this->options['table']) === false) { + $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table'], true); + } else { + $t = explode('.', $this->options['table']); + for ($i = 0, $count = count($t); $i < $count; $i++) + $t[$i] = $this->db->quoteIdentifier($t[$i], true); + $this->options['final_table'] = implode('.', $t); + } + $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol'], true); + $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol'], true); + } else { + $this->options['final_table'] = $this->options['table']; + $this->options['final_usernamecol'] = $this->options['usernamecol']; + $this->options['final_passwordcol'] = $this->options['passwordcol']; + } + + return true; + } + + // }}} + // {{{ _prepare() + + /** + * Prepare database connection + * + * This function checks if we have already opened a connection to + * the database. If that's not the case, a new connection is opened. + * + * @access private + * @return mixed True or a MDB error object. + */ + function _prepare() + { + if (is_subclass_of($this->db, 'MDB2_Driver_Common')) { + return true; + } + return $this->_connect($this->options['dsn']); + } + + // }}} + // {{{ query() + + /** + * Prepare query to the database + * + * This function checks if we have already opened a connection to + * the database. If that's not the case, a new connection is opened. + * After that the query is passed to the database. + * + * @access public + * @param string Query string + * @return mixed a MDB_result object or MDB_OK on success, a MDB + * or PEAR error on failure + */ + function query($query) + { + $this->log('Auth_Container_MDB2::query() called.', AUTH_LOG_DEBUG); + $err = $this->_prepare(); + if ($err !== true) { + return $err; + } + return $this->db->exec($query); + } + + // }}} + // {{{ _setDefaults() + + /** + * Set some default options + * + * @access private + * @return void + */ + function _setDefaults() + { + $this->options['table'] = 'auth'; + $this->options['usernamecol'] = 'username'; + $this->options['passwordcol'] = 'password'; + $this->options['dsn'] = ''; + $this->options['db_fields'] = ''; + $this->options['cryptType'] = 'md5'; + $this->options['db_options'] = array(); + $this->options['db_where'] = ''; + $this->options['auto_quote'] = true; + } + + // }}} + // {{{ _parseOptions() + + /** + * Parse options passed to the container class + * + * @access private + * @param array + */ + function _parseOptions($array) + { + foreach ($array as $key => $value) { + if (isset($this->options[$key])) { + $this->options[$key] = $value; + } + } + } + + // }}} + // {{{ _quoteDBFields() + + /** + * Quote the db_fields option to avoid the possibility of SQL injection. + * + * @access private + * @return string A properly quoted string that can be concatenated into a + * SELECT clause. + */ + function _quoteDBFields() + { + if (isset($this->options['db_fields'])) { + if (is_array($this->options['db_fields'])) { + if ($this->options['auto_quote']) { + $fields = array(); + foreach ($this->options['db_fields'] as $field) { + $fields[] = $this->db->quoteIdentifier($field, true); + } + return implode(', ', $fields); + } else { + return implode(', ', $this->options['db_fields']); + } + } else { + if (strlen($this->options['db_fields']) > 0) { + if ($this->options['auto_quote']) { + return $this->db->quoteIdentifier($this->options['db_fields'], true); + } else { + return $this->options['db_fields']; + } + } + } + } + + return ''; + } + + // }}} + // {{{ fetchData() + + /** + * Get user information from database + * + * This function uses the given username to fetch + * the corresponding login data from the database + * table. If an account that matches the passed username + * and password is found, the function returns true. + * Otherwise it returns false. + * + * @param string Username + * @param string Password + * @param boolean If true password is secured using a md5 hash + * the frontend and auth are responsible for making sure the container supports + * challenge response password authentication + * @return mixed Error object or boolean + */ + function fetchData($username, $password, $isChallengeResponse=false) + { + $this->log('Auth_Container_MDB2::fetchData() called.', AUTH_LOG_DEBUG); + // Prepare for a database query + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + //Check if db_fields contains a *, if so assume all columns are selected + if (is_string($this->options['db_fields']) + && strstr($this->options['db_fields'], '*')) { + $sql_from = '*'; + } else { + $sql_from = $this->options['final_usernamecol']. + ", ".$this->options['final_passwordcol']; + + if (strlen($fields = $this->_quoteDBFields()) > 0) { + $sql_from .= ', '.$fields; + } + } + $query = sprintf("SELECT %s FROM %s WHERE %s = %s", + $sql_from, + $this->options['final_table'], + $this->options['final_usernamecol'], + $this->db->quote($username, 'text') + ); + + // check if there is an optional parameter db_where + if ($this->options['db_where'] != '') { + // there is one, so add it to the query + $query .= " AND ".$this->options['db_where']; + } + + $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG); + + $res = $this->db->queryRow($query, null, MDB2_FETCHMODE_ASSOC); + if (MDB2::isError($res) || PEAR::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->getCode()); + } + if (!is_array($res)) { + $this->activeUser = ''; + return false; + } + + // Perform trimming here before the hashing + $password = trim($password, "\r\n"); + $res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n"); + // If using Challenge Response md5 the pass with the secret + if ($isChallengeResponse) { + $res[$this->options['passwordcol']] = + md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']); + // UGLY cannot avoid without modifying verifyPassword + if ($this->options['cryptType'] == 'md5') { + $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]); + } + } + if ($this->verifyPassword($password, + $res[$this->options['passwordcol']], + $this->options['cryptType'])) { + // Store additional field values in the session + foreach ($res as $key => $value) { + if ($key == $this->options['passwordcol'] || + $key == $this->options['usernamecol']) { + continue; + } + + $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG); + + // Use reference to the auth object if exists + // This is because the auth session variable can change so a static call to setAuthData does not make sense + $this->_auth_obj->setAuthData($key, $value); + } + return true; + } + + $this->activeUser = $res[$this->options['usernamecol']]; + return false; + } + + // }}} + // {{{ listUsers() + + /** + * Returns a list of users from the container + * + * @return mixed array|PEAR_Error + * @access public + */ + function listUsers() + { + $this->log('Auth_Container_MDB2::listUsers() called.', AUTH_LOG_DEBUG); + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + $retVal = array(); + + //Check if db_fields contains a *, if so assume all columns are selected + if ( is_string($this->options['db_fields']) + && strstr($this->options['db_fields'], '*')) { + $sql_from = '*'; + } else { + $sql_from = $this->options['final_usernamecol']. + ", ".$this->options['final_passwordcol']; + + if (strlen($fields = $this->_quoteDBFields()) > 0) { + $sql_from .= ', '.$fields; + } + } + + $query = sprintf('SELECT %s FROM %s', + $sql_from, + $this->options['final_table'] + ); + + // check if there is an optional parameter db_where + if ($this->options['db_where'] != '') { + // there is one, so add it to the query + $query .= " WHERE ".$this->options['db_where']; + } + + $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG); + + $res = $this->db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (MDB2::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->getCode()); + } else { + foreach ($res as $user) { + $user['username'] = $user[$this->options['usernamecol']]; + $retVal[] = $user; + } + } + $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG); + return $retVal; + } + + // }}} + // {{{ addUser() + + /** + * Add user to the storage container + * + * @access public + * @param string Username + * @param string Password + * @param mixed Additional information that are stored in the DB + * + * @return mixed True on success, otherwise error object + */ + function addUser($username, $password, $additional = "") + { + $this->log('Auth_Container_MDB2::addUser() called.', AUTH_LOG_DEBUG); + + // Prepare for a database query + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') { + $cryptFunction = 'strval'; + } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) { + $cryptFunction = $this->options['cryptType']; + } else { + $cryptFunction = 'md5'; + } + + $password = $cryptFunction($password); + + $additional_key = ''; + $additional_value = ''; + + if (is_array($additional)) { + foreach ($additional as $key => $value) { + if ($this->options['auto_quote']) { + $additional_key .= ', ' . $this->db->quoteIdentifier($key, true); + } else { + $additional_key .= ', ' . $key; + } + $additional_value .= ', ' . $this->db->quote($value, 'text'); + } + } + + $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)", + $this->options['final_table'], + $this->options['final_usernamecol'], + $this->options['final_passwordcol'], + $additional_key, + $this->db->quote($username, 'text'), + $this->db->quote($password, 'text'), + $additional_value + ); + + $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG); + + $res = $this->query($query); + + if (MDB2::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->code); + } + return true; + } + + // }}} + // {{{ removeUser() + + /** + * Remove user from the storage container + * + * @access public + * @param string Username + * + * @return mixed True on success, otherwise error object + */ + function removeUser($username) + { + $this->log('Auth_Container_MDB2::removeUser() called.', AUTH_LOG_DEBUG); + // Prepare for a database query + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + $query = sprintf("DELETE FROM %s WHERE %s = %s", + $this->options['final_table'], + $this->options['final_usernamecol'], + $this->db->quote($username, 'text') + ); + + // check if there is an optional parameter db_where + if ($this->options['db_where'] != '') { + // there is one, so add it to the query + $query .= " AND ".$this->options['db_where']; + } + + $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG); + + $res = $this->query($query); + + if (MDB2::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->code); + } + return true; + } + + // }}} + // {{{ changePassword() + + /** + * Change password for user in the storage container + * + * @param string Username + * @param string The new password (plain text) + */ + function changePassword($username, $password) + { + $this->log('Auth_Container_MDB2::changePassword() called.', AUTH_LOG_DEBUG); + // Prepare for a database query + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') { + $cryptFunction = 'strval'; + } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) { + $cryptFunction = $this->options['cryptType']; + } else { + $cryptFunction = 'md5'; + } + + $password = $cryptFunction($password); + + $query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s", + $this->options['final_table'], + $this->options['final_passwordcol'], + $this->db->quote($password, 'text'), + $this->options['final_usernamecol'], + $this->db->quote($username, 'text') + ); + + // check if there is an optional parameter db_where + if ($this->options['db_where'] != '') { + // there is one, so add it to the query + $query .= " AND ".$this->options['db_where']; + } + + $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG); + + $res = $this->query($query); + + if (MDB2::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->code); + } + return true; + } + + // }}} + // {{{ supportsChallengeResponse() + + /** + * Determine if this container supports + * password authentication with challenge response + * + * @return bool + * @access public + */ + function supportsChallengeResponse() + { + return in_array($this->options['cryptType'], array('md5', 'none', '')); + } + + // }}} + // {{{ getCryptType() + + /** + * Returns the selected crypt type for this container + * + * @return string Function used to crypt the password + */ + function getCryptType() + { + return $this->options['cryptType']; + } + + // }}} + +} +?> diff --git a/lib/Pear/Config.php b/lib/Pear/Config.php new file mode 100644 index 0000000..368f450 --- /dev/null +++ b/lib/Pear/Config.php @@ -0,0 +1,231 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Config.php,v 1.22 2006/12/22 00:35:34 aashley Exp $ + +require_once('PEAR.php'); +require_once('Config/Container.php'); + +$GLOBALS['CONFIG_TYPES'] = + array( + 'apache' => array('Config/Container/Apache.php', 'Config_Container_Apache'), + 'genericconf' => array('Config/Container/GenericConf.php', 'Config_Container_GenericConf'), + 'inifile' => array('Config/Container/IniFile.php', 'Config_Container_IniFile'), + 'inicommented' => array('Config/Container/IniCommented.php', 'Config_Container_IniCommented'), + 'phparray' => array('Config/Container/PHPArray.php', 'Config_Container_PHPArray'), + 'phpconstants' => array('Config/Container/PHPConstants.php', 'Config_Container_PHPConstants'), + 'xml' => array('Config/Container/XML.php', 'Config_Container_XML') + ); + +/** +* Config +* +* This class allows for parsing and editing of configuration datasources. +* Do not use this class only to read datasources because of the overhead +* it creates to keep track of the configuration structure. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config { + + /** + * Datasource + * Can be a file url, a dsn, an object... + * @var mixed + */ + var $datasrc; + + /** + * Type of datasource for config + * Ex: IniCommented, Apache... + * @var string + */ + var $configType = ''; + + /** + * Options for parser + * @var string + */ + var $parserOptions = array(); + + /** + * Container object + * @var object + */ + var $container; + + /** + * Constructor + * Creates a root container + * + * @access public + */ + function Config() + { + $this->container =& new Config_Container('section', 'root'); + } // end constructor + + /** + * Returns true if container is registered + * + * @param string $configType Type of config + * @access public + * @return bool + */ + function isConfigTypeRegistered($configType) + { + return isset($GLOBALS['CONFIG_TYPES'][strtolower($configType)]); + } // end func isConfigTypeRegistered + + /** + * Register a new container + * + * @param string $configType Type of config + * @param array|false $configInfo Array of format: + * array('path/to/Name.php', + * 'Config_Container_Class_Name'). + * + * If left false, defaults to: + * array('Config/Container/$configType.php', + * 'Config_Container_$configType') + * @access public + * @static + * @author Greg Beaver + * @return true|PEAR_Error true on success + */ + function registerConfigType($configType, $configInfo = false) + { + if (Config::isConfigTypeRegistered($configType)) { + $info = $GLOBALS['CONFIG_TYPES'][strtolower($configType)]; + if ($info[0] == $configInfo[0] && + $info[1] == $configInfo[1]) { + return true; + } else { + return PEAR::raiseError("Config::registerConfigType registration of existing $configType failed.", null, PEAR_ERROR_RETURN); + } + } + if (!is_array($configInfo)) { + // make the normal assumption, that this is a standard config container added in at runtime + $configInfo = array('Config/Container/' . $configType . '.php', + 'Config_Container_'. $configType); + } + $file_exists = @include_once($configInfo[0]); + if ($file_exists) { + if (!class_exists($configInfo[1])) { + return PEAR::raiseError("Config::registerConfigType class '$configInfo[1]' not found in $configInfo[0]", null, PEAR_ERROR_RETURN); + } + } else { + return PEAR::raiseError("Config::registerConfigType file $configInfo[0] not found", null, PEAR_ERROR_RETURN); + } + $GLOBALS['CONFIG_TYPES'][strtolower($configType)] = $configInfo; + return true; + } // end func registerConfigType + + /** + * Returns the root container for this config object + * + * @access public + * @return object reference to config's root container object + */ + function &getRoot() + { + return $this->container; + } // end func getRoot + + /** + * Sets the content of the root Config_container object. + * + * This method will replace the current child of the root + * Config_Container object by the given object. + * + * @param object $rootContainer container to be used as the first child to root + * @access public + * @return mixed true on success or PEAR_Error + */ + function setRoot(&$rootContainer) + { + if (is_object($rootContainer) && strtolower(get_class($rootContainer)) === 'config_container') { + if ($rootContainer->getName() === 'root' && $rootContainer->getType() === 'section') { + $this->container =& $rootContainer; + } else { + $this->container =& new Config_Container('section', 'root'); + $this->container->addItem($rootContainer); + } + return true; + } else { + return PEAR::raiseError("Config::setRoot only accepts object of Config_Container type.", null, PEAR_ERROR_RETURN); + } + } // end func setRoot + + /** + * Parses the datasource contents + * + * This method will parse the datasource given and fill the root + * Config_Container object with other Config_Container objects. + * + * @param mixed $datasrc Datasource to parse + * @param string $configType Type of configuration + * @param array $options Options for the parser + * @access public + * @return mixed PEAR_Error on error or Config_Container object + */ + function &parseConfig($datasrc, $configType, $options = array()) + { + $configType = strtolower($configType); + if (!$this->isConfigTypeRegistered($configType)) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config::parseConfig.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + + $parser = new $className($options); + $error = $parser->parseDatasrc($datasrc, $this); + if ($error !== true) { + return $error; + } + $this->parserOptions = $parser->options; + $this->datasrc = $datasrc; + $this->configType = $configType; + return $this->container; + } // end func &parseConfig + + /** + * Writes the container contents to the datasource. + * + * @param mixed $datasrc Datasource to write to + * @param string $configType Type of configuration + * @param array $options Options for config container + * @access public + * @return mixed PEAR_Error on error or true if ok + */ + function writeConfig($datasrc = null, $configType = null, $options = array()) + { + if (empty($datasrc)) { + $datasrc = $this->datasrc; + } + if (empty($configType)) { + $configType = $this->configType; + } + if (empty($options)) { + $options = $this->parserOptions; + } + return $this->container->writeDatasrc($datasrc, $configType, $options); + } // end func writeConfig +} // end class Config +?> diff --git a/lib/Pear/Config/Container.php b/lib/Pear/Config/Container.php new file mode 100644 index 0000000..a143eb6 --- /dev/null +++ b/lib/Pear/Config/Container.php @@ -0,0 +1,776 @@ + | +// +---------------------------------------------------------------------+ +// +// $Id: Container.php,v 1.41 2006/05/30 06:37:28 aashley Exp $ + +require_once 'Config.php'; + +/** +* Interface for Config containers +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container { + + /** + * Container object type + * Ex: section, directive, comment, blank + * @var string + */ + var $type; + + /** + * Container object name + * @var string + */ + var $name = ''; + + /** + * Container object content + * @var string + */ + var $content = ''; + + /** + * Container object children + * @var array + */ + var $children = array(); + + /** + * Reference to container object's parent + * @var object + */ + var $parent; + + /** + * Array of attributes for this item + * @var array + */ + var $attributes; + + /** + * Unique id to differenciate nodes + * + * This is used to compare nodes + * Will not be needed anymore when this class will use ZendEngine 2 + * + * @var int + */ + var $_id; + + /** + * Constructor + * + * @param string $type Type of container object + * @param string $name Name of container object + * @param string $content Content of container object + * @param array $attributes Array of attributes for container object + */ + function Config_Container($type = 'section', $name = '', $content = '', $attributes = null) + { + $this->type = $type; + $this->name = $name; + $this->content = $content; + $this->attributes = $attributes; + $this->parent = null; + if (version_compare(PHP_VERSION, '5.0.0', 'gt')) { + $this->_id = uniqid($name.$type, true); + } else { + $this->_id = uniqid(substr($name.$type, 0, 114), true); + } + } // end constructor + + /** + * Create a child for this item. + * @param string $type type of item: directive, section, comment, blank... + * @param mixed $item item name + * @param string $content item content + * @param array $attributes item attributes + * @param string $where choose a position 'bottom', 'top', 'after', 'before' + * @param object $target needed if you choose 'before' or 'after' for where + * @return object reference to new item or Pear_Error + */ + function &createItem($type, $name, $content, $attributes = null, $where = 'bottom', $target = null) + { + $item =& new Config_Container($type, $name, $content, $attributes); + $result =& $this->addItem($item, $where, $target); + return $result; + } // end func &createItem + + /** + * Adds an item to this item. + * @param object $item a container object + * @param string $where choose a position 'bottom', 'top', 'after', 'before' + * @param object $target needed if you choose 'before' or 'after' in $where + * @return mixed reference to added container on success, Pear_Error on error + */ + function &addItem(&$item, $where = 'bottom', $target = null) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::addItem must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + if (is_null($target)) { + $target =& $this; + } + if (strtolower(get_class($target)) != 'config_container') { + return PEAR::raiseError('Target must be a Config_Container object in Config_Container::addItem.', null, PEAR_ERROR_RETURN); + } + + switch ($where) { + case 'before': + $index = $target->getItemIndex(); + break; + case 'after': + $index = $target->getItemIndex()+1; + break; + case 'top': + $index = 0; + break; + case 'bottom': + $index = -1; + break; + default: + return PEAR::raiseError('Use only top, bottom, before or after in Config_Container::addItem.', null, PEAR_ERROR_RETURN); + } + if (isset($index) && $index >= 0) { + array_splice($this->children, $index, 0, 'tmp'); + } else { + $index = count($this->children); + } + $this->children[$index] =& $item; + $this->children[$index]->parent =& $this; + + return $item; + } // end func addItem + + /** + * Adds a comment to this item. + * This is a helper method that calls createItem + * + * @param string $content Object content + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createComment($content = '', $where = 'bottom', $target = null) + { + return $this->createItem('comment', null, $content, null, $where, $target); + } // end func &createComment + + /** + * Adds a blank line to this item. + * This is a helper method that calls createItem + * + * @return object reference to new item or Pear_Error + */ + function &createBlank($where = 'bottom', $target = null) + { + return $this->createItem('blank', null, null, null, $where, $target); + } // end func &createBlank + + /** + * Adds a directive to this item. + * This is a helper method that calls createItem + * + * @param string $name Name of new directive + * @param string $content Content of new directive + * @param mixed $attributes Directive attributes + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createDirective($name, $content, $attributes = null, $where = 'bottom', $target = null) + { + return $this->createItem('directive', $name, $content, $attributes, $where, $target); + } // end func &createDirective + + /** + * Adds a section to this item. + * + * This is a helper method that calls createItem + * If the section already exists, it won't create a new one. + * It will return reference to existing item. + * + * @param string $name Name of new section + * @param array $attributes Section attributes + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createSection($name, $attributes = null, $where = 'bottom', $target = null) + { + return $this->createItem('section', $name, null, $attributes, $where, $target); + } // end func &createSection + + /** + * Tries to find the specified item(s) and returns the objects. + * + * Examples: + * $directives =& $obj->getItem('directive'); + * $directive_bar_4 =& $obj->getItem('directive', 'bar', null, 4); + * $section_foo =& $obj->getItem('section', 'foo'); + * + * This method can only be called on an object of type 'section'. + * Note that root is a section. + * This method is not recursive and tries to keep the current structure. + * For a deeper search, use searchPath() + * + * @param string $type Type of item: directive, section, comment, blank... + * @param mixed $name Item name + * @param mixed $content Find item with this content + * @param array $attributes Find item with attribute set to the given value + * @param int $index Index of the item in the returned object list. If it is not set, will try to return the last item with this name. + * @return mixed reference to item found or false when not found + * @see &searchPath() + */ + function &getItem($type = null, $name = null, $content = null, $attributes = null, $index = -1) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::getItem must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + if (!is_null($type)) { + $testFields[] = 'type'; + } + if (!is_null($name)) { + $testFields[] = 'name'; + } + if (!is_null($content)) { + $testFields[] = 'content'; + } + if (!is_null($attributes) && is_array($attributes)) { + $testFields[] = 'attributes'; + } + + $itemsArr = array(); + $fieldsToMatch = count($testFields); + for ($i = 0, $count = count($this->children); $i < $count; $i++) { + $match = 0; + reset($testFields); + foreach ($testFields as $field) { + if ($field != 'attributes') { + if ($this->children[$i]->$field == ${$field}) { + $match++; + } + } else { + // Look for attributes in array + $attrToMatch = count($attributes); + $attrMatch = 0; + foreach ($attributes as $key => $value) { + if (isset($this->children[$i]->attributes[$key]) && + $this->children[$i]->attributes[$key] == $value) { + $attrMatch++; + } + } + if ($attrMatch == $attrToMatch) { + $match++; + } + } + } + if ($match == $fieldsToMatch) { + $itemsArr[] =& $this->children[$i]; + } + } + if ($index >= 0) { + if (isset($itemsArr[$index])) { + return $itemsArr[$index]; + } else { + $return = false; + return $return; + } + } else { + if ($count = count($itemsArr)) { + return $itemsArr[$count-1]; + } else { + $return = false; + return $return; + } + } + } // end func &getItem + + /** + * Finds a node using XPATH like format. + * + * The search format is an array: + * array(item1, item2, item3, ...) + * + * Each item can be defined as the following: + * item = 'string' : will match the container named 'string' + * item = array('string', array('name' => 'xyz')) + * will match the container name 'string' whose attribute name is equal to "xyz" + * For example : + * + * @param mixed Search path and attributes + * + * @return mixed Config_Container object, array of Config_Container objects or false on failure. + * @access public + */ + function &searchPath($args) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::searchPath must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + + $arg = array_shift($args); + + if (is_array($arg)) { + $name = $arg[0]; + $attributes = $arg[1]; + } else { + $name = $arg; + $attributes = null; + } + // find all the matches for first.. + $match =& $this->getItem(null, $name, null, $attributes); + + if (!$match) { + $return = false; + return $return; + } + if (!empty($args)) { + return $match->searchPath($args); + } + return $match; + } // end func &searchPath + + /** + * Return a child directive's content. + * + * This method can use two different search approach, depending on + * the parameter it is given. If the parameter is an array, it will use + * the {@link Config_Container::searchPath()} method. If it is a string, + * it will use the {@link Config_Container::getItem()} method. + * + * Example: + * + * require_once 'Config.php'; + * $ini = new Config(); + * $conf =& $ini->parseConfig('/path/to/config.ini', 'inicommented'); + * + * // Will return the value found at : + * // [Database] + * // host=localhost + * echo $conf->directiveContent(array('Database', 'host'))); + * + * // Will return the value found at : + * // date="dec-2004" + * echo $conf->directiveContent('date'); + * + * + * + * @param mixed Search path and attributes or a directive name + * @param int Index of the item in the returned directive list. + * Eventually used if args is a string. + * + * @return mixed Content of directive or false if not found. + * @access public + */ + function directiveContent($args, $index = -1) + { + if (is_array($args)) { + $item =& $this->searchPath($args); + } else { + $item =& $this->getItem('directive', $args, null, null, $index); + } + if ($item) { + return $item->getContent(); + } + return false; + } // end func getDirectiveContent + + /** + * Returns how many children this container has + * + * @param string $type type of children counted + * @param string $name name of children counted + * @return int number of children found + */ + function countChildren($type = null, $name = null) + { + if (is_null($type) && is_null($name)) { + return count($this->children); + } + $count = 0; + if (isset($name) && isset($type)) { + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->name === $name && + $this->children[$i]->type == $type) { + $count++; + } + } + return $count; + } + if (isset($type)) { + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->type == $type) { + $count++; + } + } + return $count; + } + if (isset($name)) { + // Some directives can have the same name + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->name === $name) { + $count++; + } + } + return $count; + } + } // end func &countChildren + + /** + * Deletes an item (section, directive, comment...) from the current object + * TODO: recursive remove in sub-sections + * @return mixed true if object was removed, false if not, or PEAR_Error if root + */ + function removeItem() + { + if ($this->isRoot()) { + return PEAR::raiseError('Cannot remove root item in Config_Container::removeItem.', null, PEAR_ERROR_RETURN); + } + $index = $this->getItemIndex(); + if (!is_null($index)) { + array_splice($this->parent->children, $index, 1); + return true; + } + return false; + } // end func removeItem + + /** + * Returns the item index in its parent children array. + * @return int returns int or null if root object + */ + function getItemIndex() + { + if (is_object($this->parent)) { + // This will be optimized with Zend Engine 2 + $pchildren =& $this->parent->children; + for ($i = 0, $count = count($pchildren); $i < $count; $i++) { + if ($pchildren[$i]->_id == $this->_id) { + return $i; + } + } + } + return; + } // end func getItemIndex + + /** + * Returns the item rank in its parent children array + * according to other items with same type and name. + * @param bool count items differently by type + * @return int returns int or null if root object + */ + function getItemPosition($byType = true) + { + if (is_object($this->parent)) { + $pchildren =& $this->parent->children; + for ($i = 0, $count = count($pchildren); $i < $count; $i++) { + if ($pchildren[$i]->name == $this->name) { + if ($byType == true) { + if ($pchildren[$i]->type == $this->type) { + $obj[] =& $pchildren[$i]; + } + } else { + $obj[] =& $pchildren[$i]; + } + } + } + for ($i = 0, $count = count($obj); $i < $count; $i++) { + if ($obj[$i]->_id == $this->_id) { + return $i; + } + } + } + return; + } // end func getItemPosition + + /** + * Returns the item parent object. + * @return object returns reference to parent object or null if root object + */ + function &getParent() + { + return $this->parent; + } // end func &getParent + + /** + * Returns the item parent object. + * @return mixed returns reference to child object or false if child does not exist + */ + function &getChild($index = 0) + { + if (!empty($this->children[$index])) { + return $this->children[$index]; + } else { + return false; + } + } // end func &getChild + + /** + * Set this item's name. + * @return void + */ + function setName($name) + { + $this->name = $name; + } // end func setName + + /** + * Get this item's name. + * @return string item's name + */ + function getName() + { + return $this->name; + } // end func getName + + /** + * Set this item's content. + * @return void + */ + function setContent($content) + { + $this->content = $content; + } // end func setContent + + /** + * Get this item's content. + * @return string item's content + */ + function getContent() + { + return $this->content; + } // end func getContent + + /** + * Set this item's type. + * @return void + */ + function setType($type) + { + $this->type = $type; + } // end func setType + + /** + * Get this item's type. + * @return string item's type + */ + function getType() + { + return $this->type; + } // end func getType + + /** + * Set this item's attributes. + * @param array $attributes Array of attributes + * @return void + */ + function setAttributes($attributes) + { + $this->attributes = $attributes; + } // end func setAttributes + + /** + * Set this item's attributes. + * @param array $attributes Array of attributes + * @return void + */ + function updateAttributes($attributes) + { + if (is_array($attributes)) { + foreach ($attributes as $key => $value) { + $this->attributes[$key] = $value; + } + } + } // end func updateAttributes + + /** + * Get this item's attributes. + * @return array item's attributes + */ + function getAttributes() + { + return $this->attributes; + } // end func getAttributes + + /** + * Get one attribute value of this item + * @param string $attribute Attribute key + * @return mixed item's attribute value + */ + function getAttribute($attribute) + { + if (isset($this->attributes[$attribute])) { + return $this->attributes[$attribute]; + } + return null; + } // end func getAttribute + + /** + * Set a children directive content. + * This is an helper method calling getItem and addItem or setContent for you. + * If the directive does not exist, it will be created at the bottom. + * + * @param string $name Name of the directive to look for + * @param mixed $content New content + * @param int $index Index of the directive to set, + * in case there are more than one directive + * with the same name + * @return object newly set directive + */ + function &setDirective($name, $content, $index = -1) + { + $item =& $this->getItem('directive', $name, null, null, $index); + if ($item === false || PEAR::isError($item)) { + // Directive does not exist, will create one + unset($item); + return $this->createDirective($name, $content, null); + } else { + // Change existing directive value + $item->setContent($content); + return $item; + } + } // end func setDirective + + /** + * Is this item root, in a config container object + * @return bool true if item is root + */ + function isRoot() + { + if (is_null($this->parent)) { + return true; + } + return false; + } // end func isRoot + + /** + * Call the toString methods in the container plugin + * @param string $configType Type of configuration used to generate the string + * @param array $options Specify special options used by the parser + * @return mixed true on success or PEAR_ERROR + */ + function toString($configType, $options = array()) + { + $configType = strtolower($configType); + if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::toString.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + $renderer = new $className($options); + return $renderer->toString($this); + } // end func toString + + /** + * Returns a key/value pair array of the container and its children. + * + * Format : section[directive][index] = value + * If the container has attributes, it will use '@' and '#' + * index is here because multiple directives can have the same name. + * + * @param bool $useAttr Whether to return the attributes too + * @return array + */ + function toArray($useAttr = true) + { + $array[$this->name] = array(); + switch ($this->type) { + case 'directive': + if ($useAttr && count($this->attributes) > 0) { + $array[$this->name]['#'] = $this->content; + $array[$this->name]['@'] = $this->attributes; + } else { + $array[$this->name] = $this->content; + } + break; + case 'section': + if ($useAttr && count($this->attributes) > 0) { + $array[$this->name]['@'] = $this->attributes; + } + if ($count = count($this->children)) { + for ($i = 0; $i < $count; $i++) { + $newArr = $this->children[$i]->toArray($useAttr); + if (!is_null($newArr)) { + foreach ($newArr as $key => $value) { + if (isset($array[$this->name][$key])) { + // duplicate name/type + if (!is_array($array[$this->name][$key]) || + !isset($array[$this->name][$key][0])) { + $old = $array[$this->name][$key]; + unset($array[$this->name][$key]); + $array[$this->name][$key][0] = $old; + } + $array[$this->name][$key][] = $value; + } else { + $array[$this->name][$key] = $value; + } + } + } + } + } + break; + default: + return null; + } + return $array; + } // end func toArray + + /** + * Writes the configuration to a file + * + * @param mixed $datasrc Info on datasource such as path to the configuraton file or dsn... + * @param string $configType Type of configuration + * @param array $options Options for writer + * @access public + * @return mixed true on success or PEAR_ERROR + */ + function writeDatasrc($datasrc, $configType, $options = array()) + { + $configType = strtolower($configType); + if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::writeDatasrc.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + + $writeMethodName = (version_compare(phpversion(), '5', '<')) ? 'writedatasrc' : 'writeDatasrc'; + if (in_array($writeMethodName, get_class_methods($className))) { + $writer = new $className($options); + return $writer->writeDatasrc($datasrc, $this); + } + + // Default behaviour + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = $this->toString($configType, $options); + $len = strlen($string); + @flock($fp, LOCK_EX); + @fwrite($fp, $string, $len); + @flock($fp, LOCK_UN); + @fclose($fp); + return true; + } else { + return PEAR::raiseError('Cannot open datasource for writing.', 1, PEAR_ERROR_RETURN); + } + } // end func writeDatasrc +} // end class Config_Container +?> diff --git a/lib/Pear/Config/Container/Apache.php b/lib/Pear/Config/Container/Apache.php new file mode 100644 index 0000000..fe406ae --- /dev/null +++ b/lib/Pear/Config/Container/Apache.php @@ -0,0 +1,169 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Apache.php,v 1.11 2005/12/24 02:34:39 aashley Exp $ + +/** +* Simple config parser for apache httpd.conf files +* A more complex version could handle directives as +* associative arrays. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_Apache { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_Apache($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!is_readable($datasrc)) { + return PEAR::raiseError("Datasource file cannot be read.", null, PEAR_ERROR_RETURN); + } + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $sections[0] =& $obj->container; + foreach ($lines as $line) { + $n++; + if (!preg_match('/^\s*#/', $line) && + preg_match('/^\s*(.*)\s+\\\$/', $line, $match)) { + // directive on more than one line + $lastline .= $match[1].' '; + continue; + } + if ($lastline != '') { + $line = $lastline.trim($line); + $lastline = ''; + } + if (preg_match('/^\s*#+\s*(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection =& $sections[count($sections)-1]; + $currentSection->createComment($match[1]); + } elseif (trim($line) == '') { + // a blank line + $currentSection =& $sections[count($sections)-1]; + $currentSection->createBlank(); + } elseif (preg_match('/^\s*(\w+)(?:\s+(.*?)|)\s*$/', $line, $match)) { + // a directive + $currentSection =& $sections[count($sections)-1]; + $currentSection->createDirective($match[1], $match[2]); + } elseif (preg_match('/^\s*<(\w+)(?:\s+([^>]*)|\s*)>\s*$/', $line, $match)) { + // a section opening + if (!isset($match[2])) + $match[2] = ''; + $currentSection =& $sections[count($sections)-1]; + $attributes = explode(' ', $match[2]); + $sections[] =& $currentSection->createSection($match[1], $attributes); + } elseif (preg_match('/^\s*<\/(\w+)\s*>\s*$/', $line, $match)) { + // a section closing + $currentSection =& $sections[count($sections)-1]; + if ($currentSection->name != $match[1]) { + return PEAR::raiseError("Section not closed in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + array_pop($sections); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return $return; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $deep = -1; + $ident = ''; + if (!$obj->isRoot()) { + // no indent for root + $deep++; + $ident = str_repeat(' ', $deep); + } + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = $ident.'# '.$obj->content."\n"; + break; + case 'directive': + $string = $ident.$obj->name.' '.$obj->content."\n"; + break; + case 'section': + if (!$obj->isRoot()) { + $string = $ident.'<'.$obj->name; + if (is_array($obj->attributes) && count($obj->attributes) > 0) { + foreach ($obj->attributes as $attr => $val) { + $string .= ' '.$val; + } + } + $string .= ">\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + if (!$obj->isRoot()) { + // object is not root + $string .= $ident.'name.">\n"; + } + break; + default: + $string = ''; + } + if (!$obj->isRoot()) { + $deep--; + } + return $string; + } // end func toString +} // end class Config_Container_Apache +?> diff --git a/lib/Pear/Config/Container/GenericConf.php b/lib/Pear/Config/Container/GenericConf.php new file mode 100644 index 0000000..a6aef5d --- /dev/null +++ b/lib/Pear/Config/Container/GenericConf.php @@ -0,0 +1,139 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: GenericConf.php,v 1.7 2005/12/24 02:24:30 aashley Exp $ + +/** +* Config parser for generic .conf files like +* htdig.conf... +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_GenericConf { + + /** + * This class options: + * Ex: $options['comment'] = '#'; + * Ex: $options['equals'] = ':'; + * Ex: $options['newline'] = '\\'; + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_GenericConf($options = array()) + { + if (empty($options['comment'])) { + $options['comment'] = '#'; + } + if (empty($options['equals'])) { + $options['equals'] = ':'; + } + if (empty($options['newline'])) { + $options['newline'] = '\\'; + } + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!is_readable($datasrc)) { + return PEAR::raiseError("Datasource file cannot be read.", null, PEAR_ERROR_RETURN); + } + + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $currentSection =& $obj->container; + foreach ($lines as $line) { + $n++; + if (!preg_match('/^\s*'.$this->options['comment'].'/', $line) && + preg_match('/^\s*(.*)\s+'.$this->options['newline'].'\s*$/', $line, $match)) { + // directive on more than one line + $lastline .= $match[1].' '; + continue; + } + if ($lastline != '') { + $line = $lastline.trim($line); + $lastline = ''; + } + if (preg_match('/^\s*'.$this->options['comment'].'+\s*(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection->createComment($match[1]); + } elseif (preg_match('/^\s*$/', $line)) { + // a blank line + $currentSection->createBlank(); + } elseif (preg_match('/^\s*(\w+)'.$this->options['equals'].'\s*((.*?)|)\s*$/', $line, $match)) { + // a directive + $currentSection->createDirective($match[1], $match[2]); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return $return; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $string = ''; + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = $this->options['comment'].$obj->content."\n"; + break; + case 'directive': + $string = $obj->name.$this->options['equals'].$obj->content."\n"; + break; + case 'section': + // How to deal with sections ??? + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_GenericConf +?> diff --git a/lib/Pear/Config/Container/IniCommented.php b/lib/Pear/Config/Container/IniCommented.php new file mode 100644 index 0000000..5c2315c --- /dev/null +++ b/lib/Pear/Config/Container/IniCommented.php @@ -0,0 +1,327 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: IniCommented.php,v 1.26 2006/05/30 06:51:05 aashley Exp $ + +/** +* Config parser for PHP .ini files with comments +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_IniCommented { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_IniCommented($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $currentSection =& $obj->container; + foreach ($lines as $line) { + $n++; + if (preg_match('/^\s*;(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection->createComment($match[1]); + } elseif (preg_match('/^\s*$/', $line)) { + // a blank line + $currentSection->createBlank(); + } elseif (preg_match('/^\s*([a-zA-Z0-9_\-\.\s:]*)\s*=\s*(.*)\s*$/', $line, $match)) { + // a directive + + $values = $this->_quoteAndCommaParser($match[2]); + if (PEAR::isError($values)) { + return PEAR::raiseError($values); + } + + if (count($values)) { + foreach($values as $value) { + if ($value[0] == 'normal') { + $currentSection->createDirective(trim($match[1]), $value[1]); + } + if ($value[0] == 'comment') { + $currentSection->createComment(substr($value[1], 1)); + } + } + } + } elseif (preg_match('/^\s*\[\s*(.*)\s*\]\s*$/', $line, $match)) { + // a section + $currentSection =& $obj->container->createSection($match[1]); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return $return; + } // end func parseDatasrc + + /** + * Quote and Comma Parser for INI files + * + * This function allows complex values such as: + * + * + * mydirective = "Item, number \"1\"", Item 2 ; "This" is really, really tricky + * + * @param string $text value of a directive to parse for quotes/multiple values + * @return array The array returned contains multiple values, if any (unquoted literals + * to be used as is), and a comment, if any. The format of the array is: + * + *
+     * array(array('normal', 'first value'),
+     *       array('normal', 'next value'),...
+     *       array('comment', '; comment with leading ;'))
+     * 
+ * @author Greg Beaver + * @access private + */ + function _quoteAndCommaParser($text) + { + $text = trim($text); + if ($text == '') { + $emptyNode = array(); + $emptyNode[0][0] = 'normal'; + $emptyNode[0][1] = ''; + return $emptyNode; + } + + // tokens + $tokens['normal'] = array('"', ';', ','); + $tokens['quote'] = array('"', '\\'); + $tokens['escape'] = false; // cycle + $tokens['after_quote'] = array(',', ';'); + + // events + $events['normal'] = array('"' => 'quote', ';' => 'comment', ',' => 'normal'); + $events['quote'] = array('"' => 'after_quote', '\\' => 'escape'); + $events['after_quote'] = array(',' => 'normal', ';' => 'comment'); + + // state stack + $stack = array(); + + // return information + $return = array(); + $returnpos = 0; + $returntype = 'normal'; + + // initialize + array_push($stack, 'normal'); + $pos = 0; // position in $text + + do { + $char = $text{$pos}; + $state = $this->_getQACEvent($stack); + + if ($tokens[$state]) { + if (in_array($char, $tokens[$state])) { + switch($events[$state][$char]) { + case 'quote' : + if ($state == 'normal' && + isset($return[$returnpos]) && + !empty($return[$returnpos][1])) { + return PEAR::raiseError("invalid ini syntax, quotes cannot follow text '$text'", + null, PEAR_ERROR_RETURN); + } + if ($returnpos >= 0 && isset($return[$returnpos])) { + // trim any unnecessary whitespace in earlier entries + $return[$returnpos][1] = trim($return[$returnpos][1]); + } else { + $returnpos++; + } + $return[$returnpos] = array('normal', ''); + array_push($stack, 'quote'); + continue 2; + break; + case 'comment' : + // comments go to the end of the line, so we are done + $return[++$returnpos] = array('comment', substr($text, $pos)); + return $return; + break; + case 'after_quote' : + array_push($stack, 'after_quote'); + break; + case 'escape' : + // don't save the first slash + array_push($stack, 'escape'); + continue 2; + break; + case 'normal' : + // start a new segment + if ($state == 'normal') { + $returnpos++; + continue 2; + } else { + while ($state != 'normal') { + array_pop($stack); + $state = $this->_getQACEvent($stack); + } + $returnpos++; + } + break; + default : + PEAR::raiseError("::_quoteAndCommaParser oops, state missing", null, PEAR_ERROR_DIE); + break; + } + } else { + if ($state != 'after_quote') { + if (!isset($return[$returnpos])) { + $return[$returnpos] = array('normal', ''); + } + // add this character to the current ini segment if non-empty, or if in a quote + if ($state == 'quote') { + $return[$returnpos][1] .= $char; + } elseif (!empty($return[$returnpos][1]) || + (empty($return[$returnpos][1]) && trim($char) != '')) { + if (!isset($return[$returnpos])) { + $return[$returnpos] = array('normal', ''); + } + $return[$returnpos][1] .= $char; + if (strcasecmp('true', $return[$returnpos][1]) == 0) { + $return[$returnpos][1] = '1'; + } elseif (strcasecmp('false', $return[$returnpos][1]) == 0) { + $return[$returnpos][1] = ''; + } + } + } else { + if (trim($char) != '') { + return PEAR::raiseError("invalid ini syntax, text after a quote not allowed '$text'", + null, PEAR_ERROR_RETURN); + } + } + } + } else { + // no tokens, so add this one and cycle to previous state + $return[$returnpos][1] .= $char; + array_pop($stack); + } + } while (++$pos < strlen($text)); + return $return; + } // end func _quoteAndCommaParser + + /** + * Retrieve the state off of a state stack for the Quote and Comma Parser + * @param array $stack The parser state stack + * @author Greg Beaver + * @access private + */ + function _getQACEvent($stack) + { + return array_pop($stack); + } // end func _getQACEvent + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $childrenCount, $commaString; + + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = ';'.$obj->content."\n"; + break; + case 'directive': + $count = $obj->parent->countChildren('directive', $obj->name); + $content = $obj->content; + if ($content === false) { + $content = '0'; + } elseif ($content === true) { + $content = '1'; + } elseif (strlen(trim($content)) < strlen($content) || + strpos($content, ',') !== false || + strpos($content, ';') !== false || + strpos($content, '=') !== false || + strpos($content, '"') !== false || + strpos($content, '%') !== false || + strpos($content, '~') !== false) { + $content = '"'.addslashes($content).'"'; + } + if ($count > 1) { + // multiple values for a directive are separated by a comma + if (isset($childrenCount[$obj->name])) { + $childrenCount[$obj->name]++; + } else { + $childrenCount[$obj->name] = 0; + $commaString[$obj->name] = $obj->name.' = '; + } + if ($childrenCount[$obj->name] == $count-1) { + // Clean the static for future calls to toString + $string .= $commaString[$obj->name].$content."\n"; + unset($childrenCount[$obj->name]); + unset($commaString[$obj->name]); + } else { + $commaString[$obj->name] .= $content.', '; + } + } else { + $string = $obj->name.' = '.$content."\n"; + } + break; + case 'section': + if (!$obj->isRoot()) { + $string = '['.$obj->name."]\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_IniCommented +?> diff --git a/lib/Pear/Config/Container/IniFile.php b/lib/Pear/Config/Container/IniFile.php new file mode 100644 index 0000000..d32bd57 --- /dev/null +++ b/lib/Pear/Config/Container/IniFile.php @@ -0,0 +1,165 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: IniFile.php,v 1.17 2005/12/24 02:36:56 aashley Exp $ + +/** +* Config parser for PHP .ini files +* Faster because it uses parse_ini_file() but get rid of comments, +* quotes, types and converts On, Off, True, False, Yes, No to 0 and 1. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_IniFile { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_IniFile($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } + $currentSection =& $obj->container; + $confArray = parse_ini_file($datasrc, true); + if (!$confArray) { + return PEAR::raiseError("File '$datasrc' does not contain configuration data.", null, PEAR_ERROR_RETURN); + } + foreach ($confArray as $key => $value) { + if (is_array($value)) { + $currentSection =& $obj->container->createSection($key); + foreach ($value as $directive => $content) { + // try to split the value if comma found + if (strpos($content, '"') === false) { + $values = preg_split('/\s*,\s+/', $content); + if (count($values) > 1) { + foreach ($values as $k => $v) { + $currentSection->createDirective($directive, $v); + } + } else { + $currentSection->createDirective($directive, $content); + } + } else { + $currentSection->createDirective($directive, $content); + } + } + } else { + $currentSection->createDirective($key, $value); + } + } + return $return; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $childrenCount, $commaString; + + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = ';'.$obj->content."\n"; + break; + case 'directive': + $count = $obj->parent->countChildren('directive', $obj->name); + $content = $obj->content; + if ($content === false) { + $content = '0'; + } elseif ($content === true) { + $content = '1'; + } elseif (strlen(trim($content)) < strlen($content) || + strpos($content, ',') !== false || + strpos($content, ';') !== false || + strpos($content, '=') !== false || + strpos($content, '"') !== false || + strpos($content, '%') !== false || + strpos($content, '~') !== false) { + $content = '"'.addslashes($content).'"'; + } + if ($count > 1) { + // multiple values for a directive are separated by a comma + if (isset($childrenCount[$obj->name])) { + $childrenCount[$obj->name]++; + } else { + $childrenCount[$obj->name] = 0; + $commaString[$obj->name] = $obj->name.'='; + } + if ($childrenCount[$obj->name] == $count-1) { + // Clean the static for future calls to toString + $string .= $commaString[$obj->name].$content."\n"; + unset($childrenCount[$obj->name]); + unset($commaString[$obj->name]); + } else { + $commaString[$obj->name] .= $content.', '; + } + } else { + $string = $obj->name.'='.$content."\n"; + } + break; + case 'section': + if (!$obj->isRoot()) { + $string = '['.$obj->name."]\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_IniFile +?> diff --git a/lib/Pear/Config/Container/PHPArray.php b/lib/Pear/Config/Container/PHPArray.php new file mode 100644 index 0000000..68fa317 --- /dev/null +++ b/lib/Pear/Config/Container/PHPArray.php @@ -0,0 +1,251 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: PHPArray.php,v 1.32 2007/06/12 05:24:19 aashley Exp $ + +/** +* Config parser for common PHP configuration array +* such as found in the horde project. +* +* Options expected is: +* 'name' => 'conf' +* Name of the configuration array. +* Default is $conf[]. +* 'useAttr' => true +* Whether we render attributes +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_PHPArray { + + /** + * This class options: + * - name of the config array to parse/output + * Ex: $options['name'] = 'myconf'; + * - Whether to add attributes to the array + * Ex: $options['useAttr'] = false; + * - Whether to treat numbered arrays as duplicates of their parent directive + * or as individual directives + * Ex: $options['duplicateDirectives'] = false; + * + * @var array + */ + var $options = array('name' => 'conf', + 'useAttr' => true, + 'duplicateDirectives' => true); + + /** + * Constructor + * + * @access public + * @param string $options Options to be used by renderer + */ + function Config_Container_PHPArray($options = array()) + { + foreach ($options as $key => $value) { + $this->options[$key] = $value; + } + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (empty($datasrc)) { + return PEAR::raiseError("Datasource file path is empty.", null, PEAR_ERROR_RETURN); + } + if (is_array($datasrc)) { + $this->_parseArray($datasrc, $obj->container); + } else { + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } else { + include($datasrc); + if (!isset(${$this->options['name']}) || !is_array(${$this->options['name']})) { + return PEAR::raiseError("File '$datasrc' does not contain a required '".$this->options['name']."' array.", null, PEAR_ERROR_RETURN); + } + } + $this->_parseArray(${$this->options['name']}, $obj->container); + } + return $return; + } // end func parseDatasrc + + /** + * Parses the PHP array recursively + * @param array $array array values from the config file + * @param object $container reference to the container object + * @access private + * @return void + */ + function _parseArray($array, &$container) + { + foreach ($array as $key => $value) { + switch ((string)$key) { + case '@': + $container->setAttributes($value); + break; + case '#': + $container->setType('directive'); + $container->setContent($value); + break; + default: + if (is_array($value)) { + if ($this->options['duplicateDirectives'] == true && is_integer(key($value))) { + foreach ($value as $nestedValue) { + if (is_array($nestedValue)) { + $section =& $container->createSection($key); + $this->_parseArray($nestedValue, $section); + } else { + $container->createDirective($key, $nestedValue); + } + } + } else { + $section =& $container->createSection($key); + $this->_parseArray($value, $section); + } + } else { + $container->createDirective($key, $value); + } + } + } + } // end func _parseArray + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string .= "\n"; + break; + case 'comment': + $string .= '// '.$obj->content."\n"; + break; + case 'directive': + $attrString = ''; + $parentString = $this->_getParentString($obj); + $attributes = $obj->getAttributes(); + if ($this->options['useAttr'] && is_array($attributes) && count($attributes) > 0) { + // Directive with attributes '@' and value '#' + $string .= $parentString."['#']"; + foreach ($attributes as $attr => $val) { + $attrString .= $parentString."['@']" + ."['".$attr."'] = '".addcslashes($val, "\\'")."';\n"; + } + } else { + $string .= $parentString; + } + $string .= ' = '; + if (is_string($obj->content)) { + $string .= "'".addcslashes($obj->content, "\\'")."'"; + } elseif (is_int($obj->content) || is_float($obj->content)) { + $string .= $obj->content; + } elseif (is_bool($obj->content)) { + $string .= ($obj->content) ? 'true' : 'false'; + } + $string .= ";\n"; + $string .= $attrString; + break; + case 'section': + $attrString = ''; + $attributes = $obj->getAttributes(); + if ($this->options['useAttr'] && is_array($attributes) && count($attributes) > 0) { + $parentString = $this->_getParentString($obj); + foreach ($attributes as $attr => $val) { + $attrString .= $parentString."['@']" + ."['".$attr."'] = '".addcslashes($val, "\\'")."';\n"; + } + } + $string .= $attrString; + if ($count = count($obj->children)) { + for ($i = 0; $i < $count; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString + + /** + * Returns a formatted string of the object parents + * @access private + * @return string + */ + function _getParentString(&$obj) + { + $string = ''; + if (!$obj->isRoot()) { + $string = is_int($obj->name) ? "[".$obj->name."]" : "['".$obj->name."']"; + $string = $this->_getParentString($obj->parent).$string; + $count = $obj->parent->countChildren(null, $obj->name); + if ($count > 1) { + $string .= '['.$obj->getItemPosition(false).']'; + } + } + else { + if (empty($this->options['name'])) { + $string .= '$'.$obj->name; + } else { + $string .= '$'.$this->options['name']; + } + } + return $string; + } // end func _getParentString + + /** + * Writes the configuration to a file + * + * @param mixed datasrc info on datasource such as path to the configuraton file + * @param string configType (optional)type of configuration + * @access public + * @return string + */ + function writeDatasrc($datasrc, &$obj) + { + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = "toString($obj) ."?>"; // diff --git a/lib/Pear/Config/Container/PHPConstants.php b/lib/Pear/Config/Container/PHPConstants.php new file mode 100644 index 0000000..7d5b172 --- /dev/null +++ b/lib/Pear/Config/Container/PHPConstants.php @@ -0,0 +1,199 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: PHPConstants.php,v 1.3 2005/12/24 02:24:30 aashley Exp $ + +/** +* Config parser for PHP constant files +* +* @author Phillip Oertel +* @package Config +* @version 0.1 (not submitted) +*/ + +require_once 'Config/Container.php'; + +class Config_Container_PHPConstants extends Config_Container { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_PHPConstants($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, + PEAR_ERROR_RETURN); + } + + $fileContent = file_get_contents($datasrc, true); + + if (!$fileContent) { + return PEAR::raiseError("File '$datasrc' could not be read.", null, + PEAR_ERROR_RETURN); + } + + $rows = explode("\n", $fileContent); + for ($i=0, $max=count($rows); $i<$max; $i++) { + $line = $rows[$i]; + + //blanks? + + // sections + if (preg_match("/^\/\/\s*$/", $line)) { + preg_match("/^\/\/\s*(.+)$/", $rows[$i+1], $matches); + $obj->container->createSection(trim($matches[1])); + $i += 2; + continue; + } + + // comments + if (preg_match("/^\/\/\s*(.+)$/", $line, $matches) || + preg_match("/^#\s*(.+)$/", $line, $matches)) { + $obj->container->createComment(trim($matches[1])); + continue; + } + + // directives + $regex = "/^\s*define\s*\('([A-Z1-9_]+)',\s*'*(.[^\']*)'*\)/"; + preg_match($regex, $line, $matches); + if (!empty($matches)) { + $obj->container->createDirective(trim($matches[1]), + trim($matches[2])); + } + } + + return $return; + + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $string = ''; + + switch ($obj->type) + { + case 'blank': + $string = "\n"; + break; + + case 'comment': + $string = '// '.$obj->content."\n"; + break; + + case 'directive': + $content = $obj->content; + // don't quote numeric values, true/false and constants + if (!is_numeric($content) && !in_array($content, array('false', + 'true')) && !preg_match('/^[A-Z_]+$/', $content)) { + $content = "'".$content."'"; + } + $string = 'define(\''.$obj->name.'\', '.$content.');'.chr(10); + break; + + case 'section': + if (!$obj->isRoot()) { + $string = chr(10); + $string .= '//'.chr(10); + $string .= '// '.$obj->name.chr(10); + $string .= '//'.chr(10); + } + if (count($obj->children) > 0) { + for ($i = 0, $max = count($obj->children); $i < $max; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString + + /** + * Writes the configuration to a file + * + * @param mixed datasrc info on datasource such as path to the file + * @param string configType (optional)type of configuration + * @access public + * @return string + */ + function writeDatasrc($datasrc, &$obj) + { + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = "toString($obj); + $string .= "\n?>"; // diff --git a/lib/Pear/Config/Container/XML.php b/lib/Pear/Config/Container/XML.php new file mode 100644 index 0000000..7cb7636 --- /dev/null +++ b/lib/Pear/Config/Container/XML.php @@ -0,0 +1,249 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: XML.php,v 1.15 2005/12/24 02:24:30 aashley Exp $ + +require_once('XML/Parser.php'); +require_once('XML/Util.php'); + +/** +* Config parser for XML Files +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_XML extends XML_Parser +{ + /** + * Deep level used for indentation + * + * @var int + * @access private + */ + var $_deep = -1; + + /** + * This class options: + * version (1.0) : XML version + * encoding (ISO-8859-1) : XML content encoding + * name : like in phparray, name of your config global entity + * indent : char used for indentation + * linebreak : char used for linebreak + * addDecl : whether to add the xml declaration at beginning or not + * useAttr : whether to use the attributes + * isFile : whether the given content is a file or an XML string + * useCData : whether to surround data with + * + * @var array + */ + var $options = array('version' => '1.0', + 'encoding' => 'ISO-8859-1', + 'name' => '', + 'indent' => ' ', + 'linebreak' => "\n", + 'addDecl' => true, + 'useAttr' => true, + 'isFile' => true, + 'useCData' => false); + + /** + * Container objects + * + * @var array + */ + var $containers = array(); + + /** + * Constructor + * + * @access public + * @param string $options Options to be used by renderer + * version : (1.0) XML version + * encoding : (ISO-8859-1) XML content encoding + * name : like in phparray, name of your config global entity + * indent : char used for indentation + * linebreak : char used for linebreak + * addDecl : whether to add the xml declaration at beginning or not + * useAttr : whether to use the attributes + * isFile : whether the given content is a file or an XML string + */ + function Config_Container_XML($options = array()) + { + foreach ($options as $key => $value) { + $this->options[$key] = $value; + } + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $err = true; + $this->folding = false; + $this->cdata = null; + $this->XML_Parser($this->options['encoding'], 'event'); + $this->containers[0] =& $obj->container; + if (is_string($datasrc)) { + if ($this->options['isFile']) { + $err = $this->setInputFile($datasrc); + if (PEAR::isError($err)) { + return $err; + } + $err = $this->parse(); + } else { + $err = $this->parseString($datasrc, true); + } + } else { + $this->setInput($datasrc); + $err = $this->parse(); + } + return $err; + } // end func parseDatasrc + + /** + * Handler for the xml-data + * + * @param mixed $xp ignored + * @param string $elem name of the element + * @param array $attribs attributes for the generated node + * + * @access private + */ + function startHandler($xp, $elem, &$attribs) + { + $container =& new Config_Container('section', $elem, null, $attribs); + $this->containers[] =& $container; + return null; + } // end func startHandler + + /** + * Handler for the xml-data + * + * @param mixed $xp ignored + * @param string $elem name of the element + * + * @access private + */ + function endHandler($xp, $elem) + { + $count = count($this->containers); + $container =& $this->containers[$count-1]; + $currentSection =& $this->containers[$count-2]; + if (count($container->children) == 0) { + $container->setType('directive'); + $container->setContent(trim($this->cdata)); + } + $currentSection->addItem($container); + array_pop($this->containers); + $this->cdata = null; + return null; + } // end func endHandler + + /* + * The xml character data handler + * + * @param mixed $xp ignored + * @param string $data PCDATA between tags + * + * @access private + */ + function cdataHandler($xp, $cdata) + { + $this->cdata .= $cdata; + } // end func cdataHandler + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $indent = ''; + if (!$obj->isRoot()) { + // no indent for root + $this->_deep++; + $indent = str_repeat($this->options['indent'], $this->_deep); + } else { + // Initialize string with xml declaration + $string = ''; + if ($this->options['addDecl']) { + $string .= XML_Util::getXMLDeclaration($this->options['version'], $this->options['encoding']); + $string .= $this->options['linebreak']; + } + if (!empty($this->options['name'])) { + $string .= '<'.$this->options['name'].'>'.$this->options['linebreak']; + $this->_deep++; + $indent = str_repeat($this->options['indent'], $this->_deep); + } + } + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'directive': + $attributes = ($this->options['useAttr']) ? $obj->attributes : array(); + $string .= $indent.XML_Util::createTag($obj->name, $attributes, $obj->content, null, + ($this->options['useCData'] ? XML_UTIL_CDATA_SECTION : XML_UTIL_REPLACE_ENTITIES)); + $string .= $this->options['linebreak']; + break; + case 'comment': + $string .= $indent.''; + $string .= $this->options['linebreak']; + break; + case 'section': + if (!$obj->isRoot()) { + $string = $indent.'<'.$obj->name; + $string .= ($this->options['useAttr']) ? XML_Util::attributesToString($obj->attributes) : ''; + } + if ($children = count($obj->children)) { + if (!$obj->isRoot()) { + $string .= '>'.$this->options['linebreak']; + } + for ($i = 0; $i < $children; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + if (!$obj->isRoot()) { + if ($children) { + $string .= $indent.'name.'>'.$this->options['linebreak']; + } else { + $string .= '/>'.$this->options['linebreak']; + } + } else { + if (!empty($this->options['name'])) { + $string .= 'options['name'].'>'.$this->options['linebreak']; + } + } + break; + default: + $string = ''; + } + if (!$obj->isRoot()) { + $this->_deep--; + } + return $string; + } // end func toString +} // end class Config_Container_XML +?> diff --git a/lib/Pear/Console/Getopt.php b/lib/Pear/Console/Getopt.php new file mode 100644 index 0000000..bb9d69c --- /dev/null +++ b/lib/Pear/Console/Getopt.php @@ -0,0 +1,290 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $ + +require_once 'PEAR.php'; + +/** + * Command-line options parsing class. + * + * @author Andrei Zmievski + * + */ +class Console_Getopt { + /** + * Parses the command-line options. + * + * The first parameter to this function should be the list of command-line + * arguments without the leading reference to the running program. + * + * The second parameter is a string of allowed short options. Each of the + * option letters can be followed by a colon ':' to specify that the option + * requires an argument, or a double colon '::' to specify that the option + * takes an optional argument. + * + * The third argument is an optional array of allowed long options. The + * leading '--' should not be included in the option name. Options that + * require an argument should be followed by '=', and options that take an + * option argument should be followed by '=='. + * + * The return value is an array of two elements: the list of parsed + * options and the list of non-option command-line arguments. Each entry in + * the list of parsed options is a pair of elements - the first one + * specifies the option, and the second one specifies the option argument, + * if there was one. + * + * Long and short options can be mixed. + * + * Most of the semantics of this function are based on GNU getopt_long(). + * + * @param array $args an array of command-line arguments + * @param string $short_options specifies the list of allowed short options + * @param array $long_options specifies the list of allowed long options + * + * @return array two-element array containing the list of parsed options and + * the non-option arguments + * + * @access public + * + */ + function getopt2($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); + } + + /** + * This function expects $args to start with the script name (POSIX-style). + * Preserved for backwards compatibility. + * @see getopt2() + */ + function getopt($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); + } + + /** + * The actual implementation of the argument parsing code. + */ + function doGetopt($version, $args, $short_options, $long_options = null) + { + // in case you pass directly readPHPArgv() as the first arg + if (PEAR::isError($args)) { + return $args; + } + if (empty($args)) { + return array(array(), array()); + } + $opts = array(); + $non_opts = array(); + + settype($args, 'array'); + + if ($long_options) { + sort($long_options); + } + + /* + * Preserve backwards compatibility with callers that relied on + * erroneous POSIX fix. + */ + if ($version < 2) { + if (isset($args[0]{0}) && $args[0]{0} != '-') { + array_shift($args); + } + } + + reset($args); + while (list($i, $arg) = each($args)) { + + /* The special element '--' means explicit end of + options. Treat the rest of the arguments as non-options + and end the loop. */ + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg{1} == '-') { + $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } elseif ($arg == '-') { + // - is stdin + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } else { + $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } + } + + return array($opts, $non_opts); + } + + /** + * @access private + * + */ + function _parseShortOption($arg, $short_options, &$opts, &$args) + { + for ($i = 0; $i < strlen($arg); $i++) { + $opt = $arg{$i}; + $opt_arg = null; + + /* Try to find the short option in the specifier string. */ + if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') + { + return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); + } + + if (strlen($spec) > 1 && $spec{1} == ':') { + if (strlen($spec) > 2 && $spec{2} == ':') { + if ($i + 1 < strlen($arg)) { + /* Option takes an optional argument. Use the remainder of + the arg string if there is anything left. */ + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + /* Option requires an argument. Use the remainder of the arg + string if there is anything left. */ + if ($i + 1 < strlen($arg)) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } else if (list(, $opt_arg) = each($args)) { + /* Else use the next argument. */; + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } else { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + /** + * @access private + * + */ + function _isShortOpt($arg) + { + return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]); + } + + /** + * @access private + * + */ + function _isLongOpt($arg) + { + return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && + preg_match('/[a-zA-Z]+$/', substr($arg, 2)); + } + + /** + * @access private + * + */ + function _parseLongOption($arg, $long_options, &$opts, &$args) + { + @list($opt, $opt_arg) = explode('=', $arg, 2); + $opt_len = strlen($opt); + + for ($i = 0; $i < count($long_options); $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + $long_opt_name = str_replace('=', '', $long_opt); + + /* Option doesn't match. Go on to the next one. */ + if ($long_opt_name != $opt) { + continue; + } + + $opt_rest = substr($long_opt, $opt_len); + + /* Check that the options uniquely matches one of the allowed + options. */ + if ($i + 1 < count($long_options)) { + $next_option_rest = substr($long_options[$i + 1], $opt_len); + } else { + $next_option_rest = ''; + } + if ($opt_rest != '' && $opt{0} != '=' && + $i + 1 < count($long_options) && + $opt == substr($long_options[$i+1], 0, $opt_len) && + $next_option_rest != '' && + $next_option_rest{0} != '=') { + return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + /* Long option requires an argument. + Take the next argument if one wasn't specified. */; + if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { + return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); + } + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument --$opt"); + } + } + } else if ($opt_arg) { + return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); + } + + $opts[] = array('--' . $opt, $opt_arg); + return; + } + + return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); + } + + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @access public + * @return mixed the $argv PHP array or PEAR error if not registered + */ + function readPHPArgv() + { + global $argv; + if (!is_array($argv)) { + if (!@is_array($_SERVER['argv'])) { + if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + +} + +?> diff --git a/lib/Pear/HTML/Common.php b/lib/Pear/HTML/Common.php new file mode 100644 index 0000000..feafb4d --- /dev/null +++ b/lib/Pear/HTML/Common.php @@ -0,0 +1,464 @@ + + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Common.php,v 1.14 2007/05/16 20:06:44 avb Exp $ + * @link http://pear.php.net/package/HTML_Common/ + */ + +/** + * Base class for all HTML classes + * + * @category HTML + * @package HTML_Common + * @author Adam Daniel + * @version Release: 1.2.4 + * @abstract + */ +class HTML_Common +{ + /** + * Associative array of attributes + * @var array + * @access private + */ + var $_attributes = array(); + + /** + * Tab offset of the tag + * @var int + * @access private + */ + var $_tabOffset = 0; + + /** + * Tab string + * @var string + * @since 1.7 + * @access private + */ + var $_tab = "\11"; + + /** + * Contains the line end string + * @var string + * @since 1.7 + * @access private + */ + var $_lineEnd = "\12"; + + /** + * HTML comment on the object + * @var string + * @since 1.5 + * @access private + */ + var $_comment = ''; + + /** + * Class constructor + * @param mixed $attributes Associative array of table tag attributes + * or HTML attributes name="value" pairs + * @param int $tabOffset Indent offset in tabs + * @access public + */ + function HTML_Common($attributes = null, $tabOffset = 0) + { + $this->setAttributes($attributes); + $this->setTabOffset($tabOffset); + } // end constructor + + /** + * Returns the current API version + * @access public + * @returns double + */ + function apiVersion() + { + return 1.7; + } // end func apiVersion + + /** + * Returns the lineEnd + * + * @since 1.7 + * @access private + * @return string + */ + function _getLineEnd() + { + return $this->_lineEnd; + } // end func getLineEnd + + /** + * Returns a string containing the unit for indenting HTML + * + * @since 1.7 + * @access private + * @return string + */ + function _getTab() + { + return $this->_tab; + } // end func _getTab + + /** + * Returns a string containing the offset for the whole HTML code + * + * @return string + * @access private + */ + function _getTabs() + { + return str_repeat($this->_getTab(), $this->_tabOffset); + } // end func _getTabs + + /** + * Returns an HTML formatted attribute string + * @param array $attributes + * @return string + * @access private + */ + function _getAttrString($attributes) + { + $strAttr = ''; + + if (is_array($attributes)) { + $charset = HTML_Common::charset(); + foreach ($attributes as $key => $value) { + $strAttr .= ' ' . $key . '="' . htmlspecialchars($value, ENT_COMPAT, $charset) . '"'; + } + } + return $strAttr; + } // end func _getAttrString + + /** + * Returns a valid atrributes array from either a string or array + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access private + * @return array + */ + function _parseAttributes($attributes) + { + if (is_array($attributes)) { + $ret = array(); + foreach ($attributes as $key => $value) { + if (is_int($key)) { + $key = $value = strtolower($value); + } else { + $key = strtolower($key); + } + $ret[$key] = $value; + } + return $ret; + + } elseif (is_string($attributes)) { + $preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" . + "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/"; + if (preg_match_all($preg, $attributes, $regs)) { + for ($counter=0; $counter $value) { + $attr1[$key] = $value; + } + } // end func _updateAtrrArray + + /** + * Removes the given attribute from the given array + * + * @param string $attr Attribute name + * @param array $attributes Attribute array + * @since 1.4 + * @access private + * @return void + */ + function _removeAttr($attr, &$attributes) + { + $attr = strtolower($attr); + if (isset($attributes[$attr])) { + unset($attributes[$attr]); + } + } //end func _removeAttr + + /** + * Returns the value of the given attribute + * + * @param string $attr Attribute name + * @since 1.5 + * @access public + * @return string|null returns null if an attribute does not exist + */ + function getAttribute($attr) + { + $attr = strtolower($attr); + if (isset($this->_attributes[$attr])) { + return $this->_attributes[$attr]; + } + return null; + } //end func getAttribute + + /** + * Sets the value of the attribute + * + * @param string Attribute name + * @param string Attribute value (will be set to $name if omitted) + * @access public + */ + function setAttribute($name, $value = null) + { + $name = strtolower($name); + if (is_null($value)) { + $value = $name; + } + $this->_attributes[$name] = $value; + } // end func setAttribute + + /** + * Sets the HTML attributes + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access public + */ + function setAttributes($attributes) + { + $this->_attributes = $this->_parseAttributes($attributes); + } // end func setAttributes + + /** + * Returns the assoc array (default) or string of attributes + * + * @param bool Whether to return the attributes as string + * @since 1.6 + * @access public + * @return mixed attributes + */ + function getAttributes($asString = false) + { + if ($asString) { + return $this->_getAttrString($this->_attributes); + } else { + return $this->_attributes; + } + } //end func getAttributes + + /** + * Updates the passed attributes without changing the other existing attributes + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access public + */ + function updateAttributes($attributes) + { + $this->_updateAttrArray($this->_attributes, $this->_parseAttributes($attributes)); + } // end func updateAttributes + + /** + * Removes an attribute + * + * @param string $attr Attribute name + * @since 1.4 + * @access public + * @return void + */ + function removeAttribute($attr) + { + $this->_removeAttr($attr, $this->_attributes); + } //end func removeAttribute + + /** + * Sets the line end style to Windows, Mac, Unix or a custom string. + * + * @param string $style "win", "mac", "unix" or custom string. + * @since 1.7 + * @access public + * @return void + */ + function setLineEnd($style) + { + switch ($style) { + case 'win': + $this->_lineEnd = "\15\12"; + break; + case 'unix': + $this->_lineEnd = "\12"; + break; + case 'mac': + $this->_lineEnd = "\15"; + break; + default: + $this->_lineEnd = $style; + } + } // end func setLineEnd + + /** + * Sets the tab offset + * + * @param int $offset + * @access public + */ + function setTabOffset($offset) + { + $this->_tabOffset = $offset; + } // end func setTabOffset + + /** + * Returns the tabOffset + * + * @since 1.5 + * @access public + * @return int + */ + function getTabOffset() + { + return $this->_tabOffset; + } //end func getTabOffset + + /** + * Sets the string used to indent HTML + * + * @since 1.7 + * @param string $string String used to indent ("\11", "\t", ' ', etc.). + * @access public + * @return void + */ + function setTab($string) + { + $this->_tab = $string; + } // end func setTab + + /** + * Sets the HTML comment to be displayed at the beginning of the HTML string + * + * @param string + * @since 1.4 + * @access public + * @return void + */ + function setComment($comment) + { + $this->_comment = $comment; + } // end func setHtmlComment + + /** + * Returns the HTML comment + * + * @since 1.5 + * @access public + * @return string + */ + function getComment() + { + return $this->_comment; + } //end func getComment + + /** + * Abstract method. Must be extended to return the objects HTML + * + * @access public + * @return string + * @abstract + */ + function toHtml() + { + return ''; + } // end func toHtml + + /** + * Displays the HTML to the screen + * + * @access public + */ + function display() + { + print $this->toHtml(); + } // end func display + + /** + * Sets the charset to use by htmlspecialchars() function + * + * Since this parameter is expected to be global, the function is designed + * to be called statically: + * + * HTML_Common::charset('utf-8'); + * + * or + * + * $charset = HTML_Common::charset(); + * + * + * @param string New charset to use. Omit if just getting the + * current value. Consult the htmlspecialchars() docs + * for a list of supported character sets. + * @return string Current charset + * @access public + * @static + */ + function charset($newCharset = null) + { + static $charset = 'ISO-8859-1'; + + if (!is_null($newCharset)) { + $charset = $newCharset; + } + return $charset; + } // end func charset +} // end class HTML_Common +?> diff --git a/lib/Pear/HTML/QuickForm.php b/lib/Pear/HTML/QuickForm.php new file mode 100644 index 0000000..b7dc531 --- /dev/null +++ b/lib/Pear/HTML/QuickForm.php @@ -0,0 +1,2059 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: QuickForm.php,v 1.164 2007/10/05 19:57:32 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * PEAR and PEAR_Error classes, for error handling + */ +require_once 'PEAR.php'; +/** + * Base class for all HTML classes + */ +require_once 'HTML/Common.php'; + +/** + * Element types known to HTML_QuickForm + * @see HTML_QuickForm::registerElementType(), HTML_QuickForm::getRegisteredTypes(), + * HTML_QuickForm::isTypeRegistered() + * @global array $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] + */ +$GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] = + array( + 'group' =>array('HTML/QuickForm/group.php','HTML_QuickForm_group'), + 'hidden' =>array('HTML/QuickForm/hidden.php','HTML_QuickForm_hidden'), + 'reset' =>array('HTML/QuickForm/reset.php','HTML_QuickForm_reset'), + 'checkbox' =>array('HTML/QuickForm/checkbox.php','HTML_QuickForm_checkbox'), + 'file' =>array('HTML/QuickForm/file.php','HTML_QuickForm_file'), + 'image' =>array('HTML/QuickForm/image.php','HTML_QuickForm_image'), + 'password' =>array('HTML/QuickForm/password.php','HTML_QuickForm_password'), + 'radio' =>array('HTML/QuickForm/radio.php','HTML_QuickForm_radio'), + 'button' =>array('HTML/QuickForm/button.php','HTML_QuickForm_button'), + 'submit' =>array('HTML/QuickForm/submit.php','HTML_QuickForm_submit'), + 'select' =>array('HTML/QuickForm/select.php','HTML_QuickForm_select'), + 'hiddenselect' =>array('HTML/QuickForm/hiddenselect.php','HTML_QuickForm_hiddenselect'), + 'text' =>array('HTML/QuickForm/text.php','HTML_QuickForm_text'), + 'textarea' =>array('HTML/QuickForm/textarea.php','HTML_QuickForm_textarea'), + 'link' =>array('HTML/QuickForm/link.php','HTML_QuickForm_link'), + 'advcheckbox' =>array('HTML/QuickForm/advcheckbox.php','HTML_QuickForm_advcheckbox'), + 'date' =>array('HTML/QuickForm/date.php','HTML_QuickForm_date'), + 'static' =>array('HTML/QuickForm/static.php','HTML_QuickForm_static'), + 'header' =>array('HTML/QuickForm/header.php', 'HTML_QuickForm_header'), + 'html' =>array('HTML/QuickForm/html.php', 'HTML_QuickForm_html'), + 'hierselect' =>array('HTML/QuickForm/hierselect.php', 'HTML_QuickForm_hierselect'), + 'autocomplete' =>array('HTML/QuickForm/autocomplete.php', 'HTML_QuickForm_autocomplete'), + 'xbutton' =>array('HTML/QuickForm/xbutton.php','HTML_QuickForm_xbutton') + ); + +/** + * Validation rules known to HTML_QuickForm + * @see HTML_QuickForm::registerRule(), HTML_QuickForm::getRegisteredRules(), + * HTML_QuickForm::isRuleRegistered() + * @global array $GLOBALS['_HTML_QuickForm_registered_rules'] + */ +$GLOBALS['_HTML_QuickForm_registered_rules'] = array( + 'required' => array('html_quickform_rule_required', 'HTML/QuickForm/Rule/Required.php'), + 'maxlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), + 'minlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), + 'rangelength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), + 'email' => array('html_quickform_rule_email', 'HTML/QuickForm/Rule/Email.php'), + 'regex' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'lettersonly' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'alphanumeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'numeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'nopunctuation' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'nonzero' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'callback' => array('html_quickform_rule_callback', 'HTML/QuickForm/Rule/Callback.php'), + 'compare' => array('html_quickform_rule_compare', 'HTML/QuickForm/Rule/Compare.php') +); + +// {{{ error codes + +/**#@+ + * Error codes for HTML_QuickForm + * + * Codes are mapped to textual messages by errorMessage() method, if you add a + * new code be sure to add a new message for it to errorMessage() + * + * @see HTML_QuickForm::errorMessage() + */ +define('QUICKFORM_OK', 1); +define('QUICKFORM_ERROR', -1); +define('QUICKFORM_INVALID_RULE', -2); +define('QUICKFORM_NONEXIST_ELEMENT', -3); +define('QUICKFORM_INVALID_FILTER', -4); +define('QUICKFORM_UNREGISTERED_ELEMENT', -5); +define('QUICKFORM_INVALID_ELEMENT_NAME', -6); +define('QUICKFORM_INVALID_PROCESS', -7); +define('QUICKFORM_DEPRECATED', -8); +define('QUICKFORM_INVALID_DATASOURCE', -9); +/**#@-*/ + +// }}} + +/** + * Create, validate and process HTML forms + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + */ +class HTML_QuickForm extends HTML_Common +{ + // {{{ properties + + /** + * Array containing the form fields + * @since 1.0 + * @var array + * @access private + */ + var $_elements = array(); + + /** + * Array containing element name to index map + * @since 1.1 + * @var array + * @access private + */ + var $_elementIndex = array(); + + /** + * Array containing indexes of duplicate elements + * @since 2.10 + * @var array + * @access private + */ + var $_duplicateIndex = array(); + + /** + * Array containing required field IDs + * @since 1.0 + * @var array + * @access private + */ + var $_required = array(); + + /** + * Prefix message in javascript alert if error + * @since 1.0 + * @var string + * @access public + */ + var $_jsPrefix = ''; + + /** + * Postfix message in javascript alert if error + * @since 1.0 + * @var string + * @access public + */ + var $_jsPostfix = ''; + + /** + * Datasource object implementing the informal + * datasource protocol + * @since 3.3 + * @var object + * @access private + */ + var $_datasource; + + /** + * Array of default form values + * @since 2.0 + * @var array + * @access private + */ + var $_defaultValues = array(); + + /** + * Array of constant form values + * @since 2.0 + * @var array + * @access private + */ + var $_constantValues = array(); + + /** + * Array of submitted form values + * @since 1.0 + * @var array + * @access private + */ + var $_submitValues = array(); + + /** + * Array of submitted form files + * @since 1.0 + * @var integer + * @access public + */ + var $_submitFiles = array(); + + /** + * Value for maxfilesize hidden element if form contains file input + * @since 1.0 + * @var integer + * @access public + */ + var $_maxFileSize = 1048576; // 1 Mb = 1048576 + + /** + * Flag to know if all fields are frozen + * @since 1.0 + * @var boolean + * @access private + */ + var $_freezeAll = false; + + /** + * Array containing the form rules + * @since 1.0 + * @var array + * @access private + */ + var $_rules = array(); + + /** + * Form rules, global variety + * @var array + * @access private + */ + var $_formRules = array(); + + /** + * Array containing the validation errors + * @since 1.0 + * @var array + * @access private + */ + var $_errors = array(); + + /** + * Note for required fields in the form + * @var string + * @since 1.0 + * @access private + */ + var $_requiredNote = '* denotes required field'; + + /** + * Whether the form was submitted + * @var boolean + * @access private + */ + var $_flagSubmitted = false; + + // }}} + // {{{ constructor + + /** + * Class constructor + * @param string $formName Form's name. + * @param string $method (optional)Form's method defaults to 'POST' + * @param string $action (optional)Form's action + * @param string $target (optional)Form's target defaults to '_self' + * @param mixed $attributes (optional)Extra attributes for
tag + * @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field + * @access public + */ + function HTML_QuickForm($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit = false) + { + HTML_Common::HTML_Common($attributes); + $method = (strtoupper($method) == 'GET') ? 'get' : 'post'; + $action = ($action == '') ? $_SERVER['PHP_SELF'] : $action; + $target = empty($target) ? array() : array('target' => $target); + $attributes = array('action'=>$action, 'method'=>$method, 'name'=>$formName, 'id'=>$formName) + $target; + $this->updateAttributes($attributes); + if (!$trackSubmit || isset($_REQUEST['_qf__' . $formName])) { + if (1 == get_magic_quotes_gpc()) { + $this->_submitValues = $this->_recursiveFilter('stripslashes', 'get' == $method? $_GET: $_POST); + foreach ($_FILES as $keyFirst => $valFirst) { + foreach ($valFirst as $keySecond => $valSecond) { + if ('name' == $keySecond) { + $this->_submitFiles[$keyFirst][$keySecond] = $this->_recursiveFilter('stripslashes', $valSecond); + } else { + $this->_submitFiles[$keyFirst][$keySecond] = $valSecond; + } + } + } + } else { + $this->_submitValues = 'get' == $method? $_GET: $_POST; + $this->_submitFiles = $_FILES; + } + $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0; + } + if ($trackSubmit) { + unset($this->_submitValues['_qf__' . $formName]); + $this->addElement('hidden', '_qf__' . $formName, null); + } + if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', ini_get('upload_max_filesize'), $matches)) { + // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes + switch (strtoupper($matches['2'])) { + case 'G': + $this->_maxFileSize = $matches['1'] * 1073741824; + break; + case 'M': + $this->_maxFileSize = $matches['1'] * 1048576; + break; + case 'K': + $this->_maxFileSize = $matches['1'] * 1024; + break; + default: + $this->_maxFileSize = $matches['1']; + } + } + } // end constructor + + // }}} + // {{{ apiVersion() + + /** + * Returns the current API version + * + * @since 1.0 + * @access public + * @return float + */ + function apiVersion() + { + return 3.2; + } // end func apiVersion + + // }}} + // {{{ registerElementType() + + /** + * Registers a new element type + * + * @param string $typeName Name of element type + * @param string $include Include path for element type + * @param string $className Element class name + * @since 1.0 + * @access public + * @return void + */ + function registerElementType($typeName, $include, $className) + { + $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className); + } // end func registerElementType + + // }}} + // {{{ registerRule() + + /** + * Registers a new validation rule + * + * @param string $ruleName Name of validation rule + * @param string $type Either: 'regex', 'function' or 'rule' for an HTML_QuickForm_Rule object + * @param string $data1 Name of function, regular expression or HTML_QuickForm_Rule classname + * @param string $data2 Object parent of above function or HTML_QuickForm_Rule file path + * @since 1.0 + * @access public + * @return void + */ + function registerRule($ruleName, $type, $data1, $data2 = null) + { + include_once('HTML/QuickForm/RuleRegistry.php'); + $registry =& HTML_QuickForm_RuleRegistry::singleton(); + $registry->registerRule($ruleName, $type, $data1, $data2); + } // end func registerRule + + // }}} + // {{{ elementExists() + + /** + * Returns true if element is in the form + * + * @param string $element form name of element to check + * @since 1.0 + * @access public + * @return boolean + */ + function elementExists($element=null) + { + return isset($this->_elementIndex[$element]); + } // end func elementExists + + // }}} + // {{{ setDatasource() + + /** + * Sets a datasource object for this form object + * + * Datasource default and constant values will feed the QuickForm object if + * the datasource implements defaultValues() and constantValues() methods. + * + * @param object $datasource datasource object implementing the informal datasource protocol + * @param mixed $defaultsFilter string or array of filter(s) to apply to default values + * @param mixed $constantsFilter string or array of filter(s) to apply to constants values + * @since 3.3 + * @access public + * @return void + * @throws HTML_QuickForm_Error + */ + function setDatasource(&$datasource, $defaultsFilter = null, $constantsFilter = null) + { + if (is_object($datasource)) { + $this->_datasource =& $datasource; + if (is_callable(array($datasource, 'defaultValues'))) { + $this->setDefaults($datasource->defaultValues($this), $defaultsFilter); + } + if (is_callable(array($datasource, 'constantValues'))) { + $this->setConstants($datasource->constantValues($this), $constantsFilter); + } + } else { + return PEAR::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true); + } + } // end func setDatasource + + // }}} + // {{{ setDefaults() + + /** + * Initializes default form values + * + * @param array $defaultValues values used to fill the form + * @param mixed $filter (optional) filter(s) to apply to all default values + * @since 1.0 + * @access public + * @return void + * @throws HTML_QuickForm_Error + */ + function setDefaults($defaultValues = null, $filter = null) + { + if (is_array($defaultValues)) { + if (isset($filter)) { + if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) { + foreach ($filter as $val) { + if (!is_callable($val)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true); + } else { + $defaultValues = $this->_recursiveFilter($val, $defaultValues); + } + } + } elseif (!is_callable($filter)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true); + } else { + $defaultValues = $this->_recursiveFilter($filter, $defaultValues); + } + } + $this->_defaultValues = HTML_QuickForm::arrayMerge($this->_defaultValues, $defaultValues); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); + } + } + } // end func setDefaults + + // }}} + // {{{ setConstants() + + /** + * Initializes constant form values. + * These values won't get overridden by POST or GET vars + * + * @param array $constantValues values used to fill the form + * @param mixed $filter (optional) filter(s) to apply to all default values + * + * @since 2.0 + * @access public + * @return void + * @throws HTML_QuickForm_Error + */ + function setConstants($constantValues = null, $filter = null) + { + if (is_array($constantValues)) { + if (isset($filter)) { + if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) { + foreach ($filter as $val) { + if (!is_callable($val)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true); + } else { + $constantValues = $this->_recursiveFilter($val, $constantValues); + } + } + } elseif (!is_callable($filter)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true); + } else { + $constantValues = $this->_recursiveFilter($filter, $constantValues); + } + } + $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, $constantValues); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); + } + } + } // end func setConstants + + // }}} + // {{{ setMaxFileSize() + + /** + * Sets the value of MAX_FILE_SIZE hidden element + * + * @param int $bytes Size in bytes + * @since 3.0 + * @access public + * @return void + */ + function setMaxFileSize($bytes = 0) + { + if ($bytes > 0) { + $this->_maxFileSize = $bytes; + } + if (!$this->elementExists('MAX_FILE_SIZE')) { + $this->addElement('hidden', 'MAX_FILE_SIZE', $this->_maxFileSize); + } else { + $el =& $this->getElement('MAX_FILE_SIZE'); + $el->updateAttributes(array('value' => $this->_maxFileSize)); + } + } // end func setMaxFileSize + + // }}} + // {{{ getMaxFileSize() + + /** + * Returns the value of MAX_FILE_SIZE hidden element + * + * @since 3.0 + * @access public + * @return int max file size in bytes + */ + function getMaxFileSize() + { + return $this->_maxFileSize; + } // end func getMaxFileSize + + // }}} + // {{{ &createElement() + + /** + * Creates a new form element of the given type. + * + * This method accepts variable number of parameters, their + * meaning and count depending on $elementType + * + * @param string $elementType type of element to add (text, textarea, file...) + * @since 1.0 + * @access public + * @return HTML_QuickForm_Element + * @throws HTML_QuickForm_Error + */ + function &createElement($elementType) + { + $args = func_get_args(); + $element =& HTML_QuickForm::_loadElement('createElement', $elementType, array_slice($args, 1)); + return $element; + } // end func createElement + + // }}} + // {{{ _loadElement() + + /** + * Returns a form element of the given type + * + * @param string $event event to send to newly created element ('createElement' or 'addElement') + * @param string $type element type + * @param array $args arguments for event + * @since 2.0 + * @access private + * @return HTML_QuickForm_Element + * @throws HTML_QuickForm_Error + */ + function &_loadElement($event, $type, $args) + { + $type = strtolower($type); + if (!HTML_QuickForm::isTypeRegistered($type)) { + $error = PEAR::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$type' does not exist in HTML_QuickForm::_loadElement()", 'HTML_QuickForm_Error', true); + return $error; + } + $className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1]; + $includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0]; + include_once($includeFile); + $elementObject =& new $className(); + for ($i = 0; $i < 5; $i++) { + if (!isset($args[$i])) { + $args[$i] = null; + } + } + $err = $elementObject->onQuickFormEvent($event, $args, $this); + if ($err !== true) { + return $err; + } + return $elementObject; + } // end func _loadElement + + // }}} + // {{{ addElement() + + /** + * Adds an element into the form + * + * If $element is a string representing element type, then this + * method accepts variable number of parameters, their meaning + * and count depending on $element + * + * @param mixed $element element object or type of element to add (text, textarea, file...) + * @since 1.0 + * @return HTML_QuickForm_Element a reference to newly added element + * @access public + * @throws HTML_QuickForm_Error + */ + function &addElement($element) + { + if (is_object($element) && is_subclass_of($element, 'html_quickform_element')) { + $elementObject = &$element; + $elementObject->onQuickFormEvent('updateValue', null, $this); + } else { + $args = func_get_args(); + $elementObject =& $this->_loadElement('addElement', $element, array_slice($args, 1)); + if (PEAR::isError($elementObject)) { + return $elementObject; + } + } + $elementName = $elementObject->getName(); + + // Add the element if it is not an incompatible duplicate + if (!empty($elementName) && isset($this->_elementIndex[$elementName])) { + if ($this->_elements[$this->_elementIndex[$elementName]]->getType() == + $elementObject->getType()) { + $this->_elements[] =& $elementObject; + $elKeys = array_keys($this->_elements); + $this->_duplicateIndex[$elementName][] = end($elKeys); + } else { + $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::addElement()", 'HTML_QuickForm_Error', true); + return $error; + } + } else { + $this->_elements[] =& $elementObject; + $elKeys = array_keys($this->_elements); + $this->_elementIndex[$elementName] = end($elKeys); + } + if ($this->_freezeAll) { + $elementObject->freeze(); + } + + return $elementObject; + } // end func addElement + + // }}} + // {{{ insertElementBefore() + + /** + * Inserts a new element right before the other element + * + * Warning: it is not possible to check whether the $element is already + * added to the form, therefore if you want to move the existing form + * element to a new position, you'll have to use removeElement(): + * $form->insertElementBefore($form->removeElement('foo', false), 'bar'); + * + * @access public + * @since 3.2.4 + * @param HTML_QuickForm_element Element to insert + * @param string Name of the element before which the new + * one is inserted + * @return HTML_QuickForm_element reference to inserted element + * @throws HTML_QuickForm_Error + */ + function &insertElementBefore(&$element, $nameAfter) + { + if (!empty($this->_duplicateIndex[$nameAfter])) { + $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, 'Several elements named "' . $nameAfter . '" exist in HTML_QuickForm::insertElementBefore().', 'HTML_QuickForm_Error', true); + return $error; + } elseif (!$this->elementExists($nameAfter)) { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true); + return $error; + } + $elementName = $element->getName(); + $targetIdx = $this->_elementIndex[$nameAfter]; + $duplicate = false; + // Like in addElement(), check that it's not an incompatible duplicate + if (!empty($elementName) && isset($this->_elementIndex[$elementName])) { + if ($this->_elements[$this->_elementIndex[$elementName]]->getType() != $element->getType()) { + $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true); + return $error; + } + $duplicate = true; + } + // Move all the elements after added back one place, reindex _elementIndex and/or _duplicateIndex + $elKeys = array_keys($this->_elements); + for ($i = end($elKeys); $i >= $targetIdx; $i--) { + if (isset($this->_elements[$i])) { + $currentName = $this->_elements[$i]->getName(); + $this->_elements[$i + 1] =& $this->_elements[$i]; + if ($this->_elementIndex[$currentName] == $i) { + $this->_elementIndex[$currentName] = $i + 1; + } else { + $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]); + $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1; + } + unset($this->_elements[$i]); + } + } + // Put the element in place finally + $this->_elements[$targetIdx] =& $element; + if (!$duplicate) { + $this->_elementIndex[$elementName] = $targetIdx; + } else { + $this->_duplicateIndex[$elementName][] = $targetIdx; + } + $element->onQuickFormEvent('updateValue', null, $this); + if ($this->_freezeAll) { + $element->freeze(); + } + // If not done, the elements will appear in reverse order + ksort($this->_elements); + return $element; + } + + // }}} + // {{{ addGroup() + + /** + * Adds an element group + * @param array $elements array of elements composing the group + * @param string $name (optional)group name + * @param string $groupLabel (optional)group label + * @param string $separator (optional)string to separate elements + * @param string $appendName (optional)specify whether the group name should be + * used in the form element name ex: group[element] + * @return HTML_QuickForm_group reference to a newly added group + * @since 2.8 + * @access public + * @throws HTML_QuickForm_Error + */ + function &addGroup($elements, $name=null, $groupLabel='', $separator=null, $appendName = true) + { + static $anonGroups = 1; + + if (0 == strlen($name)) { + $name = 'qf_group_' . $anonGroups++; + $appendName = false; + } + $group =& $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName); + return $group; + } // end func addGroup + + // }}} + // {{{ &getElement() + + /** + * Returns a reference to the element + * + * @param string $element Element name + * @since 2.0 + * @access public + * @return HTML_QuickForm_element reference to element + * @throws HTML_QuickForm_Error + */ + function &getElement($element) + { + if (isset($this->_elementIndex[$element])) { + return $this->_elements[$this->_elementIndex[$element]]; + } else { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElement()", 'HTML_QuickForm_Error', true); + return $error; + } + } // end func getElement + + // }}} + // {{{ &getElementValue() + + /** + * Returns the element's raw value + * + * This returns the value as submitted by the form (not filtered) + * or set via setDefaults() or setConstants() + * + * @param string $element Element name + * @since 2.0 + * @access public + * @return mixed element value + * @throws HTML_QuickForm_Error + */ + function &getElementValue($element) + { + if (!isset($this->_elementIndex[$element])) { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true); + return $error; + } + $value = $this->_elements[$this->_elementIndex[$element]]->getValue(); + if (isset($this->_duplicateIndex[$element])) { + foreach ($this->_duplicateIndex[$element] as $index) { + if (null !== ($v = $this->_elements[$index]->getValue())) { + if (is_array($value)) { + $value[] = $v; + } else { + $value = (null === $value)? $v: array($value, $v); + } + } + } + } + return $value; + } // end func getElementValue + + // }}} + // {{{ getSubmitValue() + + /** + * Returns the elements value after submit and filter + * + * @param string Element name + * @since 2.0 + * @access public + * @return mixed submitted element value or null if not set + */ + function getSubmitValue($elementName) + { + $value = null; + if (isset($this->_submitValues[$elementName]) || isset($this->_submitFiles[$elementName])) { + $value = isset($this->_submitValues[$elementName])? $this->_submitValues[$elementName]: array(); + if (is_array($value) && isset($this->_submitFiles[$elementName])) { + foreach ($this->_submitFiles[$elementName] as $k => $v) { + $value = HTML_QuickForm::arrayMerge($value, $this->_reindexFiles($this->_submitFiles[$elementName][$k], $k)); + } + } + + } elseif ('file' == $this->getElementType($elementName)) { + return $this->getElementValue($elementName); + + } elseif (false !== ($pos = strpos($elementName, '['))) { + $base = str_replace( + array('\\', '\''), array('\\\\', '\\\''), + substr($elementName, 0, $pos) + ); + $idx = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + substr($elementName, $pos + 1, -1) + ) . "']"; + if (isset($this->_submitValues[$base])) { + $value = eval("return (isset(\$this->_submitValues['{$base}']{$idx})) ? \$this->_submitValues['{$base}']{$idx} : null;"); + } + + if ((is_array($value) || null === $value) && isset($this->_submitFiles[$base])) { + $props = array('name', 'type', 'size', 'tmp_name', 'error'); + $code = "if (!isset(\$this->_submitFiles['{$base}']['name']{$idx})) {\n" . + " return null;\n" . + "} else {\n" . + " \$v = array();\n"; + foreach ($props as $prop) { + $code .= " \$v = HTML_QuickForm::arrayMerge(\$v, \$this->_reindexFiles(\$this->_submitFiles['{$base}']['{$prop}']{$idx}, '{$prop}'));\n"; + } + $fileValue = eval($code . " return \$v;\n}\n"); + if (null !== $fileValue) { + $value = null === $value? $fileValue: HTML_QuickForm::arrayMerge($value, $fileValue); + } + } + } + + // This is only supposed to work for groups with appendName = false + if (null === $value && 'group' == $this->getElementType($elementName)) { + $group =& $this->getElement($elementName); + $elements =& $group->getElements(); + foreach (array_keys($elements) as $key) { + $name = $group->getElementName($key); + // prevent endless recursion in case of radios and such + if ($name != $elementName) { + if (null !== ($v = $this->getSubmitValue($name))) { + $value[$name] = $v; + } + } + } + } + return $value; + } // end func getSubmitValue + + // }}} + // {{{ _reindexFiles() + + /** + * A helper function to change the indexes in $_FILES array + * + * @param mixed Some value from the $_FILES array + * @param string The key from the $_FILES array that should be appended + * @return array + */ + function _reindexFiles($value, $key) + { + if (!is_array($value)) { + return array($key => $value); + } else { + $ret = array(); + foreach ($value as $k => $v) { + $ret[$k] = $this->_reindexFiles($v, $key); + } + return $ret; + } + } + + // }}} + // {{{ getElementError() + + /** + * Returns error corresponding to validated element + * + * @param string $element Name of form element to check + * @since 1.0 + * @access public + * @return string error message corresponding to checked element + */ + function getElementError($element) + { + if (isset($this->_errors[$element])) { + return $this->_errors[$element]; + } + } // end func getElementError + + // }}} + // {{{ setElementError() + + /** + * Set error message for a form element + * + * @param string $element Name of form element to set error for + * @param string $message Error message, if empty then removes the current error message + * @since 1.0 + * @access public + * @return void + */ + function setElementError($element, $message = null) + { + if (!empty($message)) { + $this->_errors[$element] = $message; + } else { + unset($this->_errors[$element]); + } + } // end func setElementError + + // }}} + // {{{ getElementType() + + /** + * Returns the type of the given element + * + * @param string $element Name of form element + * @since 1.1 + * @access public + * @return string Type of the element, false if the element is not found + */ + function getElementType($element) + { + if (isset($this->_elementIndex[$element])) { + return $this->_elements[$this->_elementIndex[$element]]->getType(); + } + return false; + } // end func getElementType + + // }}} + // {{{ updateElementAttr() + + /** + * Updates Attributes for one or more elements + * + * @param mixed $elements Array of element names/objects or string of elements to be updated + * @param mixed $attrs Array or sting of html attributes + * @since 2.10 + * @access public + * @return void + */ + function updateElementAttr($elements, $attrs) + { + if (is_string($elements)) { + $elements = split('[ ]?,[ ]?', $elements); + } + foreach (array_keys($elements) as $key) { + if (is_object($elements[$key]) && is_a($elements[$key], 'HTML_QuickForm_element')) { + $elements[$key]->updateAttributes($attrs); + } elseif (isset($this->_elementIndex[$elements[$key]])) { + $this->_elements[$this->_elementIndex[$elements[$key]]]->updateAttributes($attrs); + if (isset($this->_duplicateIndex[$elements[$key]])) { + foreach ($this->_duplicateIndex[$elements[$key]] as $index) { + $this->_elements[$index]->updateAttributes($attrs); + } + } + } + } + } // end func updateElementAttr + + // }}} + // {{{ removeElement() + + /** + * Removes an element + * + * The method "unlinks" an element from the form, returning the reference + * to the element object. If several elements named $elementName exist, + * it removes the first one, leaving the others intact. + * + * @param string $elementName The element name + * @param boolean $removeRules True if rules for this element are to be removed too + * @access public + * @since 2.0 + * @return HTML_QuickForm_element a reference to the removed element + * @throws HTML_QuickForm_Error + */ + function &removeElement($elementName, $removeRules = true) + { + if (!isset($this->_elementIndex[$elementName])) { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$elementName' does not exist in HTML_QuickForm::removeElement()", 'HTML_QuickForm_Error', true); + return $error; + } + $el =& $this->_elements[$this->_elementIndex[$elementName]]; + unset($this->_elements[$this->_elementIndex[$elementName]]); + if (empty($this->_duplicateIndex[$elementName])) { + unset($this->_elementIndex[$elementName]); + } else { + $this->_elementIndex[$elementName] = array_shift($this->_duplicateIndex[$elementName]); + } + if ($removeRules) { + unset($this->_rules[$elementName], $this->_errors[$elementName]); + } + return $el; + } // end func removeElement + + // }}} + // {{{ addRule() + + /** + * Adds a validation rule for the given field + * + * If the element is in fact a group, it will be considered as a whole. + * To validate grouped elements as separated entities, + * use addGroupRule instead of addRule. + * + * @param string $element Form element name + * @param string $message Message to display for invalid data + * @param string $type Rule type, use getRegisteredRules() to get types + * @param string $format (optional)Required for extra rule data + * @param string $validation (optional)Where to perform validation: "server", "client" + * @param boolean $reset Client-side validation: reset the form element to its original value if there is an error? + * @param boolean $force Force the rule to be applied, even if the target form element does not exist + * @since 1.0 + * @access public + * @throws HTML_QuickForm_Error + */ + function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false) + { + if (!$force) { + if (!is_array($element) && !$this->elementExists($element)) { + return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); + } elseif (is_array($element)) { + foreach ($element as $el) { + if (!$this->elementExists($el)) { + return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$el' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); + } + } + } + } + if (false === ($newName = $this->isRuleRegistered($type, true))) { + return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); + } elseif (is_string($newName)) { + $type = $newName; + } + if (is_array($element)) { + $dependent = $element; + $element = array_shift($dependent); + } else { + $dependent = null; + } + if ($type == 'required' || $type == 'uploadedfile') { + $this->_required[] = $element; + } + if (!isset($this->_rules[$element])) { + $this->_rules[$element] = array(); + } + if ($validation == 'client') { + $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);')); + } + $this->_rules[$element][] = array( + 'type' => $type, + 'format' => $format, + 'message' => $message, + 'validation' => $validation, + 'reset' => $reset, + 'dependent' => $dependent + ); + } // end func addRule + + // }}} + // {{{ addGroupRule() + + /** + * Adds a validation rule for the given group of elements + * + * Only groups with a name can be assigned a validation rule + * Use addGroupRule when you need to validate elements inside the group. + * Use addRule if you need to validate the group as a whole. In this case, + * the same rule will be applied to all elements in the group. + * Use addRule if you need to validate the group against a function. + * + * @param string $group Form group name + * @param mixed $arg1 Array for multiple elements or error message string for one element + * @param string $type (optional)Rule type use getRegisteredRules() to get types + * @param string $format (optional)Required for extra rule data + * @param int $howmany (optional)How many valid elements should be in the group + * @param string $validation (optional)Where to perform validation: "server", "client" + * @param bool $reset Client-side: whether to reset the element's value to its original state if validation failed. + * @since 2.5 + * @access public + * @throws HTML_QuickForm_Error + */ + function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false) + { + if (!$this->elementExists($group)) { + return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Group '$group' does not exist in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); + } + + $groupObj =& $this->getElement($group); + if (is_array($arg1)) { + $required = 0; + foreach ($arg1 as $elementIndex => $rules) { + $elementName = $groupObj->getElementName($elementIndex); + foreach ($rules as $rule) { + $format = (isset($rule[2])) ? $rule[2] : null; + $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server'; + $reset = isset($rule[4]) && $rule[4]; + $type = $rule[1]; + if (false === ($newName = $this->isRuleRegistered($type, true))) { + return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); + } elseif (is_string($newName)) { + $type = $newName; + } + + $this->_rules[$elementName][] = array( + 'type' => $type, + 'format' => $format, + 'message' => $rule[0], + 'validation' => $validation, + 'reset' => $reset, + 'group' => $group); + + if ('required' == $type || 'uploadedfile' == $type) { + $groupObj->_required[] = $elementName; + $this->_required[] = $elementName; + $required++; + } + if ('client' == $validation) { + $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);')); + } + } + } + if ($required > 0 && count($groupObj->getElements()) == $required) { + $this->_required[] = $group; + } + } elseif (is_string($arg1)) { + if (false === ($newName = $this->isRuleRegistered($type, true))) { + return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); + } elseif (is_string($newName)) { + $type = $newName; + } + + // addGroupRule() should also handle form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for an elements + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_button extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $value (optional)Input field value + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_button($elementName=null, $value=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->_persistantFreeze = false; + $this->setValue($value); + $this->setType('button'); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + +} //end class HTML_QuickForm_button +?> diff --git a/lib/Pear/HTML/QuickForm/checkbox.php b/lib/Pear/HTML/QuickForm/checkbox.php new file mode 100644 index 0000000..7507289 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/checkbox.php @@ -0,0 +1,277 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: checkbox.php,v 1.22 2007/06/03 15:25:28 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a checkbox type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_checkbox extends HTML_QuickForm_input +{ + // {{{ properties + + /** + * Checkbox display text + * @var string + * @since 1.1 + * @access private + */ + var $_text = ''; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field value + * @param string $text (optional)Checkbox display text + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_checkbox($elementName=null, $elementLabel=null, $text='', $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_text = $text; + $this->setType('checkbox'); + $this->updateAttributes(array('value'=>1)); + $this->_generateId(); + } //end constructor + + // }}} + // {{{ setChecked() + + /** + * Sets whether a checkbox is checked + * + * @param bool $checked Whether the field is checked or not + * @since 1.0 + * @access public + * @return void + */ + function setChecked($checked) + { + if (!$checked) { + $this->removeAttribute('checked'); + } else { + $this->updateAttributes(array('checked'=>'checked')); + } + } //end func setChecked + + // }}} + // {{{ getChecked() + + /** + * Returns whether a checkbox is checked + * + * @since 1.0 + * @access public + * @return bool + */ + function getChecked() + { + return (bool)$this->getAttribute('checked'); + } //end func getChecked + + // }}} + // {{{ toHtml() + + /** + * Returns the checkbox element in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if (0 == strlen($this->_text)) { + $label = ''; + } elseif ($this->_flagFrozen) { + $label = $this->_text; + } else { + $label = ''; + } + return HTML_QuickForm_input::toHtml() . $label; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + if ($this->getChecked()) { + return '[x]' . + $this->_getPersistantData(); + } else { + return '[ ]'; + } + } //end func getFrozenHtml + + // }}} + // {{{ setText() + + /** + * Sets the checkbox text + * + * @param string $text + * @since 1.1 + * @access public + * @return void + */ + function setText($text) + { + $this->_text = $text; + } //end func setText + + // }}} + // {{{ getText() + + /** + * Returns the checkbox text + * + * @since 1.1 + * @access public + * @return string + */ + function getText() + { + return $this->_text; + } //end func getText + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param string $value Default value of the form element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + return $this->setChecked($value); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return bool + */ + function getValue() + { + return $this->getChecked(); + } // end func getValue + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + // constant values override both default and submitted ones + // default values are overriden by submitted + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + // if no boxes were checked, then there is no value in the array + // yet we don't want to display default value in this case + if ($caller->isSubmitted()) { + $value = $this->_findValue($caller->_submitValues); + } else { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value || $caller->isSubmitted()) { + $this->setChecked($value); + } + break; + case 'setGroupValue': + $this->setChecked($arg); + break; + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ exportValue() + + /** + * Return true if the checkbox is checked, null if it is not checked (getValue() returns false) + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (null === $value) { + $value = $this->getChecked()? true: null; + } + return $this->_prepareValue($value, $assoc); + } + + // }}} +} //end class HTML_QuickForm_checkbox +?> diff --git a/lib/Pear/HTML/QuickForm/date.php b/lib/Pear/HTML/QuickForm/date.php new file mode 100644 index 0000000..b1382a0 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/date.php @@ -0,0 +1,528 @@ + + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: date.php,v 1.61 2007/10/05 10:58:54 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Class for a group of form elements + */ +require_once 'HTML/QuickForm/group.php'; +/** + * Class for elements + */ +require_once 'HTML/QuickForm/select.php'; + +/** + * Class for a group of elements used to input dates (and times). + * + * Inspired by original 'date' element but reimplemented as a subclass + * of HTML_QuickForm_group + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 3.1 + */ +class HTML_QuickForm_date extends HTML_QuickForm_group +{ + // {{{ properties + + /** + * Various options to control the element's display. + * + * @access private + * @var array + */ + var $_options = array( + 'language' => 'en', + 'format' => 'dMY', + 'minYear' => 2001, + 'maxYear' => 2010, + 'addEmptyOption' => false, + 'emptyOptionValue' => '', + 'emptyOptionText' => ' ', + 'optionIncrement' => array('i' => 1, 's' => 1) + ); + + /** + * These complement separators, they are appended to the resultant HTML + * @access private + * @var array + */ + var $_wrap = array('', ''); + + /** + * Options in different languages + * + * Note to potential translators: to avoid encoding problems please send + * your translations with "weird" letters encoded as HTML Unicode entities + * + * @access private + * @var array + */ + var $_locale = array( + 'en' => array ( + 'weekdays_short'=> array ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'), + 'weekdays_long' => array ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), + 'months_long' => array ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') + ), + 'de' => array ( + 'weekdays_short'=> array ('So', 'Mon', 'Di', 'Mi', 'Do', 'Fr', 'Sa'), + 'weekdays_long' => array ('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'), + 'months_short' => array ('Jan', 'Feb', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dez'), + 'months_long' => array ('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember') + ), + 'fr' => array ( + 'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'), + 'weekdays_long' => array ('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'), + 'months_short' => array ('Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc'), + 'months_long' => array ('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre') + ), + 'hu' => array ( + 'weekdays_short'=> array ('V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'), + 'weekdays_long' => array ('vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'), + 'months_short' => array ('jan', 'feb', 'márc', 'ápr', 'máj', 'jún', 'júl', 'aug', 'szept', 'okt', 'nov', 'dec'), + 'months_long' => array ('január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december') + ), + 'pl' => array ( + 'weekdays_short'=> array ('Nie', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'Sob'), + 'weekdays_long' => array ('Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'), + 'months_short' => array ('Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'), + 'months_long' => array ('Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień') + ), + 'sl' => array ( + 'weekdays_short'=> array ('Ned', 'Pon', 'Tor', 'Sre', 'Cet', 'Pet', 'Sob'), + 'weekdays_long' => array ('Nedelja', 'Ponedeljek', 'Torek', 'Sreda', 'Cetrtek', 'Petek', 'Sobota'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij', 'Avgust', 'September', 'Oktober', 'November', 'December') + ), + 'ru' => array ( + 'weekdays_short'=> array ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'), + 'weekdays_long' => array ('Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'), + 'months_short' => array ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'), + 'months_long' => array ('Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь') + ), + 'es' => array ( + 'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'), + 'weekdays_long' => array ('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'), + 'months_short' => array ('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'), + 'months_long' => array ('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre') + ), + 'da' => array ( + 'weekdays_short'=> array ('Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'), + 'weekdays_long' => array ('Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December') + ), + 'is' => array ( + 'weekdays_short'=> array ('Sun', 'Mán', 'Þri', 'Mið', 'Fim', 'Fös', 'Lau'), + 'weekdays_long' => array ('Sunnudagur', 'Mánudagur', 'Þriðjudagur', 'Miðvikudagur', 'Fimmtudagur', 'Föstudagur', 'Laugardagur'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maí', 'Jún', 'Júl', 'Ágú', 'Sep', 'Okt', 'Nóv', 'Des'), + 'months_long' => array ('Janúar', 'Febrúar', 'Mars', 'Apríl', 'Maí', 'Júní', 'Júlí', 'Ágúst', 'September', 'Október', 'Nóvember', 'Desember') + ), + 'it' => array ( + 'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'), + 'weekdays_long' => array ('Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'), + 'months_short' => array ('Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'), + 'months_long' => array ('Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre') + ), + 'sk' => array ( + 'weekdays_short'=> array ('Ned', 'Pon', 'Uto', 'Str', 'Štv', 'Pia', 'Sob'), + 'weekdays_long' => array ('Nedeža', 'Pondelok', 'Utorok', 'Streda', 'Štvrtok', 'Piatok', 'Sobota'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Júl', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Január', 'Február', 'Marec', 'Apríl', 'Máj', 'Jún', 'Júl', 'August', 'September', 'Október', 'November', 'December') + ), + 'cs' => array ( + 'weekdays_short'=> array ('Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'), + 'weekdays_long' => array ('Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'), + 'months_short' => array ('Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čen', 'Čec', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro'), + 'months_long' => array ('Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec') + ), + 'hy' => array ( + 'weekdays_short'=> array ('Կրկ', 'Երկ', 'Երք', 'Չրք', 'Հնգ', 'Ուր', 'Շբթ'), + 'weekdays_long' => array ('Կիրակի', 'Երկուշաբթի', 'Երեքշաբթի', 'Չորեքշաբթի', 'Հինգշաբթի', 'Ուրբաթ', 'Շաբաթ'), + 'months_short' => array ('Հնվ', 'Փտր', 'Մրտ', 'Ապր', 'Մյս', 'Հնս', 'Հլս', 'Օգս', 'Սպտ', 'Հկտ', 'Նյմ', 'Դկտ'), + 'months_long' => array ('Հունվար', 'Փետրվար', 'Մարտ', 'Ապրիլ', 'Մայիս', 'Հունիս', 'Հուլիս', 'Օգոստոս', 'Սեպտեմբեր', 'Հոկտեմբեր', 'Նոյեմբեր', 'Դեկտեմբեր') + ), + 'nl' => array ( + 'weekdays_short'=> array ('Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'), + 'weekdays_long' => array ('Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December') + ), + 'et' => array ( + 'weekdays_short'=> array ('P', 'E', 'T', 'K', 'N', 'R', 'L'), + 'weekdays_long' => array ('Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'), + 'months_short' => array ('Jaan', 'Veebr', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'), + 'months_long' => array ('Jaanuar', 'Veebruar', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember') + ), + 'tr' => array ( + 'weekdays_short'=> array ('Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'), + 'weekdays_long' => array ('Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'), + 'months_short' => array ('Ock', 'Şbt', 'Mrt', 'Nsn', 'Mys', 'Hzrn', 'Tmmz', 'Ağst', 'Eyl', 'Ekm', 'Ksm', 'Arlk'), + 'months_long' => array ('Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık') + ), + 'no' => array ( + 'weekdays_short'=> array ('Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'), + 'weekdays_long' => array ('Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'), + 'months_long' => array ('Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Desember') + ), + 'eo' => array ( + 'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Ĵaŭ', 'Ven', 'Sab'), + 'weekdays_long' => array ('Dimanĉo', 'Lundo', 'Mardo', 'Merkredo', 'Ĵaŭdo', 'Vendredo', 'Sabato'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aŭg', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januaro', 'Februaro', 'Marto', 'Aprilo', 'Majo', 'Junio', 'Julio', 'Aŭgusto', 'Septembro', 'Oktobro', 'Novembro', 'Decembro') + ), + 'ua' => array ( + 'weekdays_short'=> array('Ндл', 'Пнд', 'Втр', 'Срд', 'Чтв', 'Птн', 'Сбт'), + 'weekdays_long' => array('Неділя', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'ятниця', 'Субота'), + 'months_short' => array('Січ', 'Лют', 'Бер', 'Кві', 'Тра', 'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'), + 'months_long' => array('Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень') + ), + 'ro' => array ( + 'weekdays_short'=> array ('Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sam'), + 'weekdays_long' => array ('Duminica', 'Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sambata'), + 'months_short' => array ('Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), + 'months_long' => array ('Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie') + ), + 'he' => array ( + 'weekdays_short'=> array ('ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'), + 'weekdays_long' => array ('יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'שבת'), + 'months_short' => array ('ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'), + 'months_long' => array ('ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר') + ), + 'sv' => array ( + 'weekdays_short'=> array ('Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'), + 'weekdays_long' => array ('Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December') + ), + 'pt' => array ( + 'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'), + 'weekdays_long' => array ('Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'), + 'months_short' => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'), + 'months_long' => array ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro') + ), + 'tw' => array ( + 'weekdays_short'=> array ('週日','週一', '週二','週三', '週四','週五', '週六'), + 'weekdays_long' => array ('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'), + 'months_short' => array ('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'), + 'months_long' => array ('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月') + ), + 'pt-br' => array ( + 'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'), + 'weekdays_long' => array ('Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'), + 'months_short' => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'), + 'months_long' => array ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro') + ) + ); + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * The following keys may appear in $options array: + * - 'language': date language + * - 'format': Format of the date, based on PHP's date() function. + * The following characters are currently recognised in format string: + *
  
+    *       D => Short names of days
+    *       l => Long names of days
+    *       d => Day numbers
+    *       M => Short names of months
+    *       F => Long names of months
+    *       m => Month numbers
+    *       Y => Four digit year
+    *       y => Two digit year
+    *       h => 12 hour format
+    *       H => 23 hour  format
+    *       i => Minutes
+    *       s => Seconds
+    *       a => am/pm
+    *       A => AM/PM
+    *   
+ * - 'minYear': Minimum year in year select + * - 'maxYear': Maximum year in year select + * - 'addEmptyOption': Should an empty option be added to the top of + * each select box? + * - 'emptyOptionValue': The value passed by the empty option. + * - 'emptyOptionText': The text displayed for the empty option. + * - 'optionIncrement': Step to increase the option values by (works for 'i' and 's') + * + * @access public + * @param string Element's name + * @param mixed Label(s) for an element + * @param array Options to control the element's display + * @param mixed Either a typical HTML attribute string or an associative array + */ + function HTML_QuickForm_date($elementName = null, $elementLabel = null, $options = array(), $attributes = null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_appendName = true; + $this->_type = 'date'; + // set the options, do not bother setting bogus ones + if (is_array($options)) { + foreach ($options as $name => $value) { + if ('language' == $name) { + $this->_options['language'] = isset($this->_locale[$value])? $value: 'en'; + } elseif (isset($this->_options[$name])) { + if (is_array($value) && is_array($this->_options[$name])) { + $this->_options[$name] = @array_merge($this->_options[$name], $value); + } else { + $this->_options[$name] = $value; + } + } + } + } + } + + // }}} + // {{{ _createElements() + + function _createElements() + { + $this->_separator = $this->_elements = array(); + $separator = ''; + $locale =& $this->_locale[$this->_options['language']]; + $backslash = false; + for ($i = 0, $length = strlen($this->_options['format']); $i < $length; $i++) { + $sign = $this->_options['format']{$i}; + if ($backslash) { + $backslash = false; + $separator .= $sign; + } else { + $loadSelect = true; + switch ($sign) { + case 'D': + // Sunday is 0 like with 'w' in date() + $options = $locale['weekdays_short']; + break; + case 'l': + $options = $locale['weekdays_long']; + break; + case 'd': + $options = $this->_createOptionList(1, 31); + break; + case 'M': + $options = $locale['months_short']; + array_unshift($options , ''); + unset($options[0]); + break; + case 'm': + $options = $this->_createOptionList(1, 12); + break; + case 'F': + $options = $locale['months_long']; + array_unshift($options , ''); + unset($options[0]); + break; + case 'Y': + $options = $this->_createOptionList( + $this->_options['minYear'], + $this->_options['maxYear'], + $this->_options['minYear'] > $this->_options['maxYear']? -1: 1 + ); + break; + case 'y': + $options = $this->_createOptionList( + $this->_options['minYear'], + $this->_options['maxYear'], + $this->_options['minYear'] > $this->_options['maxYear']? -1: 1 + ); + array_walk($options, create_function('&$v,$k','$v = substr($v,-2);')); + break; + case 'h': + $options = $this->_createOptionList(1, 12); + break; + case 'g': + $options = $this->_createOptionList(1, 12); + array_walk($options, create_function('&$v,$k', '$v = intval($v);')); + break; + case 'H': + $options = $this->_createOptionList(0, 23); + break; + case 'i': + $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['i']); + break; + case 's': + $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['s']); + break; + case 'a': + $options = array('am' => 'am', 'pm' => 'pm'); + break; + case 'A': + $options = array('AM' => 'AM', 'PM' => 'PM'); + break; + case 'W': + $options = $this->_createOptionList(1, 53); + break; + case '\\': + $backslash = true; + $loadSelect = false; + break; + default: + $separator .= (' ' == $sign? ' ': $sign); + $loadSelect = false; + } + + if ($loadSelect) { + if (0 < count($this->_elements)) { + $this->_separator[] = $separator; + } else { + $this->_wrap[0] = $separator; + } + $separator = ''; + // Should we add an empty option to the top of the select? + if (!is_array($this->_options['addEmptyOption']) && $this->_options['addEmptyOption'] || + is_array($this->_options['addEmptyOption']) && !empty($this->_options['addEmptyOption'][$sign])) { + + // Using '+' array operator to preserve the keys + if (is_array($this->_options['emptyOptionText']) && !empty($this->_options['emptyOptionText'][$sign])) { + $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText'][$sign]) + $options; + } else { + $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText']) + $options; + } + } + $this->_elements[] =& new HTML_QuickForm_select($sign, null, $options, $this->getAttributes()); + } + } + } + $this->_wrap[1] = $separator . ($backslash? '\\': ''); + } + + // }}} + // {{{ _createOptionList() + + /** + * Creates an option list containing the numbers from the start number to the end, inclusive + * + * @param int The start number + * @param int The end number + * @param int Increment by this value + * @access private + * @return array An array of numeric options. + */ + function _createOptionList($start, $end, $step = 1) + { + for ($i = $start, $options = array(); $start > $end? $i >= $end: $i <= $end; $i += $step) { + $options[$i] = sprintf('%02d', $i); + } + return $options; + } + + // }}} + // {{{ _trimLeadingZeros() + + /** + * Trims leading zeros from the (numeric) string + * + * @param string A numeric string, possibly with leading zeros + * @return string String with leading zeros removed + */ + function _trimLeadingZeros($str) + { + if (0 == strcmp($str, $this->_options['emptyOptionValue'])) { + return $str; + } + $trimmed = ltrim($str, '0'); + return strlen($trimmed)? $trimmed: '0'; + } + + // }}} + // {{{ setValue() + + function setValue($value) + { + if (empty($value)) { + $value = array(); + } elseif (is_scalar($value)) { + if (!is_numeric($value)) { + $value = strtotime($value); + } + // might be a unix epoch, then we fill all possible values + $arr = explode('-', date('w-j-n-Y-g-G-i-s-a-A-W', (int)$value)); + $value = array( + 'D' => $arr[0], + 'l' => $arr[0], + 'd' => $arr[1], + 'M' => $arr[2], + 'm' => $arr[2], + 'F' => $arr[2], + 'Y' => $arr[3], + 'y' => $arr[3], + 'h' => $arr[4], + 'g' => $arr[4], + 'H' => $arr[5], + 'i' => $this->_trimLeadingZeros($arr[6]), + 's' => $this->_trimLeadingZeros($arr[7]), + 'a' => $arr[8], + 'A' => $arr[9], + 'W' => $this->_trimLeadingZeros($arr[10]) + ); + } else { + $value = array_map(array($this, '_trimLeadingZeros'), $value); + } + parent::setValue($value); + } + + // }}} + // {{{ toHtml() + + function toHtml() + { + include_once('HTML/QuickForm/Renderer/Default.php'); + $renderer =& new HTML_QuickForm_Renderer_Default(); + $renderer->setElementTemplate('{element}'); + parent::accept($renderer); + return $this->_wrap[0] . $renderer->toHtml() . $this->_wrap[1]; + } + + // }}} + // {{{ accept() + + function accept(&$renderer, $required = false, $error = null) + { + $renderer->renderElement($this, $required, $error); + } + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + // we need to call setValue(), 'cause the default/constant value + // may be in fact a timestamp, not an array + return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller); + } else { + return parent::onQuickFormEvent($event, $arg, $caller); + } + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/HTML/QuickForm/element.php b/lib/Pear/HTML/QuickForm/element.php new file mode 100644 index 0000000..15af7de --- /dev/null +++ b/lib/Pear/HTML/QuickForm/element.php @@ -0,0 +1,494 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: element.php,v 1.36 2007/10/05 10:22:57 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for all HTML classes + */ +require_once 'HTML/Common.php'; + +/** + * Base class for form elements + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 1.0 + * @abstract + */ +class HTML_QuickForm_element extends HTML_Common +{ + // {{{ properties + + /** + * Label of the field + * @var string + * @since 1.3 + * @access private + */ + var $_label = ''; + + /** + * Form element type + * @var string + * @since 1.0 + * @access private + */ + var $_type = ''; + + /** + * Flag to tell if element is frozen + * @var boolean + * @since 1.0 + * @access private + */ + var $_flagFrozen = false; + + /** + * Does the element support persistant data when frozen + * @var boolean + * @since 1.3 + * @access private + */ + var $_persistantFreeze = false; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Name of the element + * @param mixed Label(s) for the element + * @param mixed Associative array of tag attributes or HTML attributes name="value" pairs + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_element($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_Common::HTML_Common($attributes); + if (isset($elementName)) { + $this->setName($elementName); + } + if (isset($elementLabel)) { + $this->setLabel($elementLabel); + } + } //end constructor + + // }}} + // {{{ apiVersion() + + /** + * Returns the current API version + * + * @since 1.0 + * @access public + * @return float + */ + function apiVersion() + { + return 3.2; + } // end func apiVersion + + // }}} + // {{{ getType() + + /** + * Returns element type + * + * @since 1.0 + * @access public + * @return string + */ + function getType() + { + return $this->_type; + } // end func getType + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + // interface method + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + // interface method + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param string $value Default value of the form element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + // interface + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return mixed + */ + function getValue() + { + // interface + return null; + } // end func getValue + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + $this->_flagFrozen = true; + } //end func freeze + + // }}} + // {{{ unfreeze() + + /** + * Unfreezes the element so that it becomes editable + * + * @access public + * @return void + * @since 3.2.4 + */ + function unfreeze() + { + $this->_flagFrozen = false; + } + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = $this->getValue(); + return (strlen($value)? htmlspecialchars($value): ' ') . + $this->_getPersistantData(); + } //end func getFrozenHtml + + // }}} + // {{{ _getPersistantData() + + /** + * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on + * + * @access private + * @return string + */ + function _getPersistantData() + { + if (!$this->_persistantFreeze) { + return ''; + } else { + $id = $this->getAttribute('id'); + return '_getAttrString(array( + 'type' => 'hidden', + 'name' => $this->getName(), + 'value' => $this->getValue() + ) + (isset($id)? array('id' => $id): array())) . ' />'; + } + } + + // }}} + // {{{ isFrozen() + + /** + * Returns whether or not the element is frozen + * + * @since 1.3 + * @access public + * @return bool + */ + function isFrozen() + { + return $this->_flagFrozen; + } // end func isFrozen + + // }}} + // {{{ setPersistantFreeze() + + /** + * Sets wether an element value should be kept in an hidden field + * when the element is frozen or not + * + * @param bool $persistant True if persistant value + * @since 2.0 + * @access public + * @return void + */ + function setPersistantFreeze($persistant=false) + { + $this->_persistantFreeze = $persistant; + } //end func setPersistantFreeze + + // }}} + // {{{ setLabel() + + /** + * Sets display text for the element + * + * @param string $label Display text for the element + * @since 1.3 + * @access public + * @return void + */ + function setLabel($label) + { + $this->_label = $label; + } //end func setLabel + + // }}} + // {{{ getLabel() + + /** + * Returns display text for the element + * + * @since 1.3 + * @access public + * @return string + */ + function getLabel() + { + return $this->_label; + } //end func getLabel + + // }}} + // {{{ _findValue() + + /** + * Tries to find the element value from the values array + * + * @since 2.7 + * @access private + * @return mixed + */ + function _findValue(&$values) + { + if (empty($values)) { + return null; + } + $elementName = $this->getName(); + if (isset($values[$elementName])) { + return $values[$elementName]; + } elseif (strpos($elementName, '[')) { + $myVar = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + $elementName + ) . "']"; + return eval("return (isset(\$values$myVar)) ? \$values$myVar : null;"); + } else { + return null; + } + } //end func _findValue + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'createElement': + $className = get_class($this); + $this->$className($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]); + break; + case 'addElement': + $this->onQuickFormEvent('createElement', $arg, $caller); + $this->onQuickFormEvent('updateValue', null, $caller); + break; + case 'updateValue': + // constant values override both default and submitted ones + // default values are overriden by submitted + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value) { + $this->setValue($value); + } + break; + case 'setGroupValue': + $this->setValue($arg); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @param bool Whether an element is required + * @param string An error message associated with an element + * @access public + * @return void + */ + function accept(&$renderer, $required=false, $error=null) + { + $renderer->renderElement($this, $required, $error); + } // end func accept + + // }}} + // {{{ _generateId() + + /** + * Automatically generates and assigns an 'id' attribute for the element. + * + * Currently used to ensure that labels work on radio buttons and + * checkboxes. Per idea of Alexander Radivanovich. + * + * @access private + * @return void + */ + function _generateId() + { + static $idx = 1; + + if (!$this->getAttribute('id')) { + $this->updateAttributes(array('id' => 'qf_' . substr(md5(microtime() . $idx++), 0, 6))); + } + } // end func _generateId + + // }}} + // {{{ exportValue() + + /** + * Returns a 'safe' element's value + * + * @param array array of submitted values to search + * @param bool whether to return the value as associative array + * @access public + * @return mixed + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (null === $value) { + $value = $this->getValue(); + } + return $this->_prepareValue($value, $assoc); + } + + // }}} + // {{{ _prepareValue() + + /** + * Used by exportValue() to prepare the value for returning + * + * @param mixed the value found in exportValue() + * @param bool whether to return the value as associative array + * @access private + * @return mixed + */ + function _prepareValue($value, $assoc) + { + if (null === $value) { + return null; + } elseif (!$assoc) { + return $value; + } else { + $name = $this->getName(); + if (!strpos($name, '[')) { + return array($name => $value); + } else { + $valueAry = array(); + $myIndex = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + $name + ) . "']"; + eval("\$valueAry$myIndex = \$value;"); + return $valueAry; + } + } + } + + // }}} +} // end class HTML_QuickForm_element +?> \ No newline at end of file diff --git a/lib/Pear/HTML/QuickForm/file.php b/lib/Pear/HTML/QuickForm/file.php new file mode 100644 index 0000000..ee1e771 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/file.php @@ -0,0 +1,358 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: file.php,v 1.24 2007/10/05 10:17:55 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +// register file-related rules +if (class_exists('HTML_QuickForm')) { + HTML_QuickForm::registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', 'HTML_QuickForm_file'); + HTML_QuickForm::registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', 'HTML_QuickForm_file'); + HTML_QuickForm::registerRule('mimetype', 'callback', '_ruleCheckMimeType', 'HTML_QuickForm_file'); + HTML_QuickForm::registerRule('filename', 'callback', '_ruleCheckFileName', 'HTML_QuickForm_file'); +} + +/** + * HTML class for a file upload field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_file extends HTML_QuickForm_input +{ + // {{{ properties + + /** + * Uploaded file data, from $_FILES + * @var array + */ + var $_value = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param string Input field label + * @param mixed (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + */ + function HTML_QuickForm_file($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->setType('file'); + } //end constructor + + // }}} + // {{{ setSize() + + /** + * Sets size of file element + * + * @param int Size of file element + * @since 1.0 + * @access public + */ + function setSize($size) + { + $this->updateAttributes(array('size' => $size)); + } //end func setSize + + // }}} + // {{{ getSize() + + /** + * Returns size of file element + * + * @since 1.0 + * @access public + * @return int + */ + function getSize() + { + return $this->getAttribute('size'); + } //end func getSize + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return bool + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + // {{{ setValue() + + /** + * Sets value for file element. + * + * Actually this does nothing. The function is defined here to override + * HTML_Quickform_input's behaviour of setting the 'value' attribute. As + * no sane user-agent uses 's value for anything + * (because of security implications) we implement file's value as a + * read-only property with a special meaning. + * + * @param mixed Value for file element + * @since 3.0 + * @access public + */ + function setValue($value) + { + return null; + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns information about the uploaded file + * + * @since 3.0 + * @access public + * @return array + */ + function getValue() + { + return $this->_value; + } // end func getValue + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string Name of event + * @param mixed event arguments + * @param object calling object + * @since 1.0 + * @access public + * @return bool + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + if ($caller->getAttribute('method') == 'get') { + return PEAR::raiseError('Cannot add a file upload field to a GET method form'); + } + $this->_value = $this->_findValue(); + $caller->updateAttributes(array('enctype' => 'multipart/form-data')); + $caller->setMaxFileSize(); + break; + case 'addElement': + $this->onQuickFormEvent('createElement', $arg, $caller); + return $this->onQuickFormEvent('updateValue', null, $caller); + break; + case 'createElement': + $className = get_class($this); + $this->$className($arg[0], $arg[1], $arg[2]); + break; + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ moveUploadedFile() + + /** + * Moves an uploaded file into the destination + * + * @param string Destination directory path + * @param string New file name + * @access public + * @return bool Whether the file was moved successfully + */ + function moveUploadedFile($dest, $fileName = '') + { + if ($dest != '' && substr($dest, -1) != '/') { + $dest .= '/'; + } + $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']); + return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName); + } // end func moveUploadedFile + + // }}} + // {{{ isUploadedFile() + + /** + * Checks if the element contains an uploaded file + * + * @access public + * @return bool true if file has been uploaded, false otherwise + */ + function isUploadedFile() + { + return $this->_ruleIsUploadedFile($this->_value); + } // end func isUploadedFile + + // }}} + // {{{ _ruleIsUploadedFile() + + /** + * Checks if the given element contains an uploaded file + * + * @param array Uploaded file info (from $_FILES) + * @access private + * @return bool true if file has been uploaded, false otherwise + */ + function _ruleIsUploadedFile($elementValue) + { + if ((isset($elementValue['error']) && $elementValue['error'] == 0) || + (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) { + return is_uploaded_file($elementValue['tmp_name']); + } else { + return false; + } + } // end func _ruleIsUploadedFile + + // }}} + // {{{ _ruleCheckMaxFileSize() + + /** + * Checks that the file does not exceed the max file size + * + * @param array Uploaded file info (from $_FILES) + * @param int Max file size + * @access private + * @return bool true if filesize is lower than maxsize, false otherwise + */ + function _ruleCheckMaxFileSize($elementValue, $maxSize) + { + if (!empty($elementValue['error']) && + (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) { + return false; + } + if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) { + return true; + } + return ($maxSize >= @filesize($elementValue['tmp_name'])); + } // end func _ruleCheckMaxFileSize + + // }}} + // {{{ _ruleCheckMimeType() + + /** + * Checks if the given element contains an uploaded file of the right mime type + * + * @param array Uploaded file info (from $_FILES) + * @param mixed Mime Type (can be an array of allowed types) + * @access private + * @return bool true if mimetype is correct, false otherwise + */ + function _ruleCheckMimeType($elementValue, $mimeType) + { + if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) { + return true; + } + if (is_array($mimeType)) { + return in_array($elementValue['type'], $mimeType); + } + return $elementValue['type'] == $mimeType; + } // end func _ruleCheckMimeType + + // }}} + // {{{ _ruleCheckFileName() + + /** + * Checks if the given element contains an uploaded file of the filename regex + * + * @param array Uploaded file info (from $_FILES) + * @param string Regular expression + * @access private + * @return bool true if name matches regex, false otherwise + */ + function _ruleCheckFileName($elementValue, $regex) + { + if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) { + return true; + } + return (bool)preg_match($regex, $elementValue['name']); + } // end func _ruleCheckFileName + + // }}} + // {{{ _findValue() + + /** + * Tries to find the element value from the values array + * + * Needs to be redefined here as $_FILES is populated differently from + * other arrays when element name is of the form foo[bar] + * + * @access private + * @return mixed + */ + function _findValue() + { + if (empty($_FILES)) { + return null; + } + $elementName = $this->getName(); + if (isset($_FILES[$elementName])) { + return $_FILES[$elementName]; + } elseif (false !== ($pos = strpos($elementName, '['))) { + $base = str_replace( + array('\\', '\''), array('\\\\', '\\\''), + substr($elementName, 0, $pos) + ); + $idx = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + substr($elementName, $pos + 1, -1) + ) . "']"; + $props = array('name', 'type', 'size', 'tmp_name', 'error'); + $code = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" . + " return null;\n" . + "} else {\n" . + " \$value = array();\n"; + foreach ($props as $prop) { + $code .= " \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n"; + } + return eval($code . " return \$value;\n}\n"); + } else { + return null; + } + } + + // }}} +} // end class HTML_QuickForm_file +?> diff --git a/lib/Pear/HTML/QuickForm/group.php b/lib/Pear/HTML/QuickForm/group.php new file mode 100644 index 0000000..6ffde90 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/group.php @@ -0,0 +1,588 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: group.php,v 1.39 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/element.php'; + +/** + * HTML class for a form element group + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_group extends HTML_QuickForm_element +{ + // {{{ properties + + /** + * Name of the element + * @var string + * @since 1.0 + * @access private + */ + var $_name = ''; + + /** + * Array of grouped elements + * @var array + * @since 1.0 + * @access private + */ + var $_elements = array(); + + /** + * String to separate elements + * @var mixed + * @since 2.5 + * @access private + */ + var $_separator = null; + + /** + * Required elements in this group + * @var array + * @since 2.5 + * @access private + */ + var $_required = array(); + + /** + * Whether to change elements' names to $groupName[$elementName] or leave them as is + * @var bool + * @since 3.0 + * @access private + */ + var $_appendName = true; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Group name + * @param array $elementLabel (optional)Group label + * @param array $elements (optional)Group elements + * @param mixed $separator (optional)Use a string for one separator, + * use an array to alternate the separators. + * @param bool $appendName (optional)whether to change elements' names to + * the form $groupName[$elementName] or leave + * them as is. + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_group($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true) + { + $this->HTML_QuickForm_element($elementName, $elementLabel); + $this->_type = 'group'; + if (isset($elements) && is_array($elements)) { + $this->setElements($elements); + } + if (isset($separator)) { + $this->_separator = $separator; + } + if (isset($appendName)) { + $this->_appendName = $appendName; + } + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the group name + * + * @param string $name Group name + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->_name = $name; + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the group name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->_name; + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets values for group's elements + * + * @param mixed Values for group's elements + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->_createElementsIfNotExist(); + foreach (array_keys($this->_elements) as $key) { + if (!$this->_appendName) { + $v = $this->_elements[$key]->_findValue($value); + if (null !== $v) { + $this->_elements[$key]->onQuickFormEvent('setGroupValue', $v, $this); + } + + } else { + $elementName = $this->_elements[$key]->getName(); + $index = strlen($elementName) ? $elementName : $key; + if (is_array($value)) { + if (isset($value[$index])) { + $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value[$index], $this); + } + } elseif (isset($value)) { + $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value, $this); + } + } + } + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the group + * + * @since 1.0 + * @access public + * @return mixed + */ + function getValue() + { + $value = null; + foreach (array_keys($this->_elements) as $key) { + $element =& $this->_elements[$key]; + switch ($element->getType()) { + case 'radio': + $v = $element->getChecked()? $element->getValue(): null; + break; + case 'checkbox': + $v = $element->getChecked()? true: null; + break; + default: + $v = $element->getValue(); + } + if (null !== $v) { + $elementName = $element->getName(); + if (is_null($elementName)) { + $value = $v; + } else { + if (!is_array($value)) { + $value = is_null($value)? array(): array($value); + } + if ('' === $elementName) { + $value[] = $v; + } else { + $value[$elementName] = $v; + } + } + } + } + return $value; + } // end func getValue + + // }}} + // {{{ setElements() + + /** + * Sets the grouped elements + * + * @param array $elements Array of elements + * @since 1.1 + * @access public + * @return void + */ + function setElements($elements) + { + $this->_elements = array_values($elements); + if ($this->_flagFrozen) { + $this->freeze(); + } + } // end func setElements + + // }}} + // {{{ getElements() + + /** + * Gets the grouped elements + * + * @since 2.4 + * @access public + * @return array + */ + function &getElements() + { + $this->_createElementsIfNotExist(); + return $this->_elements; + } // end func getElements + + // }}} + // {{{ getGroupType() + + /** + * Gets the group type based on its elements + * Will return 'mixed' if elements contained in the group + * are of different types. + * + * @access public + * @return string group elements type + */ + function getGroupType() + { + $this->_createElementsIfNotExist(); + $prevType = ''; + foreach (array_keys($this->_elements) as $key) { + $type = $this->_elements[$key]->getType(); + if ($type != $prevType && $prevType != '') { + return 'mixed'; + } + $prevType = $type; + } + return $type; + } // end func getGroupType + + // }}} + // {{{ toHtml() + + /** + * Returns Html for the group + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + include_once('HTML/QuickForm/Renderer/Default.php'); + $renderer =& new HTML_QuickForm_Renderer_Default(); + $renderer->setElementTemplate('{element}'); + $this->accept($renderer); + return $renderer->toHtml(); + } //end func toHtml + + // }}} + // {{{ getElementName() + + /** + * Returns the element name inside the group such as found in the html form + * + * @param mixed $index Element name or element index in the group + * @since 3.0 + * @access public + * @return mixed string with element name, false if not found + */ + function getElementName($index) + { + $this->_createElementsIfNotExist(); + $elementName = false; + if (is_int($index) && isset($this->_elements[$index])) { + $elementName = $this->_elements[$index]->getName(); + if (isset($elementName) && $elementName == '') { + $elementName = $index; + } + if ($this->_appendName) { + if (is_null($elementName)) { + $elementName = $this->getName(); + } else { + $elementName = $this->getName().'['.$elementName.']'; + } + } + + } elseif (is_string($index)) { + foreach (array_keys($this->_elements) as $key) { + $elementName = $this->_elements[$key]->getName(); + if ($index == $elementName) { + if ($this->_appendName) { + $elementName = $this->getName().'['.$elementName.']'; + } + break; + } elseif ($this->_appendName && $this->getName().'['.$elementName.']' == $index) { + break; + } + } + } + return $elementName; + } //end func getElementName + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.3 + * @access public + * @return string + */ + function getFrozenHtml() + { + $flags = array(); + $this->_createElementsIfNotExist(); + foreach (array_keys($this->_elements) as $key) { + if (false === ($flags[$key] = $this->_elements[$key]->isFrozen())) { + $this->_elements[$key]->freeze(); + } + } + $html = $this->toHtml(); + foreach (array_keys($this->_elements) as $key) { + if (!$flags[$key]) { + $this->_elements[$key]->unfreeze(); + } + } + return $html; + } //end func getFrozenHtml + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + $this->_createElementsIfNotExist(); + foreach (array_keys($this->_elements) as $key) { + if ($this->_appendName) { + $elementName = $this->_elements[$key]->getName(); + if (is_null($elementName)) { + $this->_elements[$key]->setName($this->getName()); + } elseif ('' === $elementName) { + $this->_elements[$key]->setName($this->getName() . '[' . $key . ']'); + } else { + $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']'); + } + } + $this->_elements[$key]->onQuickFormEvent('updateValue', $arg, $caller); + if ($this->_appendName) { + $this->_elements[$key]->setName($elementName); + } + } + break; + + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @param bool Whether a group is required + * @param string An error message associated with a group + * @access public + * @return void + */ + function accept(&$renderer, $required = false, $error = null) + { + $this->_createElementsIfNotExist(); + $renderer->startGroup($this, $required, $error); + $name = $this->getName(); + foreach (array_keys($this->_elements) as $key) { + $element =& $this->_elements[$key]; + + if ($this->_appendName) { + $elementName = $element->getName(); + if (isset($elementName)) { + $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']'); + } else { + $element->setName($name); + } + } + + $required = !$element->isFrozen() && in_array($element->getName(), $this->_required); + + $element->accept($renderer, $required); + + // restore the element's name + if ($this->_appendName) { + $element->setName($elementName); + } + } + $renderer->finishGroup($this); + } // end func accept + + // }}} + // {{{ exportValue() + + /** + * As usual, to get the group's value we access its elements and call + * their exportValue() methods + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = null; + foreach (array_keys($this->_elements) as $key) { + $elementName = $this->_elements[$key]->getName(); + if ($this->_appendName) { + if (is_null($elementName)) { + $this->_elements[$key]->setName($this->getName()); + } elseif ('' === $elementName) { + $this->_elements[$key]->setName($this->getName() . '[' . $key . ']'); + } else { + $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']'); + } + } + $v = $this->_elements[$key]->exportValue($submitValues, $assoc); + if ($this->_appendName) { + $this->_elements[$key]->setName($elementName); + } + if (null !== $v) { + // Make $value an array, we will use it like one + if (null === $value) { + $value = array(); + } + if ($assoc) { + // just like HTML_QuickForm::exportValues() + $value = HTML_QuickForm::arrayMerge($value, $v); + } else { + // just like getValue(), but should work OK every time here + if (is_null($elementName)) { + $value = $v; + } elseif ('' === $elementName) { + $value[] = $v; + } else { + $value[$elementName] = $v; + } + } + } + } + // do not pass the value through _prepareValue, we took care of this already + return $value; + } + + // }}} + // {{{ _createElements() + + /** + * Creates the group's elements. + * + * This should be overriden by child classes that need to create their + * elements. The method will be called automatically when needed, calling + * it from the constructor is discouraged as the constructor is usually + * called _twice_ on element creation, first time with _no_ parameters. + * + * @access private + * @abstract + */ + function _createElements() + { + // abstract + } + + // }}} + // {{{ _createElementsIfNotExist() + + /** + * A wrapper around _createElements() + * + * This method calls _createElements() if the group's _elements array + * is empty. It also performs some updates, e.g. freezes the created + * elements if the group is already frozen. + * + * @access private + */ + function _createElementsIfNotExist() + { + if (empty($this->_elements)) { + $this->_createElements(); + if ($this->_flagFrozen) { + $this->freeze(); + } + } + } + + // }}} + // {{{ freeze() + + function freeze() + { + parent::freeze(); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->freeze(); + } + } + + // }}} + // {{{ unfreeze() + + function unfreeze() + { + parent::unfreeze(); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->unfreeze(); + } + } + + // }}} + // {{{ setPersistantFreeze() + + function setPersistantFreeze($persistant = false) + { + parent::setPersistantFreeze($persistant); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->setPersistantFreeze($persistant); + } + } + + // }}} +} //end class HTML_QuickForm_group +?> \ No newline at end of file diff --git a/lib/Pear/HTML/QuickForm/header.php b/lib/Pear/HTML/QuickForm/header.php new file mode 100644 index 0000000..41e8d69 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/header.php @@ -0,0 +1,74 @@ + + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: header.php,v 1.2 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * HTML class for static data + */ +require_once 'HTML/QuickForm/static.php'; + +/** + * A pseudo-element used for adding headers to form + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 3.0 + */ +class HTML_QuickForm_header extends HTML_QuickForm_static +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName Header name + * @param string $text Header text + * @access public + * @return void + */ + function HTML_QuickForm_header($elementName = null, $text = null) + { + $this->HTML_QuickForm_static($elementName, null, $text); + $this->_type = 'header'; + } + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @access public + * @return void + */ + function accept(&$renderer) + { + $renderer->renderHeader($this); + } // end func accept + + // }}} + +} //end class HTML_QuickForm_header +?> diff --git a/lib/Pear/HTML/QuickForm/hidden.php b/lib/Pear/HTML/QuickForm/hidden.php new file mode 100644 index 0000000..2a48deb --- /dev/null +++ b/lib/Pear/HTML/QuickForm/hidden.php @@ -0,0 +1,94 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: hidden.php,v 1.11 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a hidden type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_hidden extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $value (optional)Input field value + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_hidden($elementName=null, $value='', $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setType('hidden'); + $this->setValue($value); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @access public + * @return void + */ + function accept(&$renderer) + { + $renderer->renderHidden($this); + } // end func accept + + // }}} + +} //end class HTML_QuickForm_hidden +?> diff --git a/lib/Pear/HTML/QuickForm/hiddenselect.php b/lib/Pear/HTML/QuickForm/hiddenselect.php new file mode 100644 index 0000000..1769a70 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/hiddenselect.php @@ -0,0 +1,118 @@ + + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: hiddenselect.php,v 1.6 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Class for elements + */ +require_once 'HTML/QuickForm/select.php'; + +/** + * Hidden select pseudo-element + * + * This class takes the same arguments as a select element, but instead + * of creating a select ring it creates hidden elements for all values + * already selected with setDefault or setConstant. This is useful if + * you have a select ring that you don't want visible, but you need all + * selected values to be passed. + * + * @category HTML + * @package HTML_QuickForm + * @author Isaac Shepard + * @version Release: 3.2.10 + * @since 2.1 + */ +class HTML_QuickForm_hiddenselect extends HTML_QuickForm_select +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string Select name attribute + * @param mixed Label(s) for the select (not used) + * @param mixed Data to be used to populate options + * @param mixed Either a typical HTML attribute string or an associative array (not used) + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_hiddenselect($elementName=null, $elementLabel=null, $options=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'hiddenselect'; + if (isset($options)) { + $this->load($options); + } + } //end constructor + + // }}} + // {{{ toHtml() + + /** + * Returns the SELECT in HTML + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function toHtml() + { + if (empty($this->_values)) { + return ''; + } + + $tabs = $this->_getTabs(); + $name = $this->getPrivateName(); + $strHtml = ''; + + foreach ($this->_values as $key => $val) { + for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { + if ($val == $this->_options[$i]['attr']['value']) { + $strHtml .= $tabs . '_getAttrString(array( + 'type' => 'hidden', + 'name' => $name, + 'value' => $val + )) . " />\n" ; + } + } + } + + return $strHtml; + } //end func toHtml + + // }}} + // {{{ accept() + + /** + * This is essentially a hidden element and should be rendered as one + */ + function accept(&$renderer) + { + $renderer->renderHidden($this); + } + + // }}} +} //end class HTML_QuickForm_hiddenselect +?> diff --git a/lib/Pear/HTML/QuickForm/hierselect.php b/lib/Pear/HTML/QuickForm/hierselect.php new file mode 100644 index 0000000..cba2aa7 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/hierselect.php @@ -0,0 +1,593 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: hierselect.php,v 1.19 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Class for a group of form elements + */ +require_once 'HTML/QuickForm/group.php'; +/** + * Class for elements + */ +require_once 'HTML/QuickForm/select.php'; + +/** + * Hierarchical select element + * + * Class to dynamically create two or more HTML Select elements + * The first select changes the content of the second select and so on. + * This element is considered as a group. Selects will be named + * groupName[0], groupName[1], groupName[2]... + * + * @category HTML + * @package HTML_QuickForm + * @author Herim Vasquez + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 3.1 + */ +class HTML_QuickForm_hierselect extends HTML_QuickForm_group +{ + // {{{ properties + + /** + * Options for all the select elements + * + * @see setOptions() + * @var array + * @access private + */ + var $_options = array(); + + /** + * Number of select elements on this group + * + * @var int + * @access private + */ + var $_nbElements = 0; + + /** + * The javascript used to set and change the options + * + * @var string + * @access private + */ + var $_js = ''; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field label in form + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array. Date format is passed along the attributes. + * @param mixed $separator (optional)Use a string for one separator, + * use an array to alternate the separators. + * @access public + * @return void + */ + function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + if (isset($separator)) { + $this->_separator = $separator; + } + $this->_type = 'hierselect'; + $this->_appendName = true; + } //end constructor + + // }}} + // {{{ setOptions() + + /** + * Initialize the array structure containing the options for each select element. + * Call the functions that actually do the magic. + * + * Format is a bit more complex than for a simple select as we need to know + * which options are related to the ones in the previous select: + * + * Ex: + * + * // first select + * $select1[0] = 'Pop'; + * $select1[1] = 'Classical'; + * $select1[2] = 'Funeral doom'; + * + * // second select + * $select2[0][0] = 'Red Hot Chil Peppers'; + * $select2[0][1] = 'The Pixies'; + * $select2[1][0] = 'Wagner'; + * $select2[1][1] = 'Strauss'; + * $select2[2][0] = 'Pantheist'; + * $select2[2][1] = 'Skepticism'; + * + * // If only need two selects + * // - and using the deprecated functions + * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:'); + * $sel->setMainOptions($select1); + * $sel->setSecOptions($select2); + * + * // - and using the new setOptions function + * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:'); + * $sel->setOptions(array($select1, $select2)); + * + * // If you have a third select with prices for the cds + * $select3[0][0][0] = '15.00$'; + * $select3[0][0][1] = '17.00$'; + * // etc + * + * // You can now use + * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:'); + * $sel->setOptions(array($select1, $select2, $select3)); + * + * + * @param array $options Array of options defining each element + * @access public + * @return void + */ + function setOptions($options) + { + $this->_options = $options; + + if (empty($this->_elements)) { + $this->_nbElements = count($this->_options); + $this->_createElements(); + } else { + // setDefaults has probably been called before this function + // check if all elements have been created + $totalNbElements = count($this->_options); + for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) { + $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes()); + $this->_nbElements++; + } + } + + $this->_setOptions(); + } // end func setMainOptions + + // }}} + // {{{ setMainOptions() + + /** + * Sets the options for the first select element. Deprecated. setOptions() should be used. + * + * @param array $array Options for the first select element + * + * @access public + * @deprecated Deprecated since release 3.2.2 + * @return void + */ + function setMainOptions($array) + { + $this->_options[0] = $array; + + if (empty($this->_elements)) { + $this->_nbElements = 2; + $this->_createElements(); + } + } // end func setMainOptions + + // }}} + // {{{ setSecOptions() + + /** + * Sets the options for the second select element. Deprecated. setOptions() should be used. + * The main _options array is initialized and the _setOptions function is called. + * + * @param array $array Options for the second select element + * + * @access public + * @deprecated Deprecated since release 3.2.2 + * @return void + */ + function setSecOptions($array) + { + $this->_options[1] = $array; + + if (empty($this->_elements)) { + $this->_nbElements = 2; + $this->_createElements(); + } else { + // setDefaults has probably been called before this function + // check if all elements have been created + $totalNbElements = 2; + for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) { + $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes()); + $this->_nbElements++; + } + } + + $this->_setOptions(); + } // end func setSecOptions + + // }}} + // {{{ _setOptions() + + /** + * Sets the options for each select element + * + * @access private + * @return void + */ + function _setOptions() + { + $toLoad = ''; + foreach (array_keys($this->_elements) AS $key) { + $array = eval("return isset(\$this->_options[{$key}]{$toLoad})? \$this->_options[{$key}]{$toLoad}: null;"); + if (is_array($array)) { + $select =& $this->_elements[$key]; + $select->_options = array(); + $select->loadArray($array); + + $value = is_array($v = $select->getValue()) ? $v[0] : key($array); + $toLoad .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $value) . '\']'; + } + } + } // end func _setOptions + + // }}} + // {{{ setValue() + + /** + * Sets values for group's elements + * + * @param array $value An array of 2 or more values, for the first, + * the second, the third etc. select + * + * @access public + * @return void + */ + function setValue($value) + { + // fix for bug #6766. Hope this doesn't break anything more + // after bug #7961. Forgot that _nbElements was used in + // _createElements() called in several places... + $this->_nbElements = max($this->_nbElements, count($value)); + parent::setValue($value); + $this->_setOptions(); + } // end func setValue + + // }}} + // {{{ _createElements() + + /** + * Creates all the elements for the group + * + * @access private + * @return void + */ + function _createElements() + { + for ($i = 0; $i < $this->_nbElements; $i++) { + $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes()); + } + } // end func _createElements + + // }}} + // {{{ toHtml() + + function toHtml() + { + $this->_js = ''; + if (!$this->_flagFrozen) { + // set the onchange attribute for each element except last + $keys = array_keys($this->_elements); + $onChange = array(); + for ($i = 0; $i < count($keys) - 1; $i++) { + $select =& $this->_elements[$keys[$i]]; + $onChange[$i] = $select->getAttribute('onchange'); + $select->updateAttributes( + array('onchange' => '_hs_swapOptions(this.form, \'' . $this->_escapeString($this->getName()) . '\', ' . $keys[$i] . ');' . $onChange[$i]) + ); + } + + // create the js function to call + if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) { + $this->_js .= <<_nbElements; $i++) { + $jsParts[] = $this->_convertArrayToJavascript($this->_options[$i]); + } + $this->_js .= "\n_hs_options['" . $this->_escapeString($this->getName()) . "'] = [\n" . + implode(",\n", $jsParts) . + "\n];\n"; + // default value; if we don't actually have any values yet just use + // the first option (for single selects) or empty array (for multiple) + $values = array(); + foreach (array_keys($this->_elements) as $key) { + if (is_array($v = $this->_elements[$key]->getValue())) { + $values[] = count($v) > 1? $v: $v[0]; + } else { + // XXX: accessing the supposedly private _options array + $values[] = $this->_elements[$key]->getMultiple() || empty($this->_elements[$key]->_options[0])? + array(): + $this->_elements[$key]->_options[0]['attr']['value']; + } + } + $this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " . + $this->_convertArrayToJavascript($values, false) . ";\n"; + } + include_once('HTML/QuickForm/Renderer/Default.php'); + $renderer =& new HTML_QuickForm_Renderer_Default(); + $renderer->setElementTemplate('{element}'); + parent::accept($renderer); + + if (!empty($onChange)) { + $keys = array_keys($this->_elements); + for ($i = 0; $i < count($keys) - 1; $i++) { + $this->_elements[$keys[$i]]->updateAttributes(array('onchange' => $onChange[$i])); + } + } + return (empty($this->_js)? '': "") . + $renderer->toHtml(); + } // end func toHtml + + // }}} + // {{{ accept() + + function accept(&$renderer, $required = false, $error = null) + { + $renderer->renderElement($this, $required, $error); + } // end func accept + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + // we need to call setValue() so that the secondary option + // matches the main option + return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller); + } else { + $ret = parent::onQuickFormEvent($event, $arg, $caller); + // add onreset handler to form to properly reset hierselect (see bug #2970) + if ('addElement' == $event) { + $onReset = $caller->getAttribute('onreset'); + if (strlen($onReset)) { + if (strpos($onReset, '_hs_setupOnReset')) { + $caller->updateAttributes(array('onreset' => str_replace('_hs_setupOnReset(this, [', "_hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "', ", $onReset))); + } else { + $caller->updateAttributes(array('onreset' => "var temp = function() { {$onReset} } ; if (!temp()) { return false; } ; if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } ")); + } + } else { + $caller->updateAttributes(array('onreset' => "if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } ")); + } + } + return $ret; + } + } // end func onQuickFormEvent + + // }}} + // {{{ _convertArrayToJavascript() + + /** + * Converts PHP array to its Javascript analog + * + * @access private + * @param array PHP array to convert + * @param bool Generate Javascript object literal (default, works like PHP's associative array) or array literal + * @return string Javascript representation of the value + */ + function _convertArrayToJavascript($array, $assoc = true) + { + if (!is_array($array)) { + return $this->_convertScalarToJavascript($array); + } else { + $items = array(); + foreach ($array as $key => $val) { + $item = $assoc? "'" . $this->_escapeString($key) . "': ": ''; + if (is_array($val)) { + $item .= $this->_convertArrayToJavascript($val, $assoc); + } else { + $item .= $this->_convertScalarToJavascript($val); + } + $items[] = $item; + } + } + $js = implode(', ', $items); + return $assoc? '{ ' . $js . ' }': '[' . $js . ']'; + } + + // }}} + // {{{ _convertScalarToJavascript() + + /** + * Converts PHP's scalar value to its Javascript analog + * + * @access private + * @param mixed PHP value to convert + * @return string Javascript representation of the value + */ + function _convertScalarToJavascript($val) + { + if (is_bool($val)) { + return $val ? 'true' : 'false'; + } elseif (is_int($val) || is_double($val)) { + return $val; + } elseif (is_string($val)) { + return "'" . $this->_escapeString($val) . "'"; + } elseif (is_null($val)) { + return 'null'; + } else { + // don't bother + return '{}'; + } + } + + // }}} + // {{{ _escapeString() + + /** + * Quotes the string so that it can be used in Javascript string constants + * + * @access private + * @param string + * @return string + */ + function _escapeString($str) + { + return strtr($str,array( + "\r" => '\r', + "\n" => '\n', + "\t" => '\t', + "'" => "\\'", + '"' => '\"', + '\\' => '\\\\' + )); + } + + // }}} +} // end class HTML_QuickForm_hierselect +?> \ No newline at end of file diff --git a/lib/Pear/HTML/QuickForm/html.php b/lib/Pear/HTML/QuickForm/html.php new file mode 100644 index 0000000..1703b1d --- /dev/null +++ b/lib/Pear/HTML/QuickForm/html.php @@ -0,0 +1,77 @@ + + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: html.php,v 1.2 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * HTML class for static data + */ +require_once 'HTML/QuickForm/static.php'; + +/** + * A pseudo-element used for adding raw HTML to form + * + * Intended for use with the default renderer only, template-based + * ones may (and probably will) completely ignore this + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 3.0 + * @deprecated Please use the templates rather than add raw HTML via this element + */ +class HTML_QuickForm_html extends HTML_QuickForm_static +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $text raw HTML to add + * @access public + * @return void + */ + function HTML_QuickForm_html($text = null) + { + $this->HTML_QuickForm_static(null, null, $text); + $this->_type = 'html'; + } + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object (only works with Default renderer!) + * @access public + * @return void + */ + function accept(&$renderer) + { + $renderer->renderHtml($this); + } // end func accept + + // }}} + +} //end class HTML_QuickForm_html +?> diff --git a/lib/Pear/HTML/QuickForm/image.php b/lib/Pear/HTML/QuickForm/image.php new file mode 100644 index 0000000..ddf8a06 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/image.php @@ -0,0 +1,127 @@ + element + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: image.php,v 1.5 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for an element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_image extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Element name attribute + * @param string $src (optional)Image source + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_image($elementName=null, $src='', $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setType('image'); + $this->setSource($src); + } // end class constructor + + // }}} + // {{{ setSource() + + /** + * Sets source for image element + * + * @param string $src source for image element + * @since 1.0 + * @access public + * @return void + */ + function setSource($src) + { + $this->updateAttributes(array('src' => $src)); + } // end func setSource + + // }}} + // {{{ setBorder() + + /** + * Sets border size for image element + * + * @param string $border border for image element + * @since 1.0 + * @access public + * @return void + */ + function setBorder($border) + { + $this->updateAttributes(array('border' => $border)); + } // end func setBorder + + // }}} + // {{{ setAlign() + + /** + * Sets alignment for image element + * + * @param string $align alignment for image element + * @since 1.0 + * @access public + * @return void + */ + function setAlign($align) + { + $this->updateAttributes(array('align' => $align)); + } // end func setAlign + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + +} // end class HTML_QuickForm_image +?> diff --git a/lib/Pear/HTML/QuickForm/input.php b/lib/Pear/HTML/QuickForm/input.php new file mode 100644 index 0000000..9f699ab --- /dev/null +++ b/lib/Pear/HTML/QuickForm/input.php @@ -0,0 +1,209 @@ + form elements + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: input.php,v 1.9 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/element.php'; + +/** + * Base class for form elements + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + * @abstract + */ +class HTML_QuickForm_input extends HTML_QuickForm_element +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param mixed Label(s) for the input field + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_input($elementName=null, $elementLabel=null, $attributes=null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + } //end constructor + + // }}} + // {{{ setType() + + /** + * Sets the element type + * + * @param string $type Element type + * @since 1.0 + * @access public + * @return void + */ + function setType($type) + { + $this->_type = $type; + $this->updateAttributes(array('type'=>$type)); + } // end func setType + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param string $value Default value of the form element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->updateAttributes(array('value'=>$value)); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return string + */ + function getValue() + { + return $this->getAttribute('value'); + } // end func getValue + + // }}} + // {{{ toHtml() + + /** + * Returns the input field in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + return $this->_getTabs() . '_getAttrString($this->_attributes) . ' />'; + } + } //end func toHtml + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + * @throws + */ + function onQuickFormEvent($event, $arg, &$caller) + { + // do not use submit values for button-type elements + $type = $this->getType(); + if (('updateValue' != $event) || + ('submit' != $type && 'reset' != $type && 'image' != $type && 'button' != $type)) { + parent::onQuickFormEvent($event, $arg, $caller); + } else { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + if (null !== $value) { + $this->setValue($value); + } + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ exportValue() + + /** + * We don't need values from button-type elements (except submit) and files + */ + function exportValue(&$submitValues, $assoc = false) + { + $type = $this->getType(); + if ('reset' == $type || 'image' == $type || 'button' == $type || 'file' == $type) { + return null; + } else { + return parent::exportValue($submitValues, $assoc); + } + } + + // }}} +} // end class HTML_QuickForm_element +?> diff --git a/lib/Pear/HTML/QuickForm/link.php b/lib/Pear/HTML/QuickForm/link.php new file mode 100644 index 0000000..e641738 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/link.php @@ -0,0 +1,200 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: link.php,v 1.3 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * HTML class for static data + */ +require_once 'HTML/QuickForm/static.php'; + +/** + * HTML class for a link type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 2.0 + */ +class HTML_QuickForm_link extends HTML_QuickForm_static +{ + // {{{ properties + + /** + * Link display text + * @var string + * @since 1.0 + * @access private + */ + var $_text = ""; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementLabel (optional)Link label + * @param string $href (optional)Link href + * @param string $text (optional)Link display text + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + * @throws + */ + function HTML_QuickForm_link($elementName=null, $elementLabel=null, $href=null, $text=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = false; + $this->_type = 'link'; + $this->setHref($href); + $this->_text = $text; + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + * @throws + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets value for textarea element + * + * @param string $value Value for password element + * @since 1.0 + * @access public + * @return void + * @throws + */ + function setValue($value) + { + return; + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return void + * @throws + */ + function getValue() + { + return; + } // end func getValue + + + // }}} + // {{{ setHref() + + /** + * Sets the links href + * + * @param string $href + * @since 1.0 + * @access public + * @return void + * @throws + */ + function setHref($href) + { + $this->updateAttributes(array('href'=>$href)); + } // end func setHref + + // }}} + // {{{ toHtml() + + /** + * Returns the textarea element in HTML + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function toHtml() + { + $tabs = $this->_getTabs(); + $html = "$tabs_getAttrString($this->_attributes).">"; + $html .= $this->_text; + $html .= ""; + return $html; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags (in this case, value is changed to a mask) + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function getFrozenHtml() + { + return; + } //end func getFrozenHtml + + // }}} + +} //end class HTML_QuickForm_textarea +?> diff --git a/lib/Pear/HTML/QuickForm/password.php b/lib/Pear/HTML/QuickForm/password.php new file mode 100644 index 0000000..047d827 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/password.php @@ -0,0 +1,115 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: password.php,v 1.7 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a password type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_password extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field label + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + * @throws + */ + function HTML_QuickForm_password($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->setType('password'); + } //end constructor + + // }}} + // {{{ setSize() + + /** + * Sets size of password element + * + * @param string $size Size of password field + * @since 1.0 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size'=>$size)); + } //end func setSize + + // }}} + // {{{ setMaxlength() + + /** + * Sets maxlength of password element + * + * @param string $maxlength Maximum length of password field + * @since 1.0 + * @access public + * @return void + */ + function setMaxlength($maxlength) + { + $this->updateAttributes(array('maxlength'=>$maxlength)); + } //end func setMaxlength + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags (in this case, value is changed to a mask) + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function getFrozenHtml() + { + $value = $this->getValue(); + return ('' != $value? '**********': ' ') . + $this->_getPersistantData(); + } //end func getFrozenHtml + + // }}} + +} //end class HTML_QuickForm_password +?> diff --git a/lib/Pear/HTML/QuickForm/radio.php b/lib/Pear/HTML/QuickForm/radio.php new file mode 100644 index 0000000..814cd86 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/radio.php @@ -0,0 +1,251 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: radio.php,v 1.19 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a radio type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_radio extends HTML_QuickForm_input +{ + // {{{ properties + + /** + * Radio display text + * @var string + * @since 1.1 + * @access private + */ + var $_text = ''; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param mixed Label(s) for a field + * @param string Text to display near the radio + * @param string Input field value + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_radio($elementName=null, $elementLabel=null, $text=null, $value=null, $attributes=null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + if (isset($value)) { + $this->setValue($value); + } + $this->_persistantFreeze = true; + $this->setType('radio'); + $this->_text = $text; + $this->_generateId(); + } //end constructor + + // }}} + // {{{ setChecked() + + /** + * Sets whether radio button is checked + * + * @param bool $checked Whether the field is checked or not + * @since 1.0 + * @access public + * @return void + */ + function setChecked($checked) + { + if (!$checked) { + $this->removeAttribute('checked'); + } else { + $this->updateAttributes(array('checked'=>'checked')); + } + } //end func setChecked + + // }}} + // {{{ getChecked() + + /** + * Returns whether radio button is checked + * + * @since 1.0 + * @access public + * @return string + */ + function getChecked() + { + return $this->getAttribute('checked'); + } //end func getChecked + + // }}} + // {{{ toHtml() + + /** + * Returns the radio element in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if (0 == strlen($this->_text)) { + $label = ''; + } elseif ($this->_flagFrozen) { + $label = $this->_text; + } else { + $label = ''; + } + return HTML_QuickForm_input::toHtml() . $label; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + if ($this->getChecked()) { + return '(x)' . + $this->_getPersistantData(); + } else { + return '( )'; + } + } //end func getFrozenHtml + + // }}} + // {{{ setText() + + /** + * Sets the radio text + * + * @param string $text Text to display near the radio button + * @since 1.1 + * @access public + * @return void + */ + function setText($text) + { + $this->_text = $text; + } //end func setText + + // }}} + // {{{ getText() + + /** + * Returns the radio text + * + * @since 1.1 + * @access public + * @return string + */ + function getText() + { + return $this->_text; + } //end func getText + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + // constant values override both default and submitted ones + // default values are overriden by submitted + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (!is_null($value) && $value == $this->getValue()) { + $this->setChecked(true); + } else { + $this->setChecked(false); + } + break; + case 'setGroupValue': + if ($arg == $this->getValue()) { + $this->setChecked(true); + } else { + $this->setChecked(false); + } + break; + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormLoad + + // }}} + // {{{ exportValue() + + /** + * Returns the value attribute if the radio is checked, null if it is not + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (null === $value) { + $value = $this->getChecked()? $this->getValue(): null; + } elseif ($value != $this->getValue()) { + $value = null; + } + return $this->_prepareValue($value, $assoc); + } + + // }}} +} //end class HTML_QuickForm_radio +?> diff --git a/lib/Pear/HTML/QuickForm/reset.php b/lib/Pear/HTML/QuickForm/reset.php new file mode 100644 index 0000000..92369d7 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/reset.php @@ -0,0 +1,79 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: reset.php,v 1.5 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a reset type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_reset extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $value (optional)Input field value + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_reset($elementName=null, $value=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setValue($value); + $this->setType('reset'); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + +} //end class HTML_QuickForm_reset +?> diff --git a/lib/Pear/HTML/QuickForm/select.php b/lib/Pear/HTML/QuickForm/select.php new file mode 100644 index 0000000..a12baa2 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/select.php @@ -0,0 +1,614 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: select.php,v 1.33 2007/06/03 15:01:00 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/element.php'; + +/** + * Class to dynamically create an HTML SELECT + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_select extends HTML_QuickForm_element { + + // {{{ properties + + /** + * Contains the select options + * + * @var array + * @since 1.0 + * @access private + */ + var $_options = array(); + + /** + * Default values of the SELECT + * + * @var string + * @since 1.0 + * @access private + */ + var $_values = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Select name attribute + * @param mixed Label(s) for the select + * @param mixed Data to be used to populate options + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_select($elementName=null, $elementLabel=null, $options=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'select'; + if (isset($options)) { + $this->load($options); + } + } //end constructor + + // }}} + // {{{ apiVersion() + + /** + * Returns the current API version + * + * @since 1.0 + * @access public + * @return double + */ + function apiVersion() + { + return 2.3; + } //end func apiVersion + + // }}} + // {{{ setSelected() + + /** + * Sets the default values of the select box + * + * @param mixed $values Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return void + */ + function setSelected($values) + { + if (is_string($values) && $this->getMultiple()) { + $values = split("[ ]?,[ ]?", $values); + } + if (is_array($values)) { + $this->_values = array_values($values); + } else { + $this->_values = array($values); + } + } //end func setSelected + + // }}} + // {{{ getSelected() + + /** + * Returns an array of the selected values + * + * @since 1.0 + * @access public + * @return array of selected values + */ + function getSelected() + { + return $this->_values; + } // end func getSelected + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name' => $name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ getPrivateName() + + /** + * Returns the element name (possibly with brackets appended) + * + * @since 1.0 + * @access public + * @return string + */ + function getPrivateName() + { + if ($this->getAttribute('multiple')) { + return $this->getName() . '[]'; + } else { + return $this->getName(); + } + } //end func getPrivateName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param mixed $values Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->setSelected($value); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns an array of the selected values + * + * @since 1.0 + * @access public + * @return array of selected values + */ + function getValue() + { + return $this->_values; + } // end func getValue + + // }}} + // {{{ setSize() + + /** + * Sets the select field size, only applies to 'multiple' selects + * + * @param int $size Size of select field + * @since 1.0 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size' => $size)); + } //end func setSize + + // }}} + // {{{ getSize() + + /** + * Returns the select field size + * + * @since 1.0 + * @access public + * @return int + */ + function getSize() + { + return $this->getAttribute('size'); + } //end func getSize + + // }}} + // {{{ setMultiple() + + /** + * Sets the select mutiple attribute + * + * @param bool $multiple Whether the select supports multi-selections + * @since 1.2 + * @access public + * @return void + */ + function setMultiple($multiple) + { + if ($multiple) { + $this->updateAttributes(array('multiple' => 'multiple')); + } else { + $this->removeAttribute('multiple'); + } + } //end func setMultiple + + // }}} + // {{{ getMultiple() + + /** + * Returns the select mutiple attribute + * + * @since 1.2 + * @access public + * @return bool true if multiple select, false otherwise + */ + function getMultiple() + { + return (bool)$this->getAttribute('multiple'); + } //end func getMultiple + + // }}} + // {{{ addOption() + + /** + * Adds a new OPTION to the SELECT + * + * @param string $text Display text for the OPTION + * @param string $value Value for the OPTION + * @param mixed $attributes Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function addOption($text, $value, $attributes=null) + { + if (null === $attributes) { + $attributes = array('value' => (string)$value); + } else { + $attributes = $this->_parseAttributes($attributes); + if (isset($attributes['selected'])) { + // the 'selected' attribute will be set in toHtml() + $this->_removeAttr('selected', $attributes); + if (is_null($this->_values)) { + $this->_values = array($value); + } elseif (!in_array($value, $this->_values)) { + $this->_values[] = $value; + } + } + $this->_updateAttrArray($attributes, array('value' => (string)$value)); + } + $this->_options[] = array('text' => $text, 'attr' => $attributes); + } // end func addOption + + // }}} + // {{{ loadArray() + + /** + * Loads the options from an associative array + * + * @param array $arr Associative array of options + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function loadArray($arr, $values=null) + { + if (!is_array($arr)) { + return PEAR::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array'); + } + if (isset($values)) { + $this->setSelected($values); + } + foreach ($arr as $key => $val) { + // Warning: new API since release 2.3 + $this->addOption($val, $key); + } + return true; + } // end func loadArray + + // }}} + // {{{ loadDbResult() + + /** + * Loads the options from DB_result object + * + * If no column names are specified the first two columns of the result are + * used as the text and value columns respectively + * @param object $result DB_result object + * @param string $textCol (optional) Name of column to display as the OPTION text + * @param string $valueCol (optional) Name of column to use as the OPTION value + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function loadDbResult(&$result, $textCol=null, $valueCol=null, $values=null) + { + if (!is_object($result) || !is_a($result, 'db_result')) { + return PEAR::raiseError('Argument 1 of HTML_Select::loadDbResult is not a valid DB_result'); + } + if (isset($values)) { + $this->setValue($values); + } + $fetchMode = ($textCol && $valueCol) ? DB_FETCHMODE_ASSOC : DB_FETCHMODE_ORDERED; + while (is_array($row = $result->fetchRow($fetchMode)) ) { + if ($fetchMode == DB_FETCHMODE_ASSOC) { + $this->addOption($row[$textCol], $row[$valueCol]); + } else { + $this->addOption($row[0], $row[1]); + } + } + return true; + } // end func loadDbResult + + // }}} + // {{{ loadQuery() + + /** + * Queries a database and loads the options from the results + * + * @param mixed $conn Either an existing DB connection or a valid dsn + * @param string $sql SQL query string + * @param string $textCol (optional) Name of column to display as the OPTION text + * @param string $valueCol (optional) Name of column to use as the OPTION value + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.1 + * @access public + * @return void + * @throws PEAR_Error + */ + function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null) + { + if (is_string($conn)) { + require_once('DB.php'); + $dbConn = &DB::connect($conn, true); + if (DB::isError($dbConn)) { + return $dbConn; + } + } elseif (is_subclass_of($conn, "db_common")) { + $dbConn = &$conn; + } else { + return PEAR::raiseError('Argument 1 of HTML_Select::loadQuery is not a valid type'); + } + $result = $dbConn->query($sql); + if (DB::isError($result)) { + return $result; + } + $this->loadDbResult($result, $textCol, $valueCol, $values); + $result->free(); + if (is_string($conn)) { + $dbConn->disconnect(); + } + return true; + } // end func loadQuery + + // }}} + // {{{ load() + + /** + * Loads options from different types of data sources + * + * This method is a simulated overloaded method. The arguments, other than the + * first are optional and only mean something depending on the type of the first argument. + * If the first argument is an array then all arguments are passed in order to loadArray. + * If the first argument is a db_result then all arguments are passed in order to loadDbResult. + * If the first argument is a string or a DB connection then all arguments are + * passed in order to loadQuery. + * @param mixed $options Options source currently supports assoc array or DB_result + * @param mixed $param1 (optional) See function detail + * @param mixed $param2 (optional) See function detail + * @param mixed $param3 (optional) See function detail + * @param mixed $param4 (optional) See function detail + * @since 1.1 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function load(&$options, $param1=null, $param2=null, $param3=null, $param4=null) + { + switch (true) { + case is_array($options): + return $this->loadArray($options, $param1); + break; + case (is_a($options, 'db_result')): + return $this->loadDbResult($options, $param1, $param2, $param3); + break; + case (is_string($options) && !empty($options) || is_subclass_of($options, "db_common")): + return $this->loadQuery($options, $param1, $param2, $param3, $param4); + break; + } + } // end func load + + // }}} + // {{{ toHtml() + + /** + * Returns the SELECT in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + $tabs = $this->_getTabs(); + $strHtml = ''; + + if ($this->getComment() != '') { + $strHtml .= $tabs . '\n"; + } + + if (!$this->getMultiple()) { + $attrString = $this->_getAttrString($this->_attributes); + } else { + $myName = $this->getName(); + $this->setName($myName . '[]'); + $attrString = $this->_getAttrString($this->_attributes); + $this->setName($myName); + } + $strHtml .= $tabs . '\n"; + + $strValues = is_array($this->_values)? array_map('strval', $this->_values): array(); + foreach ($this->_options as $option) { + if (!empty($strValues) && in_array($option['attr']['value'], $strValues, true)) { + $option['attr']['selected'] = 'selected'; + } + $strHtml .= $tabs . "\t_getAttrString($option['attr']) . '>' . + $option['text'] . "\n"; + } + + return $strHtml . $tabs . ''; + } + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = array(); + if (is_array($this->_values)) { + foreach ($this->_values as $key => $val) { + for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { + if (0 == strcmp($val, $this->_options[$i]['attr']['value'])) { + $value[$key] = $this->_options[$i]['text']; + break; + } + } + } + } + $html = empty($value)? ' ': join('
', $value); + if ($this->_persistantFreeze) { + $name = $this->getPrivateName(); + // Only use id attribute if doing single hidden input + if (1 == count($value)) { + $id = $this->getAttribute('id'); + $idAttr = isset($id)? array('id' => $id): array(); + } else { + $idAttr = array(); + } + foreach ($value as $key => $item) { + $html .= '_getAttrString(array( + 'type' => 'hidden', + 'name' => $name, + 'value' => $this->_values[$key] + ) + $idAttr) . ' />'; + } + } + return $html; + } //end func getFrozenHtml + + // }}} + // {{{ exportValue() + + /** + * We check the options and return only the values that _could_ have been + * selected. We also return a scalar value if select is not "multiple" + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (is_null($value)) { + $value = $this->getValue(); + } elseif(!is_array($value)) { + $value = array($value); + } + if (is_array($value) && !empty($this->_options)) { + $cleanValue = null; + foreach ($value as $v) { + for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { + if (0 == strcmp($v, $this->_options[$i]['attr']['value'])) { + $cleanValue[] = $v; + break; + } + } + } + } else { + $cleanValue = $value; + } + if (is_array($cleanValue) && !$this->getMultiple()) { + return $this->_prepareValue($cleanValue[0], $assoc); + } else { + return $this->_prepareValue($cleanValue, $assoc); + } + } + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + // Fix for bug #4465 & #5269 + // XXX: should we push this to element::onQuickFormEvent()? + if (null === $value && (!$caller->isSubmitted() || !$this->getMultiple())) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value) { + $this->setValue($value); + } + return true; + } else { + return parent::onQuickFormEvent($event, $arg, $caller); + } + } + + // }}} +} //end class HTML_QuickForm_select +?> diff --git a/lib/Pear/HTML/QuickForm/static.php b/lib/Pear/HTML/QuickForm/static.php new file mode 100644 index 0000000..fdc769e --- /dev/null +++ b/lib/Pear/HTML/QuickForm/static.php @@ -0,0 +1,201 @@ + + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: static.php,v 1.7 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/element.php'; + +/** + * HTML class for static data + * + * @category HTML + * @package HTML_QuickForm + * @author Wojciech Gdela + * @version Release: 3.2.10 + * @since 2.7 + */ +class HTML_QuickForm_static extends HTML_QuickForm_element { + + // {{{ properties + + /** + * Display text + * @var string + * @access private + */ + var $_text = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementLabel (optional)Label + * @param string $text (optional)Display text + * @access public + * @return void + */ + function HTML_QuickForm_static($elementName=null, $elementLabel=null, $text=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel); + $this->_persistantFreeze = false; + $this->_type = 'static'; + $this->_text = $text; + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the element name + * + * @param string $name Element name + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setText() + + /** + * Sets the text + * + * @param string $text + * @access public + * @return void + */ + function setText($text) + { + $this->_text = $text; + } // end func setText + + // }}} + // {{{ setValue() + + /** + * Sets the text (uses the standard setValue call to emulate a form element. + * + * @param string $text + * @access public + * @return void + */ + function setValue($text) + { + $this->setText($text); + } // end func setValue + + // }}} + // {{{ toHtml() + + /** + * Returns the static text element in HTML + * + * @access public + * @return string + */ + function toHtml() + { + return $this->_getTabs() . $this->_text; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @access public + * @return string + */ + function getFrozenHtml() + { + return $this->toHtml(); + } //end func getFrozenHtml + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + * @throws + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + // do NOT use submitted values for static elements + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + if (null !== $value) { + $this->setValue($value); + } + break; + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ exportValue() + + /** + * We override this here because we don't want any values from static elements + */ + function exportValue(&$submitValues, $assoc = false) + { + return null; + } + + // }}} +} //end class HTML_QuickForm_static +?> diff --git a/lib/Pear/HTML/QuickForm/submit.php b/lib/Pear/HTML/QuickForm/submit.php new file mode 100644 index 0000000..9355a12 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/submit.php @@ -0,0 +1,89 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: submit.php,v 1.5 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a submit type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_submit extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param string Input field value + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_submit($elementName=null, $value=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setValue($value); + $this->setType('submit'); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + // {{{ exportValue() + + /** + * Only return the value if it is found within $submitValues (i.e. if + * this particular submit button was clicked) + */ + function exportValue(&$submitValues, $assoc = false) + { + return $this->_prepareValue($this->_findValue($submitValues), $assoc); + } + + // }}} +} //end class HTML_QuickForm_submit +?> diff --git a/lib/Pear/HTML/QuickForm/text.php b/lib/Pear/HTML/QuickForm/text.php new file mode 100644 index 0000000..f72855d --- /dev/null +++ b/lib/Pear/HTML/QuickForm/text.php @@ -0,0 +1,98 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: text.php,v 1.6 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/input.php'; + +/** + * HTML class for a text field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_text extends HTML_QuickForm_input +{ + + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field label + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_text($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->setType('text'); + } //end constructor + + // }}} + // {{{ setSize() + + /** + * Sets size of text field + * + * @param string $size Size of text field + * @since 1.3 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size'=>$size)); + } //end func setSize + + // }}} + // {{{ setMaxlength() + + /** + * Sets maxlength of text field + * + * @param string $maxlength Maximum length of text field + * @since 1.3 + * @access public + * @return void + */ + function setMaxlength($maxlength) + { + $this->updateAttributes(array('maxlength'=>$maxlength)); + } //end func setMaxlength + + // }}} + +} //end class HTML_QuickForm_text +?> diff --git a/lib/Pear/HTML/QuickForm/textarea.php b/lib/Pear/HTML/QuickForm/textarea.php new file mode 100644 index 0000000..07db9de --- /dev/null +++ b/lib/Pear/HTML/QuickForm/textarea.php @@ -0,0 +1,229 @@ + + * @author Bertrand Mansion + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: textarea.php,v 1.12 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/element.php'; + +/** + * HTML class for a textarea type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.10 + * @since 1.0 + */ +class HTML_QuickForm_textarea extends HTML_QuickForm_element +{ + // {{{ properties + + /** + * Field value + * @var string + * @since 1.0 + * @access private + */ + var $_value = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param mixed Label(s) for a field + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_textarea($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'textarea'; + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets value for textarea element + * + * @param string $value Value for textarea element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->_value = $value; + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return string + */ + function getValue() + { + return $this->_value; + } // end func getValue + + // }}} + // {{{ setWrap() + + /** + * Sets wrap type for textarea element + * + * @param string $wrap Wrap type + * @since 1.0 + * @access public + * @return void + */ + function setWrap($wrap) + { + $this->updateAttributes(array('wrap' => $wrap)); + } //end func setWrap + + // }}} + // {{{ setRows() + + /** + * Sets height in rows for textarea element + * + * @param string $rows Height expressed in rows + * @since 1.0 + * @access public + * @return void + */ + function setRows($rows) + { + $this->updateAttributes(array('rows' => $rows)); + } //end func setRows + + // }}} + // {{{ setCols() + + /** + * Sets width in cols for textarea element + * + * @param string $cols Width expressed in cols + * @since 1.0 + * @access public + * @return void + */ + function setCols($cols) + { + $this->updateAttributes(array('cols' => $cols)); + } //end func setCols + + // }}} + // {{{ toHtml() + + /** + * Returns the textarea element in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + return $this->_getTabs() . + '_getAttrString($this->_attributes) . '>' . + // because we wrap the form later we don't want the text indented + preg_replace("/(\r\n|\n|\r)/", ' ', htmlspecialchars($this->_value)) . + ''; + } + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags (in this case, value is changed to a mask) + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = htmlspecialchars($this->getValue()); + if ($this->getAttribute('wrap') == 'off') { + $html = $this->_getTabs() . '
' . $value."
\n"; + } else { + $html = nl2br($value)."\n"; + } + return $html . $this->_getPersistantData(); + } //end func getFrozenHtml + + // }}} + +} //end class HTML_QuickForm_textarea +?> diff --git a/lib/Pear/HTML/QuickForm/xbutton.php b/lib/Pear/HTML/QuickForm/xbutton.php new file mode 100644 index 0000000..d53f1e6 --- /dev/null +++ b/lib/Pear/HTML/QuickForm/xbutton.php @@ -0,0 +1,153 @@ + element + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @copyright 2001-2007 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: xbutton.php,v 1.2 2007/05/29 18:34:36 avb Exp $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once 'HTML/QuickForm/element.php'; + +/** + * Class for HTML 4.0 tags) + * @param mixed Either a typical HTML attribute string or an associative array + * @access public + */ + function HTML_QuickForm_xbutton($elementName = null, $elementContent = null, $attributes = null) + { + $this->HTML_QuickForm_element($elementName, null, $attributes); + $this->setContent($elementContent); + $this->setPersistantFreeze(false); + $this->_type = 'xbutton'; + } + + + function toHtml() + { + return 'getAttributes(true) . '>' . $this->_content . ''; + } + + + function getFrozenHtml() + { + return $this->toHtml(); + } + + + function freeze() + { + return false; + } + + + function setName($name) + { + $this->updateAttributes(array( + 'name' => $name + )); + } + + + function getName() + { + return $this->getAttribute('name'); + } + + + function setValue($value) + { + $this->updateAttributes(array( + 'value' => $value + )); + } + + + function getValue() + { + return $this->getAttribute('value'); + } + + + /** + * Sets the contents of the button element + * + * @param string Button content (HTML to add between tags) + */ + function setContent($content) + { + $this->_content = $content; + } + + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' != $event) { + return parent::onQuickFormEvent($event, $arg, $caller); + } else { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + if (null !== $value) { + $this->setValue($value); + } + } + return true; + } + + + /** + * Returns a 'safe' element's value + * + * The value is only returned if the button's type is "submit" and if this + * particlular button was clicked + */ + function exportValue(&$submitValues, $assoc = false) + { + if ('submit' == $this->getAttribute('type')) { + return $this->_prepareValue($this->_findValue($submitValues), $assoc); + } else { + return null; + } + } +} +?> diff --git a/lib/Pear/HTML/Table.php b/lib/Pear/HTML/Table.php new file mode 100644 index 0000000..4517815 --- /dev/null +++ b/lib/Pear/HTML/Table.php @@ -0,0 +1,1037 @@ +, + * Bertrand Mansion , + * Mark Wiesemann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * + * @category HTML + * @package HTML_Table + * @author Adam Daniel + * @author Bertrand Mansion + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Table.php,v 1.39 2007/06/25 16:44:43 wiesemann Exp $ + * @link http://pear.php.net/package/HTML_Table + */ + + +/** +* Requires PEAR, HTML_Common and HTML_Table_Storage +*/ +require_once 'PEAR.php'; +require_once 'HTML/Common.php'; +require_once 'HTML/Table/Storage.php'; + +/** + * PEAR::HTML_Table makes the design of HTML tables easy, flexible, reusable and efficient. + * + * The PEAR::HTML_Table package provides methods for easy and efficient design + * of HTML tables. + * - Lots of customization options. + * - Tables can be modified at any time. + * - The logic is the same as standard HTML editors. + * - Handles col and rowspans. + * - PHP code is shorter, easier to read and to maintain. + * - Tables options can be reused. + * + * For auto filling of data and such then check out + * http://pear.php.net/package/HTML_Table_Matrix + * + * @category HTML + * @package HTML_Table + * @author Adam Daniel + * @author Bertrand Mansion + * @copyright 2005-2006 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/HTML_Table + */ +class HTML_Table extends HTML_Common { + + /** + * Value to insert into empty cells. This is used as a default for + * newly-created tbodies. + * @var string + * @access private + */ + var $_autoFill = ' '; + + /** + * Automatically adds a new row, column, or body if a given row, column, or + * body index does not exist. + * This is used as a default for newly-created tbodies. + * @var bool + * @access private + */ + var $_autoGrow = true; + + /** + * Array containing the table caption + * @var array + * @access private + */ + var $_caption = array(); + + /** + * Array containing the table column group specifications + * + * @var array + * @author Laurent Laville (pear at laurent-laville dot org) + * @access private + */ + var $_colgroup = array(); + + /** + * HTML_Table_Storage object for the (t)head of the table + * @var object + * @access private + */ + var $_thead = null; + + /** + * HTML_Table_Storage object for the (t)foot of the table + * @var object + * @access private + */ + var $_tfoot = null; + + /** + * HTML_Table_Storage object for the (t)body of the table + * @var object + * @access private + */ + var $_tbodies = array(); + + /** + * Number of bodies in the table + * @var int + * @access private + */ + var $_tbodyCount = 0; + + /** + * Whether to use , and or not + * @var bool + * @access private + */ + var $_useTGroups = false; + + /** + * Class constructor + * @param array $attributes Associative array of table tag + * attributes + * @param int $tabOffset Tab offset of the table + * @param bool $useTGroups Whether to use , and + * or not + * @access public + */ + function HTML_Table($attributes = null, $tabOffset = 0, $useTGroups = false) + { + HTML_Common::HTML_Common($attributes, (int)$tabOffset); + $this->_useTGroups = (boolean)$useTGroups; + $this->addBody(); + if ($this->_useTGroups) { + $this->_thead =& new HTML_Table_Storage($tabOffset, $this->_useTGroups); + $this->_tfoot =& new HTML_Table_Storage($tabOffset, $this->_useTGroups); + } + } + + /** + * Returns the API version + * @access public + * @return double + * @deprecated + */ + function apiVersion() + { + return 1.7; + } + + /** + * Returns the HTML_Table_Storage object for + * @access public + * @return object + */ + function &getHeader() + { + if (is_null($this->_thead)) { + $this->_useTGroups = true; + $this->_thead =& new HTML_Table_Storage($this->_tabOffset, + $this->_useTGroups); + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setUseTGroups(true); + } + } + return $this->_thead; + } + + /** + * Returns the HTML_Table_Storage object for + * @access public + * @return object + */ + function &getFooter() + { + if (is_null($this->_tfoot)) { + $this->_useTGroups = true; + $this->_tfoot =& new HTML_Table_Storage($this->_tabOffset, + $this->_useTGroups); + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setUseTGroups(true); + } + } + return $this->_tfoot; + } + + /** + * Returns the HTML_Table_Storage object for the specified + * (or the whole table if is not used) + * @param int $body (optional) The index of the body to + * return. + * @access public + * @return object + * @throws PEAR_Error + */ + function &getBody($body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'getBody'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]; + } + + /** + * Adds a table body and returns the body identifier + * @param mixed $attributes (optional) Associative array or + * string of table body attributes + * @access public + * @return int + */ + function addBody($attributes = null) + { + if (!$this->_useTGroups && $this->_tbodyCount > 0) { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setUseTGroups(true); + } + $this->_useTGroups = true; + } + + $body = $this->_tbodyCount++; + $this->_tbodies[$body] =& new HTML_Table_Storage($this->_tabOffset, + $this->_useTGroups); + $this->_tbodies[$body]->setAutoFill($this->_autoFill); + $this->_tbodies[$body]->setAttributes($attributes); + return $body; + } + + /** + * Adjusts the number of bodies + * @param int $body Body index + * @param string $method Name of calling method + * @access private + * @throws PEAR_Error + */ + function _adjustTbodyCount($body, $method) + { + if ($this->_autoGrow) { + while ($this->_tbodyCount <= (int)$body) { + $this->addBody(); + } + } else { + return PEAR::raiseError('Invalid body reference[' . + $body . '] in HTML_Table::' . $method); + } + } + + /** + * Sets the table caption + * @param string $caption + * @param mixed $attributes Associative array or string of + * table row attributes + * @access public + */ + function setCaption($caption, $attributes = null) + { + $attributes = $this->_parseAttributes($attributes); + $this->_caption = array('attr' => $attributes, 'contents' => $caption); + } + + /** + * Sets the table columns group specifications, or removes existing ones. + * + * @param mixed $colgroup (optional) Columns attributes + * @param mixed $attributes (optional) Associative array or string + * of table row attributes + * @author Laurent Laville (pear at laurent-laville dot org) + * @access public + */ + function setColGroup($colgroup = null, $attributes = null) + { + if (isset($colgroup)) { + $attributes = $this->_parseAttributes($attributes); + $this->_colgroup[] = array('attr' => $attributes, + 'contents' => $colgroup); + } else { + $this->_colgroup = array(); + } + } + + /** + * Sets the autoFill value + * @param mixed $fill Whether autoFill should be enabled or not + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function setAutoFill($fill, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'setAutoFill'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setAutoFill($fill); + } else { + $this->_autoFill = $fill; + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setAutoFill($fill); + } + } + } + + /** + * Returns the autoFill value + * @param int $body (optional) The index of the body to get. + * Pass null to get the default for new bodies. + * @access public + * @return mixed + * @throws PEAR_Error + */ + function getAutoFill($body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'getAutoFill'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getAutoFill(); + } else { + return $this->_autoFill; + } + } + + /** + * Sets the autoGrow value + * @param bool $grow Whether autoGrow should be enabled or not + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function setAutoGrow($grow, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'setAutoGrow'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setAutoGrow($grow); + } else { + $this->_autoGrow = $grow; + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setAutoGrow($grow); + } + } + } + + /** + * Returns the autoGrow value + * @param int $body (optional) The index of the body to get. + * Pass null to get the default for new bodies. + * @access public + * @return mixed + * @throws PEAR_Error + */ + function getAutoGrow($body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'getAutoGrow'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getAutoGrow(); + } else { + return $this->_autoGrow; + } + } + + /** + * Sets the number of rows in the table body + * @param int $rows The number of rows + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setRowCount($rows, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setRowCount'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setRowCount($rows); + } + + /** + * Sets the number of columns in the table + * @param int $cols The number of columns + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setColCount($cols, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setColCount'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setColCount($cols); + } + + /** + * Returns the number of rows in the table + * @param int $body (optional) The index of the body to get. + * Pass null to get the total number of + * rows in all bodies. + * @access public + * @return int + * @throws PEAR_Error + */ + function getRowCount($body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'getRowCount'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getRowCount(); + } else { + $rowCount = 0; + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $rowCount += $this->_tbodies[$i]->getRowCount(); + } + return $rowCount; + } + } + + /** + * Gets the number of columns in the table + * + * If a row index is specified, the count will not take + * the spanned cells into account in the return value. + * + * @param int $row Row index to serve for cols count + * @param int $body (optional) The index of the body to get. + * @access public + * @return int + * @throws PEAR_Error + */ + function getColCount($row = null, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'getColCount'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getColCount($row); + } + + /** + * Sets a rows type 'TH' or 'TD' + * @param int $row Row index + * @param string $type 'TH' or 'TD' + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setRowType($row, $type, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setRowType'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setRowType($row, $type); + } + + /** + * Sets a columns type 'TH' or 'TD' + * @param int $col Column index + * @param string $type 'TH' or 'TD' + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function setColType($col, $type, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'setColType'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setColType($col, $type); + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setColType($col, $type); + } + } + } + + /** + * Sets the cell attributes for an existing cell. + * + * If the given indices do not exist and autoGrow is true then the given + * row and/or col is automatically added. If autoGrow is false then an + * error is returned. + * @param int $row Row index + * @param int $col Column index + * @param mixed $attributes Associative array or string of + * table row attributes + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setCellAttributes($row, $col, $attributes, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setCellAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_tbodies[$body]->setCellAttributes($row, $col, $attributes); + if (PEAR::isError($ret)) { + return $ret; + } + } + + /** + * Updates the cell attributes passed but leaves other existing attributes + * intact + * @param int $row Row index + * @param int $col Column index + * @param mixed $attributes Associative array or string of table row + * attributes + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function updateCellAttributes($row, $col, $attributes, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'updateCellAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_tbodies[$body]->updateCellAttributes($row, $col, $attributes); + if (PEAR::isError($ret)) { + return $ret; + } + } + + /** + * Returns the attributes for a given cell + * @param int $row Row index + * @param int $col Column index + * @param int $body (optional) The index of the body to get. + * @return array + * @access public + * @throws PEAR_Error + */ + function getCellAttributes($row, $col, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'getCellAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getCellAttributes($row, $col); + } + + /** + * Sets the cell contents for an existing cell + * + * If the given indices do not exist and autoGrow is true then the given + * row and/or col is automatically added. If autoGrow is false then an + * error is returned. + * @param int $row Row index + * @param int $col Column index + * @param mixed $contents May contain html or any object with a + * toHTML() method; it is an array (with + * strings and/or objects), $col will be + * used as start offset and the array + * elements will be set to this and the + * following columns in $row + * @param string $type (optional) Cell type either 'TH' or 'TD' + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setCellContents($row, $col, $contents, $type = 'TD', $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setCellContents'); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_tbodies[$body]->setCellContents($row, $col, $contents, $type); + if (PEAR::isError($ret)) { + return $ret; + } + } + + /** + * Returns the cell contents for an existing cell + * @param int $row Row index + * @param int $col Column index + * @param int $body (optional) The index of the body to get. + * @access public + * @return mixed + * @throws PEAR_Error + */ + function getCellContents($row, $col, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'getCellContents'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getCellContents($row, $col); + } + + /** + * Sets the contents of a header cell + * @param int $row + * @param int $col + * @param mixed $contents + * @param mixed $attributes Associative array or string of + * table row attributes + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setHeaderContents($row, $col, $contents, $attributes = null, + $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setHeaderContents'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setHeaderContents($row, $col, $contents, $attributes); + } + + /** + * Adds a table row and returns the row identifier + * @param array $contents (optional) Must be a indexed array of + * valid cell contents + * @param mixed $attributes (optional) Associative array or string + * of table row attributes. This can also + * be an array of attributes, in which + * case the attributes will be repeated + * in a loop. + * @param string $type (optional) Cell type either 'th' or 'td' + * @param bool $inTR false if attributes are to be applied + * in TD tags; true if attributes are to + * ´be applied in TR tag + * @param int $body (optional) The index of the body to use. + * @return int + * @access public + * @throws PEAR_Error + */ + function addRow($contents = null, $attributes = null, $type = 'td', + $inTR = false, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'addRow'); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_tbodies[$body]->addRow($contents, $attributes, $type, $inTR); + return $ret; + } + + /** + * Sets the row attributes for an existing row + * @param int $row Row index + * @param mixed $attributes Associative array or string of table row + * attributes. This can also be an array of + * attributes, in which case the attributes + * will be repeated in a loop. + * @param bool $inTR false if attributes are to be applied in + * TD tags; true if attributes are to be + * applied in TR tag + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function setRowAttributes($row, $attributes, $inTR = false, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'setRowAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_tbodies[$body]->setRowAttributes($row, $attributes, $inTR); + if (PEAR::isError($ret)) { + return $ret; + } + } + + /** + * Updates the row attributes for an existing row + * @param int $row Row index + * @param mixed $attributes Associative array or string of table row + * attributes + * @param bool $inTR false if attributes are to be applied in + * TD tags; true if attributes are to be + * applied in TR tag + * @param int $body (optional) The index of the body to set. + * @access public + * @throws PEAR_Error + */ + function updateRowAttributes($row, $attributes = null, $inTR = false, + $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'updateRowAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_tbodies[$body]->updateRowAttributes($row, $attributes, $inTR); + if (PEAR::isError($ret)) { + return $ret; + } + } + + /** + * Returns the attributes for a given row as contained in the TR tag + * @param int $row Row index + * @param int $body (optional) The index of the body to get. + * @return array + * @access public + * @throws PEAR_Error + */ + function getRowAttributes($row, $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'getRowAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->getRowAttributes($row); + } + + /** + * Alternates the row attributes starting at $start + * @param int $start Row index of row in which alternating + * begins + * @param mixed $attributes1 Associative array or string of table + * row attributes + * @param mixed $attributes2 Associative array or string of table + * row attributes + * @param bool $inTR false if attributes are to be applied + * in TD tags; true if attributes are to + * be applied in TR tag + * @param int $firstAttributes (optional) Which attributes should be + * applied to the first row, 1 or 2. + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function altRowAttributes($start, $attributes1, $attributes2, $inTR = false, + $firstAttributes = 1, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'altRowAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->altRowAttributes($start, $attributes1, + $attributes2, $inTR, $firstAttributes); + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->altRowAttributes($start, $attributes1, + $attributes2, $inTR, $firstAttributes); + // if the tbody's row count is odd, toggle $firstAttributes to + // prevent the next tbody's first row from having the same + // attributes as this tbody's last row. + if ($this->_tbodies[$i]->getRowCount() % 2) { + $firstAttributes ^= 3; + } + } + } + } + + /** + * Adds a table column and returns the column identifier + * @param array $contents (optional) Must be a indexed array of + * valid cell contents + * @param mixed $attributes (optional) Associative array or string + * of table row attributes + * @param string $type (optional) Cell type either 'th' or 'td' + * @param int $body (optional) The index of the body to use. + * @return int + * @access public + * @throws PEAR_Error + */ + function addCol($contents = null, $attributes = null, $type = 'td', $body = 0) + { + $ret = $this->_adjustTbodyCount($body, 'addCol'); + if (PEAR::isError($ret)) { + return $ret; + } + return $this->_tbodies[$body]->addCol($contents, $attributes, $type); + } + + /** + * Sets the column attributes for an existing column + * @param int $col Column index + * @param mixed $attributes (optional) Associative array or string + * of table row attributes + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function setColAttributes($col, $attributes = null, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'setColAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setColAttributes($col, $attributes); + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setColAttributes($col, $attributes); + } + } + } + + /** + * Updates the column attributes for an existing column + * @param int $col Column index + * @param mixed $attributes (optional) Associative array or + * string of table row attributes + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function updateColAttributes($col, $attributes = null, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'updateColAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->updateColAttributes($col, $attributes); + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->updateColAttributes($col, $attributes); + } + } + } + + /** + * Sets the attributes for all cells + * @param mixed $attributes (optional) Associative array or + * string of table row attributes + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function setAllAttributes($attributes = null, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'setAllAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->setAllAttributes($attributes); + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setAllAttributes($attributes); + } + } + } + + /** + * Updates the attributes for all cells + * @param mixed $attributes (optional) Associative array or string + * of table row attributes + * @param int $body (optional) The index of the body to set. + * Pass null to set for all bodies. + * @access public + * @throws PEAR_Error + */ + function updateAllAttributes($attributes = null, $body = null) + { + if (!is_null($body)) { + $ret = $this->_adjustTbodyCount($body, 'updateAllAttributes'); + if (PEAR::isError($ret)) { + return $ret; + } + $this->_tbodies[$body]->updateAllAttributes($attributes); + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->updateAllAttributes($attributes); + } + } + } + + /** + * Returns the table structure as HTML + * @access public + * @return string + */ + function toHtml() + { + $strHtml = ''; + $tabs = $this->_getTabs(); + $tab = $this->_getTab(); + $lnEnd = $this->_getLineEnd(); + $tBodyColCounts = array(); + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $tBodyColCounts[] = $this->_tbodies[$i]->getColCount(); + } + $tBodyMaxColCount = 0; + if (count($tBodyColCounts) > 0) { + $tBodyMaxColCount = max($tBodyColCounts); + } + if ($this->_comment) { + $strHtml .= $tabs . "" . $lnEnd; + } + if ($this->getRowCount() > 0 && $tBodyMaxColCount > 0) { + $strHtml .= + $tabs . '_getAttrString($this->_attributes) . '>' . $lnEnd; + if (!empty($this->_caption)) { + $attr = $this->_caption['attr']; + $contents = $this->_caption['contents']; + $strHtml .= $tabs . $tab . '_getAttrString($attr) . '>'; + if (is_array($contents)) { + $contents = implode(', ', $contents); + } + $strHtml .= $contents; + $strHtml .= '' . $lnEnd; + } + if (!empty($this->_colgroup)) { + foreach ($this->_colgroup as $g => $col) { + $attr = $this->_colgroup[$g]['attr']; + $contents = $this->_colgroup[$g]['contents']; + $strHtml .= $tabs . $tab . '_getAttrString($attr) . '>'; + if (!empty($contents)) { + $strHtml .= $lnEnd; + if (!is_array($contents)) { + $contents = array($contents); + } + foreach ($contents as $a => $colAttr) { + $attr = $this->_parseAttributes($colAttr); + $strHtml .= $tabs . $tab . $tab . '_getAttrString($attr) . ' />' . $lnEnd; + } + $strHtml .= $tabs . $tab; + } + $strHtml .= '' . $lnEnd; + } + } + if ($this->_useTGroups) { + $tHeadColCount = 0; + if ($this->_thead !== null) { + $tHeadColCount = $this->_thead->getColCount(); + } + $tFootColCount = 0; + if ($this->_tfoot !== null) { + $tFootColCount = $this->_tfoot->getColCount(); + } + $maxColCount = max($tHeadColCount, $tFootColCount, $tBodyMaxColCount); + if ($this->_thead !== null) { + $this->_thead->setColCount($maxColCount); + if ($this->_thead->getRowCount() > 0) { + $strHtml .= $tabs . $tab . '_getAttrString($this->_thead->_attributes) . + '>' . $lnEnd; + $strHtml .= $this->_thead->toHtml($tabs, $tab); + $strHtml .= $tabs . $tab . '' . $lnEnd; + } + } + if ($this->_tfoot !== null) { + $this->_tfoot->setColCount($maxColCount); + if ($this->_tfoot->getRowCount() > 0) { + $strHtml .= $tabs . $tab . '_getAttrString($this->_tfoot->_attributes) . + '>' . $lnEnd; + $strHtml .= $this->_tfoot->toHtml($tabs, $tab); + $strHtml .= $tabs . $tab . '' . $lnEnd; + } + } + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $this->_tbodies[$i]->setColCount($maxColCount); + if ($this->_tbodies[$i]->getRowCount() > 0) { + $strHtml .= $tabs . $tab . '_getAttrString($this->_tbodies[$i]->_attributes) . + '>' . $lnEnd; + $strHtml .= $this->_tbodies[$i]->toHtml($tabs, $tab); + $strHtml .= $tabs . $tab . '' . $lnEnd; + } + } + } else { + for ($i = 0; $i < $this->_tbodyCount; $i++) { + $strHtml .= $this->_tbodies[$i]->toHtml($tabs, $tab); + } + } + $strHtml .= $tabs . '' . $lnEnd; + } + return $strHtml; + } + +} + +?> diff --git a/lib/Pear/HTML/Table/Storage.php b/lib/Pear/HTML/Table/Storage.php new file mode 100644 index 0000000..7239c15 --- /dev/null +++ b/lib/Pear/HTML/Table/Storage.php @@ -0,0 +1,869 @@ +..., ... and .... + * + * PHP versions 4 and 5 + * + * LICENSE: + * + * Copyright (c) 2005-2007, Adam Daniel , + * Bertrand Mansion , + * Mark Wiesemann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTML + * @package HTML_Table + * @author Adam Daniel + * @author Bertrand Mansion + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Storage.php,v 1.16 2007/04/29 16:31:06 wiesemann Exp $ + * @link http://pear.php.net/package/HTML_Table + */ + +/** + * Storage class for HTML::Table data + * + * This class stores data for tables built with HTML_Table. When having + * more than one instance, it can be used for grouping the table into the + * parts ..., ... and .... + * + * @category HTML + * @package HTML_Table + * @author Adam Daniel + * @author Bertrand Mansion + * @author Mark Wiesemann + * @copyright 2005-2006 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/HTML_Table + */ +class HTML_Table_Storage extends HTML_Common { + + /** + * Value to insert into empty cells + * @var string + * @access private + */ + var $_autoFill = ' '; + + /** + * Automatically adds a new row or column if a given row or column index + * does not exist + * @var bool + * @access private + */ + var $_autoGrow = true; + + /** + * Array containing the table structure + * @var array + * @access private + */ + var $_structure = array(); + + /** + * Number of rows composing in the table + * @var int + * @access private + */ + var $_rows = 0; + + /** + * Number of column composing the table + * @var int + * @access private + */ + var $_cols = 0; + + /** + * Tracks the level of nested tables + * @var int + * @access private + */ + var $_nestLevel = 0; + + /** + * Whether to use , and or not + * @var bool + * @access private + */ + var $_useTGroups = false; + + /** + * Class constructor + * @param int $tabOffset + * @param bool $useTGroups Whether to use , and + * or not + * @access public + */ + function HTML_Table_Storage($tabOffset = 0, $useTGroups = false) + { + HTML_Common::HTML_Common(null, (int)$tabOffset); + $this->_useTGroups = (boolean)$useTGroups; + } + + /** + * Sets the useTGroups value + * @param boolean $useTGroups + * @access public + */ + function setUseTGroups($useTGroups) + { + $this->_useTGroups = $useTGroups; + } + + /** + * Returns the useTGroups value + * @access public + * @return boolean + */ + function getUseTGroups() + { + return $this->_useTGroups; + } + + /** + * Sets the autoFill value + * @param mixed $fill + * @access public + */ + function setAutoFill($fill) + { + $this->_autoFill = $fill; + } + + /** + * Returns the autoFill value + * @access public + * @return mixed + */ + function getAutoFill() + { + return $this->_autoFill; + } + + /** + * Sets the autoGrow value + * @param bool $fill + * @access public + */ + function setAutoGrow($grow) + { + $this->_autoGrow = $grow; + } + + /** + * Returns the autoGrow value + * @access public + * @return mixed + */ + function getAutoGrow() + { + return $this->_autoGrow; + } + + /** + * Sets the number of rows in the table + * @param int $rows + * @access public + */ + function setRowCount($rows) + { + $this->_rows = $rows; + } + + /** + * Sets the number of columns in the table + * @param int $cols + * @access public + */ + function setColCount($cols) + { + $this->_cols = $cols; + } + + /** + * Returns the number of rows in the table + * @access public + * @return int + */ + function getRowCount() + { + return $this->_rows; + } + + /** + * Gets the number of columns in the table + * + * If a row index is specified, the count will not take + * the spanned cells into account in the return value. + * + * @param int Row index to serve for cols count + * @access public + * @return int + */ + function getColCount($row = null) + { + if (!is_null($row)) { + $count = 0; + foreach ($this->_structure[$row] as $cell) { + if (is_array($cell)) { + $count++; + } + } + return $count; + } + return $this->_cols; + } + + /** + * Sets a rows type 'TH' or 'TD' + * @param int $row Row index + * @param string $type 'TH' or 'TD' + * @access public + */ + + function setRowType($row, $type) + { + for ($counter = 0; $counter < $this->_cols; $counter++) { + $this->_structure[$row][$counter]['type'] = $type; + } + } + + /** + * Sets a columns type 'TH' or 'TD' + * @param int $col Column index + * @param string $type 'TH' or 'TD' + * @access public + */ + function setColType($col, $type) + { + for ($counter = 0; $counter < $this->_rows; $counter++) { + $this->_structure[$counter][$col]['type'] = $type; + } + } + + /** + * Sets the cell attributes for an existing cell. + * + * If the given indices do not exist and autoGrow is true then the given + * row and/or col is automatically added. If autoGrow is false then an + * error is returned. + * @param int $row Row index + * @param int $col Column index + * @param mixed $attributes Associative array or string of table + * row attributes + * @access public + * @throws PEAR_Error + */ + function setCellAttributes($row, $col, $attributes) + { + if ( isset($this->_structure[$row][$col]) + && $this->_structure[$row][$col] == '__SPANNED__' + ) { + return; + } + $attributes = $this->_parseAttributes($attributes); + $err = $this->_adjustEnds($row, $col, 'setCellAttributes', $attributes); + if (PEAR::isError($err)) { + return $err; + } + $this->_structure[$row][$col]['attr'] = $attributes; + $this->_updateSpanGrid($row, $col); + } + + /** + * Updates the cell attributes passed but leaves other existing attributes + * intact + * @param int $row Row index + * @param int $col Column index + * @param mixed $attributes Associative array or string of table row + * attributes + * @access public + */ + function updateCellAttributes($row, $col, $attributes) + { + if ( isset($this->_structure[$row][$col]) + && $this->_structure[$row][$col] == '__SPANNED__' + ) { + return; + } + $attributes = $this->_parseAttributes($attributes); + $err = $this->_adjustEnds($row, $col, 'updateCellAttributes', $attributes); + if (PEAR::isError($err)) { + return $err; + } + $this->_updateAttrArray($this->_structure[$row][$col]['attr'], $attributes); + $this->_updateSpanGrid($row, $col); + } + + /** + * Returns the attributes for a given cell + * @param int $row Row index + * @param int $col Column index + * @return array + * @access public + */ + function getCellAttributes($row, $col) + { + if ( isset($this->_structure[$row][$col]) + && $this->_structure[$row][$col] != '__SPANNED__' + ) { + return $this->_structure[$row][$col]['attr']; + } elseif (!isset($this->_structure[$row][$col])) { + return PEAR::raiseError('Invalid table cell reference[' . + $row . '][' . $col . '] in HTML_Table::getCellAttributes'); + } + return; + } + + /** + * Sets the cell contents for an existing cell + * + * If the given indices do not exist and autoGrow is true then the given + * row and/or col is automatically added. If autoGrow is false then an + * error is returned. + * @param int $row Row index + * @param int $col Column index + * @param mixed $contents May contain html or any object with a + * toHTML() method; if it is an array (with + * strings and/or objects), $col will be used + * as start offset and the array elements will + * be set to this and the following columns + * in $row + * @param string $type (optional) Cell type either 'TH' or 'TD' + * @access public + * @throws PEAR_Error + */ + function setCellContents($row, $col, $contents, $type = 'TD') + { + if (is_array($contents)) { + foreach ($contents as $singleContent) { + $ret = $this->_setSingleCellContents($row, $col, $singleContent, + $type); + if (PEAR::isError($ret)) { + return $ret; + } + $col++; + } + } else { + $ret = $this->_setSingleCellContents($row, $col, $contents, $type); + if (PEAR::isError($ret)) { + return $ret; + } + } + } + + /** + * Sets the cell contents for a single existing cell + * + * If the given indices do not exist and autoGrow is true then the given + * row and/or col is automatically added. If autoGrow is false then an + * error is returned. + * @param int $row Row index + * @param int $col Column index + * @param mixed $contents May contain html or any object with a + * toHTML() method; if it is an array (with + * strings and/or objects), $col will be used + * as start offset and the array elements will + * be set to this and the following columns + * in $row + * @param string $type (optional) Cell type either 'TH' or 'TD' + * @access private + * @throws PEAR_Error + */ + function _setSingleCellContents($row, $col, $contents, $type = 'TD') + { + if ( isset($this->_structure[$row][$col]) + && $this->_structure[$row][$col] == '__SPANNED__' + ) { + return; + } + $err = $this->_adjustEnds($row, $col, 'setCellContents'); + if (PEAR::isError($err)) { + return $err; + } + $this->_structure[$row][$col]['contents'] = $contents; + $this->_structure[$row][$col]['type'] = $type; + } + + /** + * Returns the cell contents for an existing cell + * @param int $row Row index + * @param int $col Column index + * @access public + * @return mixed + */ + function getCellContents($row, $col) + { + if ( isset($this->_structure[$row][$col]) + && $this->_structure[$row][$col] == '__SPANNED__' + ) { + return; + } + if (!isset($this->_structure[$row][$col])) { + return PEAR::raiseError('Invalid table cell reference[' . + $row . '][' . $col . '] in HTML_Table::getCellContents'); + } + return $this->_structure[$row][$col]['contents']; + } + + /** + * Sets the contents of a header cell + * @param int $row + * @param int $col + * @param mixed $contents + * @param mixed $attributes Associative array or string of table row + * attributes + * @access public + */ + function setHeaderContents($row, $col, $contents, $attributes = null) + { + $this->setCellContents($row, $col, $contents, 'TH'); + if (!is_null($attributes)) { + $this->updateCellAttributes($row, $col, $attributes); + } + } + + /** + * Adds a table row and returns the row identifier + * @param array $contents (optional) Must be a indexed array of valid + * cell contents + * @param mixed $attributes (optional) Associative array or string of + * table row attributes. This can + * also be an array of attributes, + * in which case the attributes + * will be repeated in a loop. + * @param string $type (optional) Cell type either 'th' or 'td' + * @param bool $inTR false if attributes are to be + * applied in TD tags; true if + * attributes are to be applied in + * TR tag + * @return int + * @access public + */ + function addRow($contents = null, $attributes = null, $type = 'td', + $inTR = false) + { + if (isset($contents) && !is_array($contents)) { + return PEAR::raiseError('First parameter to HTML_Table::addRow ' . + 'must be an array'); + } + if (is_null($contents)) { + $contents = array(); + } + + $type = strtolower($type); + $row = $this->_rows++; + foreach ($contents as $col => $content) { + if ($type == 'td') { + $this->setCellContents($row, $col, $content); + } elseif ($type == 'th') { + $this->setHeaderContents($row, $col, $content); + } + } + $this->setRowAttributes($row, $attributes, $inTR); + return $row; + } + + /** + * Sets the row attributes for an existing row + * @param int $row Row index + * @param mixed $attributes Associative array or string of table + * row attributes. This can also be an + * array of attributes, in which case the + * attributes will be repeated in a loop. + * @param bool $inTR false if attributes are to be applied + * in TD tags; true if attributes are to + * be applied in TR tag + * @access public + * @throws PEAR_Error + */ + function setRowAttributes($row, $attributes, $inTR = false) + { + if (!$inTR) { + $multiAttr = $this->_isAttributesArray($attributes); + for ($i = 0; $i < $this->_cols; $i++) { + if ($multiAttr) { + $this->setCellAttributes($row, $i, + $attributes[$i - ((ceil(($i + 1) / count($attributes))) - 1) * count($attributes)]); + } else { + $this->setCellAttributes($row, $i, $attributes); + } + } + } else { + $attributes = $this->_parseAttributes($attributes); + $err = $this->_adjustEnds($row, 0, 'setRowAttributes', $attributes); + if (PEAR::isError($err)) { + return $err; + } + $this->_structure[$row]['attr'] = $attributes; + } + } + + /** + * Updates the row attributes for an existing row + * @param int $row Row index + * @param mixed $attributes Associative array or string of table + * row attributes + * @param bool $inTR false if attributes are to be applied + * in TD tags; true if attributes are to + * be applied in TR tag + * @access public + * @throws PEAR_Error + */ + function updateRowAttributes($row, $attributes = null, $inTR = false) + { + if (!$inTR) { + $multiAttr = $this->_isAttributesArray($attributes); + for ($i = 0; $i < $this->_cols; $i++) { + if ($multiAttr) { + $this->updateCellAttributes($row, $i, + $attributes[$i - ((ceil(($i + 1) / count($attributes))) - 1) * count($attributes)]); + } else { + $this->updateCellAttributes($row, $i, $attributes); + } + } + } else { + $attributes = $this->_parseAttributes($attributes); + $err = $this->_adjustEnds($row, 0, 'updateRowAttributes', $attributes); + if (PEAR::isError($err)) { + return $err; + } + $this->_updateAttrArray($this->_structure[$row]['attr'], $attributes); + } + } + + /** + * Returns the attributes for a given row as contained in the TR tag + * @param int $row Row index + * @return array + * @access public + */ + function getRowAttributes($row) + { + if (isset($this->_structure[$row]['attr'])) { + return $this->_structure[$row]['attr']; + } + return; + } + + /** + * Alternates the row attributes starting at $start + * @param int $start Row index of row in which alternating + * begins + * @param mixed $attributes1 Associative array or string of table + * row attributes + * @param mixed $attributes2 Associative array or string of table + * row attributes + * @param bool $inTR false if attributes are to be applied + * in TD tags; true if attributes are to + * be applied in TR tag + * @param int $firstAttributes (optional) Which attributes should be + * applied to the first row, 1 or 2. + * @access public + */ + function altRowAttributes($start, $attributes1, $attributes2, $inTR = false, + $firstAttributes = 1) + { + for ($row = $start; $row < $this->_rows; $row++) { + if (($row + $start + ($firstAttributes - 1)) % 2 == 0) { + $attributes = $attributes1; + } else { + $attributes = $attributes2; + } + $this->updateRowAttributes($row, $attributes, $inTR); + } + } + + /** + * Adds a table column and returns the column identifier + * @param array $contents (optional) Must be a indexed array of valid + * cell contents + * @param mixed $attributes (optional) Associative array or string of + * table row attributes + * @param string $type (optional) Cell type either 'th' or 'td' + * @return int + * @access public + */ + function addCol($contents = null, $attributes = null, $type = 'td') + { + if (isset($contents) && !is_array($contents)) { + return PEAR::raiseError('First parameter to HTML_Table::addCol ' . + 'must be an array'); + } + if (is_null($contents)) { + $contents = array(); + } + + $type = strtolower($type); + $col = $this->_cols++; + foreach ($contents as $row => $content) { + if ($type == 'td') { + $this->setCellContents($row, $col, $content); + } elseif ($type == 'th') { + $this->setHeaderContents($row, $col, $content); + } + } + $this->setColAttributes($col, $attributes); + return $col; + } + + /** + * Sets the column attributes for an existing column + * @param int $col Column index + * @param mixed $attributes (optional) Associative array or string + * of table row attributes + * @access public + */ + function setColAttributes($col, $attributes = null) + { + $multiAttr = $this->_isAttributesArray($attributes); + for ($i = 0; $i < $this->_rows; $i++) { + if ($multiAttr) { + $this->setCellAttributes($i, $col, + $attributes[$i - ((ceil(($i + 1) / count($attributes))) - 1) * count($attributes)]); + } else { + $this->setCellAttributes($i, $col, $attributes); + } + } + } + + /** + * Updates the column attributes for an existing column + * @param int $col Column index + * @param mixed $attributes (optional) Associative array or string + * of table row attributes + * @access public + */ + function updateColAttributes($col, $attributes = null) + { + $multiAttr = $this->_isAttributesArray($attributes); + for ($i = 0; $i < $this->_rows; $i++) { + if ($multiAttr) { + $this->updateCellAttributes($i, $col, + $attributes[$i - ((ceil(($i + 1) / count($attributes))) - 1) * count($attributes)]); + } else { + $this->updateCellAttributes($i, $col, $attributes); + } + } + } + + /** + * Sets the attributes for all cells + * @param mixed $attributes (optional) Associative array or + * string of table row attributes + * @access public + */ + function setAllAttributes($attributes = null) + { + for ($i = 0; $i < $this->_rows; $i++) { + $this->setRowAttributes($i, $attributes); + } + } + + /** + * Updates the attributes for all cells + * @param mixed $attributes (optional) Associative array or + * string of table row attributes + * @access public + */ + function updateAllAttributes($attributes = null) + { + for ($i = 0; $i < $this->_rows; $i++) { + $this->updateRowAttributes($i, $attributes); + } + } + + /** + * Returns the table rows as HTML + * @access public + * @return string + */ + function toHtml($tabs = null, $tab = null) + { + $strHtml = ''; + if (is_null($tabs)) { + $tabs = $this->_getTabs(); + } + if (is_null($tab)) { + $tab = $this->_getTab(); + } + $lnEnd = $this->_getLineEnd(); + if ($this->_useTGroups) { + $extraTab = $tab; + } else { + $extraTab = ''; + } + if ($this->_cols > 0) { + for ($i = 0 ; $i < $this->_rows ; $i++) { + $attr = ''; + if (isset($this->_structure[$i]['attr'])) { + $attr = $this->_getAttrString($this->_structure[$i]['attr']); + } + $strHtml .= $tabs .$tab . $extraTab . '' . $lnEnd; + for ($j = 0 ; $j < $this->_cols ; $j++) { + $attr = ''; + $contents = ''; + $type = 'td'; + if (isset($this->_structure[$i][$j]) && $this->_structure[$i][$j] == '__SPANNED__') { + continue; + } + if (isset($this->_structure[$i][$j]['type'])) { + $type = (strtolower($this->_structure[$i][$j]['type']) == 'th' ? 'th' : 'td'); + } + if (isset($this->_structure[$i][$j]['attr'])) { + $attr = $this->_structure[$i][$j]['attr']; + } + if (isset($this->_structure[$i][$j]['contents'])) { + $contents = $this->_structure[$i][$j]['contents']; + } + $strHtml .= $tabs . $tab . $tab . $extraTab . "<$type" . $this->_getAttrString($attr) . '>'; + if (is_object($contents)) { + // changes indent and line end settings on nested tables + if (is_subclass_of($contents, 'html_common')) { + $contents->setTab($tab . $extraTab); + $contents->setTabOffset($this->_tabOffset + 3); + $contents->_nestLevel = $this->_nestLevel + 1; + $contents->setLineEnd($this->_getLineEnd()); + } + if (method_exists($contents, 'toHtml')) { + $contents = $contents->toHtml(); + } elseif (method_exists($contents, 'toString')) { + $contents = $contents->toString(); + } + } + if (is_array($contents)) { + $contents = implode(', ', $contents); + } + if (isset($this->_autoFill) && $contents === '') { + $contents = $this->_autoFill; + } + $strHtml .= $contents; + $strHtml .= "" . $lnEnd; + } + $strHtml .= $tabs . $tab . $extraTab . '' . $lnEnd; + } + } + return $strHtml; + } + + /** + * Checks if rows or columns are spanned + * @param int $row Row index + * @param int $col Column index + * @access private + */ + function _updateSpanGrid($row, $col) + { + if (isset($this->_structure[$row][$col]['attr']['colspan'])) { + $colspan = $this->_structure[$row][$col]['attr']['colspan']; + } + + if (isset($this->_structure[$row][$col]['attr']['rowspan'])) { + $rowspan = $this->_structure[$row][$col]['attr']['rowspan']; + } + + if (isset($colspan)) { + for ($j = $col + 1; (($j < $this->_cols) && ($j <= ($col + $colspan - 1))); $j++) { + $this->_structure[$row][$j] = '__SPANNED__'; + } + } + + if (isset($rowspan)) { + for ($i = $row + 1; (($i < $this->_rows) && ($i <= ($row + $rowspan - 1))); $i++) { + $this->_structure[$i][$col] = '__SPANNED__'; + } + } + + if (isset($colspan) && isset($rowspan)) { + for ($i = $row + 1; (($i < $this->_rows) && ($i <= ($row + $rowspan - 1))); $i++) { + for ($j = $col + 1; (($j <= $this->_cols) && ($j <= ($col + $colspan - 1))); $j++) { + $this->_structure[$i][$j] = '__SPANNED__'; + } + } + } + } + + /** + * Adjusts ends (total number of rows and columns) + * @param int $row Row index + * @param int $col Column index + * @param string $method Method name of caller + * Used to populate PEAR_Error if thrown. + * @param array $attributes Assoc array of attributes + * Default is an empty array. + * @access private + * @throws PEAR_Error + */ + function _adjustEnds($row, $col, $method, $attributes = array()) + { + $colspan = isset($attributes['colspan']) ? $attributes['colspan'] : 1; + $rowspan = isset($attributes['rowspan']) ? $attributes['rowspan'] : 1; + if (($row + $rowspan - 1) >= $this->_rows) { + if ($this->_autoGrow) { + $this->_rows = $row + $rowspan; + } else { + return PEAR::raiseError('Invalid table row reference[' . + $row . '] in HTML_Table::' . $method); + } + } + + if (($col + $colspan - 1) >= $this->_cols) { + if ($this->_autoGrow) { + $this->_cols = $col + $colspan; + } else { + return PEAR::raiseError('Invalid table column reference[' . + $col . '] in HTML_Table::' . $method); + } + } + } + + /** + * Tells if the parameter is an array of attribute arrays/strings + * @param mixed $attributes Variable to test + * @access private + * @return bool + */ + function _isAttributesArray($attributes) + { + if (is_array($attributes) && isset($attributes[0])) { + if (is_array($attributes[0]) || (is_string($attributes[0]) && count($attributes) > 1)) { + return true; + } + } + return false; + } + +} +?> diff --git a/lib/Pear/I18Nv2/CommonList.php b/lib/Pear/I18Nv2/CommonList.php new file mode 100644 index 0000000..a95dfbf --- /dev/null +++ b/lib/Pear/I18Nv2/CommonList.php @@ -0,0 +1,242 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: CommonList.php,v 1.13 2005/10/03 10:34:18 mike Exp $ + +/** + * I18Nv2::CommonList + * + * @author Michael Wallner + * @package I18Nv2 + * @category Internationalization + */ + +/** + * I18Nv2_CommonList + * + * Base class for I18Nv2_Country and I18Nv2_Language that performs some basic + * work, so code doesn't get written twice or even more often in the future. + * + * @author Michael Wallner + * @version $Revision: 1.13 $ + * @access public + */ +class I18Nv2_CommonList +{ + /** + * Codes + * + * @access protected + * @var array + */ + var $codes = array(); + + /** + * Language + * + * @access protected + * @var string + */ + var $language = ''; + + /** + * Encoding + * + * @access protected + * @var string + */ + var $encoding = ''; + + /** + * Constructor + * + * @access public + * @param string $language + * @param string $encoding + */ + function I18Nv2_CommonList($language = null, $encoding = null) + { + if (!$this->setLanguage($language)) { + if (class_exists('I18Nv2')) { + $l = I18Nv2::lastLocale(0, true); + if (!isset($l) || !$this->setLanguage($l['language'])) { + $this->setLanguage('en'); + } + } else { + $this->setLanguage('en'); + } + } + if (!$this->setEncoding($encoding)) { + $this->setEncoding('UTF-8'); + } + } + + /** + * Set active language + * + * Note that each time you set a different language the corresponding + * language file has to be loaded again, too. + * + * @access public + * @return bool + * @param string $language + */ + function setLanguage($language) + { + if (!isset($language)) { + return false; + } + $language = strToLower($language); + if ($language === $this->language) { + return true; + } + if ($this->loadLanguage($language)) { + $this->language = $language; + return true; + } + return false; + } + + /** + * Get current language + * + * @access public + * @return string + */ + function getLanguage() + { + return $this->language; + } + + /** + * Set active encoding + * + * @access public + * @return bool + * @param string $encoding + */ + function setEncoding($encoding) + { + if (!isset($encoding)) { + return false; + } + $this->encoding = strToUpper($encoding); + return true; + } + + /** + * Get current encoding + * + * @access public + * @return string + */ + function getEncoding() + { + return $this->encoding; + } + + /** + * Check if code is valid + * + * @access public + * @return bool + * @param string $code code + */ + function isValidCode($code) + { + return isset($this->codes[$this->changeKeyCase($code)]); + } + + /** + * Return corresponding name of code + * + * @access public + * @return string name + * @param string $code code + */ + function getName($code) + { + $code = $this->changeKeyCase($code); + if (!isset($this->codes[$code])) { + return ''; + } + if ('UTF-8' !== $this->encoding) { + return iconv('UTF-8', $this->encoding .'//TRANSLIT', $this->codes[$code]); + } + return $this->codes[$code]; + } + + /** + * Return all the codes + * + * @access public + * @return array all codes as associative array + */ + function getAllCodes() + { + if ('UTF-8' !== $this->encoding) { + $codes = $this->codes; + array_walk($codes, array(&$this, '_iconv')); + return $codes; + } + return $this->codes; + } + + /** + * @access private + * @return void + */ + function _iconv(&$code, $key) + { + $code = iconv('UTF-8', $this->encoding .'//TRANSLIT', $code); + } + + /** + * Load Language + * + * @access proteceted + * @return bool + * @param string $language + */ + function loadLanguage($language) + { + return false; + } + + /** + * Change Key Case + * + * @access protected + * @return string + * @param string $code + */ + function changeKeyCase($code) + { + return $code; + } + + /** + * Decorate this list + * + * @access public + * @return object I18NV2_DecoratedList + * @param string $type + */ + function &toDecoratedList($type) + { + require_once 'I18Nv2/DecoratedList/'. $type .'.php'; + $decoratedList = 'I18Nv2_DecoratedList_' . $type; + return new $decoratedList($this); + } +} +?> diff --git a/lib/Pear/I18Nv2/Country.php b/lib/Pear/I18Nv2/Country.php new file mode 100644 index 0000000..6447df3 --- /dev/null +++ b/lib/Pear/I18Nv2/Country.php @@ -0,0 +1,61 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Country.php,v 1.10 2004/10/29 10:21:08 mike Exp $ + +/** + * I18Nv2::Country + * + * @package I18Nv2 + * @category Internationalization + */ + +require_once 'I18Nv2/CommonList.php'; + +/** + * I18Nv2_Country + * + * List of ISO-3166 two letter country code to country name mapping. + * + * @author Michael Wallner + * @version $Revision: 1.10 $ + * @access public + * @package I18Nv2 + */ +class I18Nv2_Country extends I18Nv2_CommonList +{ + /** + * Load language file + * + * @access protected + * @return bool + * @param string $language + */ + function loadLanguage($language) + { + return @include 'I18Nv2/Country/' . $language . '.php'; + } + + /** + * Change case of code key + * + * @access protected + * @return string + * @param string $code + */ + function changeKeyCase($code) + { + return strToUpper($code); + } +} +?> diff --git a/lib/Pear/I18Nv2/Language.php b/lib/Pear/I18Nv2/Language.php new file mode 100644 index 0000000..803a9ef --- /dev/null +++ b/lib/Pear/I18Nv2/Language.php @@ -0,0 +1,61 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Language.php,v 1.8 2004/10/29 10:21:08 mike Exp $ + +/** + * I18Nv2::Language + * + * @package I18Nv2 + * @category Internationalization + */ + +require_once 'I18Nv2/CommonList.php'; + +/** + * I18Nv2_Language + * + * List of ISO-639-1 two letter language code to language name mapping. + * + * @author Michael Wallner + * @version $Revision: 1.8 $ + * @package I18Nv2 + * @access public + */ +class I18Nv2_Language extends I18Nv2_CommonList +{ + /** + * Load language file + * + * @access proteceted + * @return bool + * @param string $language + */ + function loadLanguage($language) + { + return @include 'I18Nv2/Language/' . $language . '.php'; + } + + /** + * Change case of code key + * + * @access protected + * @return string + * @param string $code + */ + function changeKeyCase($code) + { + return strToLower($code); + } +} +?> diff --git a/lib/Pear/I18Nv2/Language/aa.php b/lib/Pear/I18Nv2/Language/aa.php new file mode 100644 index 0000000..759b245 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/aa.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Qafar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/af.php b/lib/Pear/I18Nv2/Language/af.php new file mode 100644 index 0000000..5d91a64 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/af.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/am.php b/lib/Pear/I18Nv2/Language/am.php new file mode 100644 index 0000000..bc14701 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/am.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'አá‹áˆ­áŠ›', + 'ab' => 'አብáˆá‹šáŠ›', + 'ae' => 'Avestan', + 'af' => 'አáሪቃንስኛ', + 'ak' => 'Akan', + 'am' => 'አማርኛ', + 'an' => 'Aragonese', + 'ar' => 'á‹áˆ­á‰¢áŠ›', + 'as' => 'አሳሜዛዊ', + 'av' => 'Avaric', + 'ay' => 'አያማርኛ', + 'az' => 'አዜርባይጃንኛ', + 'ba' => 'ባስኪርኛ', + 'be' => 'ቤላራሻኛ', + 'bg' => 'ቡáˆáŒ‹áˆªáŠ›', + 'bh' => 'ቢሃሪ', + 'bi' => 'ቢስላáˆáŠ›', + 'bm' => 'Bambara', + 'bn' => 'በንጋሊኛ', + 'bo' => 'ትበትንኛ', + 'br' => 'ብሬቶንኛ', + 'bs' => 'Bosnian', + 'ca' => 'ካታላንኛ', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'ኮርሲካኛ', + 'cr' => 'Cree', + 'cs' => 'ቼክኛ', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'ወáˆáˆ½', + 'da' => 'ዴኒሽ', + 'de' => 'ጀርመን', + 'dv' => 'Divehi', + 'dz' => 'ድዞንáŒáŠ»áŠ›', + 'ee' => 'Ewe', + 'el' => 'áŒáˆªáŠ­áŠ›', + 'en' => 'እንáŒáˆŠá‹áŠ›', + 'eo' => 'ኤስáራንቶ', + 'es' => 'ስá“ኒሽ', + 'et' => 'ኤስቶኒአን', + 'eu' => 'ባስክኛ', + 'fa' => 'áርሲያኛ', + 'ff' => 'Fulah', + 'fi' => 'áŠáŠ’ሽ', + 'fj' => 'áŠáŒ‚ኛ', + 'fo' => 'á‹áˆ®áŠ›', + 'fr' => 'áˆáˆ¨áŠ•áˆ³á‹­áŠ›', + 'fy' => 'áሪስኛ', + 'ga' => 'አይሪሽ', + 'gd' => 'እስኮትስ ጌáˆáŠ­áŠ›', + 'gl' => 'ጋለጋኛ', + 'gn' => 'ጓራኒኛ', + 'gu' => 'ጉጃርቲኛ', + 'gv' => 'Manx', + 'ha' => 'ሃá‹áˆ³áŠ›', + 'he' => 'ዕብራስጥ', + 'hi' => 'áˆáŠ•á‹µáŠ›', + 'ho' => 'Hiri Motu', + 'hr' => 'ክሮሽያንኛ', + 'ht' => 'Haitian', + 'hu' => 'ሀንጋሪኛ', + 'hy' => 'አርመናዊ', + 'hz' => 'Herero', + 'ia' => 'ኢንቴርሊንጓ', + 'id' => 'እንዶኒሲኛ', + 'ie' => 'እንተርሊንáŒá‹ˆ', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'እኑá’ያቅኛ', + 'io' => 'Ido', + 'is' => 'አይስላንድኛ', + 'it' => 'ጣሊያንኛ', + 'iu' => 'እኑክቲቱትኛ', + 'ja' => 'ጃá“ንኛ', + 'jv' => 'ጃቫንኛ', + 'ka' => 'ጊዮርጊያን', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'ካዛክኛ', + 'kl' => 'ካላሊሱትኛ', + 'km' => 'ክመርኛ', + 'kn' => 'ካናዳኛ', + 'ko' => 'ኮሪያኛ', + 'kr' => 'Kanuri', + 'ks' => 'ካሽሚርኛ', + 'ku' => 'ኩርድሽኛ', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'ኪርጊá‹áŠ›', + 'la' => 'ላቲንኛ', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'ሊንጋላኛ', + 'lo' => 'ላá‹áˆµáŠ›', + 'lt' => 'ሊቱአኒያን', + 'lu' => 'Luba-Katanga', + 'lv' => 'ላትቪያን', + 'mg' => 'ማላጋስኛ', + 'mh' => 'Marshallese', + 'mi' => 'ማዮሪኛ', + 'mk' => 'ማከዶኒኛ', + 'ml' => 'ማላያላáˆáŠ›', + 'mn' => 'ሞንጎላዊኛ', + 'mo' => 'ሞáˆá‹³á‰«á‹ŠáŠ“', + 'mr' => 'ማራዚኛ', + 'ms' => 'ማላይኛ', + 'mt' => 'ማáˆá‰²áˆµáŠ›', + 'my' => 'ቡርማኛ', + 'na' => 'ናኡሩ', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ኔá“ሊኛ', + 'ng' => 'Ndonga', + 'nl' => 'ደች', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'ኖርዌጂያን', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ኦኪታንኛ', + 'oj' => 'Ojibwa', + 'om' => 'ኦሮáˆáŠ›', + 'or' => 'ኦሪያኛ', + 'os' => 'Ossetic', + 'pa' => 'á“ንጃቢኛ', + 'pi' => 'Pali', + 'pl' => 'á–ሊሽ', + 'ps' => 'á‘ሽቶኛ', + 'pt' => 'á–ርቱጋሊኛ', + 'qu' => 'ኵቿኛ', + 'rm' => 'ሮማንስ', + 'rn' => 'ሩንዲኛ', + 'ro' => 'ሮማኒያን', + 'ru' => 'ራሽኛ', + 'rw' => 'ኪንያርዋንድኛ', + 'sa' => 'ሳንስክሪትኛ', + 'sc' => 'Sardinian', + 'sd' => 'ሲንድሂኛ', + 'se' => 'Northern Sami', + 'sg' => 'ሳንጎኛ', + 'sh' => 'Serbo-Croatian', + 'si' => 'ስንሃáˆáŠ›', + 'sk' => 'ስሎቫክኛ', + 'sl' => 'ስሎቪኛ', + 'sm' => 'ሳሞአኛ', + 'sn' => 'ሾናኛ', + 'so' => 'ሱማáˆáŠ›', + 'sq' => 'áˆá‰¤áŠ’ኛ', + 'sr' => 'ሰርቢኛ', + 'ss' => 'ስዋቲኛ', + 'st' => 'ሶዞኛ', + 'su' => 'ሱዳንኛ', + 'sv' => 'ስዊድንኛ', + 'sw' => 'ስዋሂሊኛ', + 'ta' => 'ታሚáˆáŠ›', + 'te' => 'ተሉጉኛ', + 'tg' => 'ታጂኪኛ', + 'th' => 'ታይኛ', + 'ti' => 'ትáŒáˆ­áŠ›', + 'tk' => 'ቱርክመንኛ', + 'tl' => 'ታጋሎገኛ', + 'tn' => 'ጽዋናዊኛ', + 'to' => 'ቶንጋ', + 'tr' => 'ቱርክኛ', + 'ts' => 'ጾንጋኛ', + 'tt' => 'ታታርኛ', + 'tw' => 'ትዊኛ', + 'ty' => 'Tahitian', + 'ug' => 'ኡዊáŒáˆáˆ­áŠ›', + 'uk' => 'ዩክረኒኛ', + 'ur' => 'ኡርዱኛ', + 'uz' => 'ኡá‹á‰ áŠ­áŠ›', + 've' => 'Venda', + 'vi' => 'ቪትናáˆáŠ›', + 'vo' => 'ቮላá‘ክኛ', + 'wa' => 'Walloon', + 'wo' => 'ዎሎáኛ', + 'xh' => 'ዞሳኛ', + 'yi' => 'ይዲሻዊኛ', + 'yo' => 'ዮሩባዊኛ', + 'za' => 'ዡዋንáŒáŠ›', + 'zh' => 'ቻይንኛ', + 'zu' => 'ዙሉኛ', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ar.php b/lib/Pear/I18Nv2/Language/ar.php new file mode 100644 index 0000000..ae07fed --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ar.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'الاÙارية', + 'ab' => 'الابخازية', + 'ae' => 'Avestan', + 'af' => 'الاÙريقية', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'العربية', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'اذرية', + 'ba' => 'Bashkir', + 'be' => 'البيلوروسية', + 'bg' => 'البلغارية', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'البنغالية', + 'bo' => 'التبتية', + 'br' => 'Breton', + 'bs' => 'البوسنية', + 'ca' => 'الكاتالوينية', + 'ce' => 'الشيشانية', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'التشيكية', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'الولزية', + 'da' => 'الدانماركية', + 'de' => 'الالمانية', + 'dv' => 'المالديÙية', + 'dz' => 'الزونخاية', + 'ee' => 'Ewe', + 'el' => 'اليونانية', + 'en' => 'الانجليزية', + 'eo' => 'اسبرانتو', + 'es' => 'الاسبانية', + 'et' => 'استونية', + 'eu' => 'Basque', + 'fa' => 'الÙارسية', + 'ff' => 'Fulah', + 'fi' => 'الÙنلندية', + 'fj' => 'الÙيجية', + 'fo' => 'Faroese', + 'fr' => 'الÙرنسية', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'الغوجاراتية', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'العبرية', + 'hi' => 'الهندية', + 'ho' => 'Hiri Motu', + 'hr' => 'الكرواتية', + 'ht' => 'الهايتية', + 'hu' => 'الهنغارية', + 'hy' => 'الارمنية', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'الاندونيسية', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'الايطالية', + 'iu' => 'Inuktitut', + 'ja' => 'اليابانية', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'الخميرية', + 'kn' => 'Kannada', + 'ko' => 'الكورية', + 'kr' => 'Kanuri', + 'ks' => 'الكاشميرية', + 'ku' => 'الكردية', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'اللاتينية', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'اللتوانية', + 'lu' => 'Luba-Katanga', + 'lv' => 'اللاتÙية', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'المنغولية', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'لغة الملايو', + 'mt' => 'المالطية', + 'my' => 'البورمية', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'النيبالية', + 'ng' => 'Ndonga', + 'nl' => 'الهولندية', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'البنجابية', + 'pi' => 'Pali', + 'pl' => 'البولونية', + 'ps' => 'البشتونية', + 'pt' => 'البرتغالية', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'الرومانية', + 'ru' => 'الروسية', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'الالبانية', + 'sr' => 'الصربية', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'السويدية', + 'sw' => 'السواحلية', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'التايلاندية', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'التاغالوغية', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'التركية', + 'ts' => 'Tsonga', + 'tt' => 'التترية', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'الاغورية', + 'uk' => 'الاوكرانية', + 'ur' => 'الاردية', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'الÙيتنامية', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'الصينية', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/as.php b/lib/Pear/I18Nv2/Language/as.php new file mode 100644 index 0000000..2f95052 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/as.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'অসমীয়া', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/az.php b/lib/Pear/I18Nv2/Language/az.php new file mode 100644 index 0000000..9bcc178 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/az.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'AzÉ™rbaycanca', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/be.php b/lib/Pear/I18Nv2/Language/be.php new file mode 100644 index 0000000..fbf3f4f --- /dev/null +++ b/lib/Pear/I18Nv2/Language/be.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ÐрабÑкі', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'БеларуÑкі', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'ÐÑмецкі', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'ÐнглійÑкі', + 'eo' => 'Esperanto', + 'es' => 'ІÑпанÑкі', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'ФранцузÑкі', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Хіндзі', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ІтальÑнÑкі', + 'iu' => 'Inuktitut', + 'ja' => 'ЯпонÑкі', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'ПартугальÑкі', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'РуÑкі', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'КітайÑкі', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/bg.php b/lib/Pear/I18Nv2/Language/bg.php new file mode 100644 index 0000000..326bfdc --- /dev/null +++ b/lib/Pear/I18Nv2/Language/bg.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'ÐбкхазÑки', + 'ae' => 'Avestan', + 'af' => 'ÐфриканÑ', + 'ak' => 'Akan', + 'am' => 'ÐмхарÑки', + 'an' => 'Aragonese', + 'ar' => 'ÐрабÑки', + 'as' => 'Assamese', + 'av' => 'ÐварÑки', + 'ay' => 'Ðймара', + 'az' => 'ÐзербайджанÑки', + 'ba' => 'БашкирÑки', + 'be' => 'БеларуÑки', + 'bg' => 'БългарÑки', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'БенгалÑки', + 'bo' => 'ТибетÑки', + 'br' => 'БретонÑки', + 'bs' => 'БоÑненÑки', + 'ca' => 'КаталонÑки', + 'ce' => 'ЧеченÑки', + 'ch' => 'Chamorro', + 'co' => 'КорÑиканÑки', + 'cr' => 'Cree', + 'cs' => 'Чешки', + 'cu' => 'Църковно ÑлавÑнÑки', + 'cv' => 'Chuvash', + 'cy' => 'УелÑки', + 'da' => 'ДатÑки', + 'de' => 'ÐемÑки', + 'dv' => 'Дивехи', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Гръцки', + 'en' => 'ÐнглийÑки', + 'eo' => 'ЕÑперанто', + 'es' => 'ИÑпанÑки', + 'et' => 'ЕÑтонÑки', + 'eu' => 'БаÑки', + 'fa' => 'ПерÑийÑки', + 'ff' => 'Fulah', + 'fi' => 'ФинÑки', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'ФренÑки', + 'fy' => 'Frisian', + 'ga' => 'ИрландÑки', + 'gd' => 'ШотландÑки галÑки', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Гуджарати', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Иврит', + 'hi' => 'Хинди', + 'ho' => 'Hiri Motu', + 'hr' => 'ХърватÑки', + 'ht' => 'ХаитÑнÑки', + 'hu' => 'УнгарÑки', + 'hy' => 'ÐрменÑки', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'ИндонезийÑки', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Идо', + 'is' => 'ИÑландÑки', + 'it' => 'ИталианÑки', + 'iu' => 'Inuktitut', + 'ja' => 'ЯпонÑки', + 'jv' => 'ЯванÑки', + 'ka' => 'ГрузинÑки', + 'kg' => 'КонгоанÑки', + 'ki' => 'Кикуйу', + 'kj' => 'Kuanyama', + 'kk' => 'КазахÑки', + 'kl' => 'Kalaallisut', + 'km' => 'КхмерÑки', + 'kn' => 'Kannada', + 'ko' => 'КорейÑки', + 'kr' => 'Kanuri', + 'ks' => 'КашмирÑки', + 'ku' => 'КюрдÑки', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'КиргизÑки', + 'la' => 'ЛатинÑки', + 'lb' => 'ЛюкÑембургÑки', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'ЛаоÑки', + 'lt' => 'ЛитовÑки', + 'lu' => 'Luba-Katanga', + 'lv' => 'ЛатвийÑки', + 'mg' => 'Малгашки', + 'mh' => 'Marshallese', + 'mi' => 'МаорÑки', + 'mk' => 'МакедонÑки', + 'ml' => 'МалайÑки', + 'mn' => 'МонголÑки', + 'mo' => 'МолдовÑки', + 'mr' => 'Marathi', + 'ms' => 'МалайÑки', + 'mt' => 'МалтийÑки', + 'my' => 'БирманÑки', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ÐепалÑки', + 'ng' => 'Ndonga', + 'nl' => 'ХоландÑки', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Ðорвежки', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'ЧинÑнджа', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'ОÑетÑки', + 'pa' => 'ПенджабÑки', + 'pi' => 'Pali', + 'pl' => 'ПолÑки', + 'ps' => 'Пущу', + 'pt' => 'ПортугалÑки', + 'qu' => 'Кечуа', + 'rm' => 'РетороманÑки', + 'rn' => 'Рунди', + 'ro' => 'РумънÑки', + 'ru' => 'РуÑки', + 'rw' => 'КинÑруанда', + 'sa' => 'СанкÑкритÑки', + 'sc' => 'СардинÑки', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Санго', + 'sh' => 'СърбохърватÑки', + 'si' => 'СинхалÑки', + 'sk' => 'Словашки', + 'sl' => 'СловенÑки', + 'sm' => 'СамоанÑки', + 'sn' => 'Shona', + 'so' => 'СомалийÑки', + 'sq' => 'ÐлбанÑки', + 'sr' => 'СръбÑки', + 'ss' => 'Суази', + 'st' => 'СеÑуто', + 'su' => 'Sundanese', + 'sv' => 'ШведÑки', + 'sw' => 'Суахили', + 'ta' => 'ТамилÑки', + 'te' => 'Телугу', + 'tg' => 'ТаджикÑки', + 'th' => 'Таи', + 'ti' => 'Tigrinya', + 'tk' => 'ТуркменÑки', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'ТурÑки', + 'ts' => 'Tsonga', + 'tt' => 'ТатарÑки', + 'tw' => 'Twi', + 'ty' => 'ТаитÑнÑки', + 'ug' => 'Uighur', + 'uk' => 'УкраинÑки', + 'ur' => 'Урду', + 'uz' => 'УзбекÑки', + 've' => 'Venda', + 'vi' => 'ВиетнамÑки', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'КитайÑки', + 'zu' => 'ЗулуÑки', +); +?> diff --git a/lib/Pear/I18Nv2/Language/bn.php b/lib/Pear/I18Nv2/Language/bn.php new file mode 100644 index 0000000..533cb37 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/bn.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'বাংলা', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ca.php b/lib/Pear/I18Nv2/Language/ca.php new file mode 100644 index 0000000..5ae81d0 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ca.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Àfar', + 'ab' => 'Abkhaz', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amhàric', + 'an' => 'Aragonese', + 'ar' => 'Àrab', + 'as' => 'Assamès', + 'av' => 'Avaric', + 'ay' => 'Aimara', + 'az' => 'Àzeri', + 'ba' => 'Baixkir', + 'be' => 'Bielorús', + 'bg' => 'Búlgar', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengalí', + 'bo' => 'Tibetà', + 'br' => 'Bretó', + 'bs' => 'Bosnian', + 'ca' => 'Català', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Cors', + 'cr' => 'Cree', + 'cs' => 'Txec', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Gal·lès', + 'da' => 'Danès', + 'de' => 'Alemany', + 'dv' => 'Divehi', + 'dz' => 'Bhutanès', + 'ee' => 'Ewe', + 'el' => 'Grec', + 'en' => 'Anglès', + 'eo' => 'Esperanto', + 'es' => 'Espanyol', + 'et' => 'Estonià', + 'eu' => 'Basc', + 'fa' => 'Persa', + 'ff' => 'Fulah', + 'fi' => 'Finès', + 'fj' => 'Fijià', + 'fo' => 'Feroès', + 'fr' => 'Francès', + 'fy' => 'Frisó', + 'ga' => 'Irlandès', + 'gd' => 'Escocès', + 'gl' => 'Gallec', + 'gn' => 'Guaraní', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebreu', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croat', + 'ht' => 'Haitian', + 'hu' => 'Hongarès', + 'hy' => 'Armeni', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesi', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiak', + 'io' => 'Ido', + 'is' => 'Islandès', + 'it' => 'Italià', + 'iu' => 'Inuktitut', + 'ja' => 'Japonès', + 'jv' => 'Javanès', + 'ka' => 'Georgià', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Greenlandès', + 'km' => 'Cambodjà', + 'kn' => 'Kannada', + 'ko' => 'Coreà', + 'kr' => 'Kanuri', + 'ks' => 'Caixmiri', + 'ku' => 'Kurd', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirguís', + 'la' => 'Llatí', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Laosià', + 'lt' => 'Lituà', + 'lu' => 'Luba-Katanga', + 'lv' => 'Letó', + 'mg' => 'Malgaix', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedoni', + 'ml' => 'Malaialam', + 'mn' => 'Mongol', + 'mo' => 'Moldau', + 'mr' => 'Marathi', + 'ms' => 'Malai', + 'mt' => 'Maltès', + 'my' => 'Birmà', + 'na' => 'Nauruà', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepalès', + 'ng' => 'Ndonga', + 'nl' => 'Neerlandès', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Noruec', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occità', + 'oj' => 'Ojibwa', + 'om' => 'Oromo (afan)', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Panjabi', + 'pi' => 'Pali', + 'pl' => 'Polonès', + 'ps' => 'Paixto', + 'pt' => 'Portuguès', + 'qu' => 'Quètxua', + 'rm' => 'Retoromànic', + 'rn' => 'Kirundi', + 'ro' => 'Romanès', + 'ru' => 'Rus', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sànscrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-croat', + 'si' => 'Sinhalès', + 'sk' => 'Eslovac', + 'sl' => 'Eslovè', + 'sm' => 'Samoà', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanès', + 'sr' => 'Serbi', + 'ss' => 'Siswati', + 'st' => 'Sotho', + 'su' => 'Sundanès', + 'sv' => 'Suec', + 'sw' => 'Swahili', + 'ta' => 'Tàmil', + 'te' => 'Telugu', + 'tg' => 'Tadjik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turcman', + 'tl' => 'Tagàlog', + 'tn' => 'Tswana', + 'to' => 'Tonga', + 'tr' => 'Turc', + 'ts' => 'Tsonga', + 'tt' => 'Tàtar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uigur', + 'uk' => 'Ucraïnès', + 'ur' => 'Urdú', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamita', + 'vo' => 'Volapuk', + 'wa' => 'Walloon', + 'wo' => 'Wòlof', + 'xh' => 'Xosa', + 'yi' => 'Jiddish', + 'yo' => 'Ioruba', + 'za' => 'Zhuang', + 'zh' => 'Xinés', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/cs.php b/lib/Pear/I18Nv2/Language/cs.php new file mode 100644 index 0000000..fc2bb45 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/cs.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'AfarÅ¡tina', + 'ab' => 'AbcházÅ¡tina', + 'ae' => 'Avestan', + 'af' => 'AfrikánÅ¡tina', + 'ak' => 'Akan', + 'am' => 'AmharÅ¡tina', + 'an' => 'Aragonese', + 'ar' => 'ArabÅ¡tina', + 'as' => 'Assaméština', + 'av' => 'Avaric', + 'ay' => 'AymárÅ¡tina', + 'az' => 'AzerbajdžánÅ¡tina', + 'ba' => 'BaskirÅ¡tina', + 'be' => 'BÄ›loruÅ¡tina', + 'bg' => 'BulharÅ¡tina', + 'bh' => 'BiharÅ¡tina', + 'bi' => 'BislámÅ¡tina', + 'bm' => 'Bambara', + 'bn' => 'BengálÅ¡tina', + 'bo' => 'TibetÅ¡tina', + 'br' => 'Bretaňština', + 'bs' => 'Bosnian', + 'ca' => 'KatalánÅ¡tina', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'KorsiÄtina', + 'cr' => 'Cree', + 'cs' => 'ÄŒeÅ¡tina', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'VelÅ¡tina', + 'da' => 'DánÅ¡tina', + 'de' => 'NÄ›mÄina', + 'dv' => 'Divehi', + 'dz' => 'BhútánÅ¡tina', + 'ee' => 'Ewe', + 'el' => 'ŘeÄtina', + 'en' => 'AngliÄtina', + 'eo' => 'Esperanto', + 'es' => 'Å panÄ›lÅ¡tina', + 'et' => 'EstonÅ¡tina', + 'eu' => 'BaskiÄtina', + 'fa' => 'PerÅ¡tina', + 'ff' => 'Fulah', + 'fi' => 'FinÅ¡tina', + 'fj' => 'Fidži', + 'fo' => 'FaerÅ¡tina', + 'fr' => 'FrancouzÅ¡tina', + 'fy' => 'Fríština', + 'ga' => 'IrÅ¡tina', + 'gd' => 'Skotská galÅ¡tina', + 'gl' => 'HaliÄÅ¡tina', + 'gn' => 'GuaranÅ¡tina', + 'gu' => 'GujaratÅ¡tina', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'HebrejÅ¡tina', + 'hi' => 'HindÅ¡tina', + 'ho' => 'Hiri Motu', + 'hr' => 'ChorvatÅ¡tina', + 'ht' => 'Haitian', + 'hu' => 'MaÄarÅ¡tina', + 'hy' => 'ArménÅ¡tina', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonéština', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'InupiakÅ¡tina', + 'io' => 'Ido', + 'is' => 'IslandÅ¡tina', + 'it' => 'ItalÅ¡tina', + 'iu' => 'InuktitutÅ¡tina', + 'ja' => 'JaponÅ¡tina', + 'jv' => 'JavánÅ¡tina', + 'ka' => 'GruzínÅ¡tina', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'KazachÅ¡tina', + 'kl' => 'GrónÅ¡tina', + 'km' => 'Kambodžština', + 'kn' => 'KannadÅ¡tina', + 'ko' => 'KorejÅ¡tina', + 'kr' => 'Kanuri', + 'ks' => 'KaÅ¡mírÅ¡tina', + 'ku' => 'KurdÅ¡tina', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'KirgizÅ¡tina', + 'la' => 'Latina', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'LingalÅ¡tina', + 'lo' => 'LaoÅ¡tina', + 'lt' => 'LitevÅ¡tina', + 'lu' => 'Luba-Katanga', + 'lv' => 'LotyÅ¡tina', + 'mg' => 'MalgaÅ¡tina', + 'mh' => 'Marshallese', + 'mi' => 'MaorÅ¡tina', + 'mk' => 'MakedonÅ¡tina', + 'ml' => 'MalabarÅ¡tina', + 'mn' => 'MongolÅ¡tina', + 'mo' => 'MoldavÅ¡tina', + 'mr' => 'Marathi', + 'ms' => 'MalajÅ¡tina', + 'mt' => 'MaltÅ¡tina', + 'my' => 'BarmÅ¡tina', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'NepálÅ¡tina', + 'ng' => 'Ndonga', + 'nl' => 'HolandÅ¡tina', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'NorÅ¡tina', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan', + 'oj' => 'Ojibwa', + 'om' => 'Oromo (Afan)', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'PaňdžábÅ¡tina', + 'pi' => 'Pali', + 'pl' => 'PolÅ¡tina', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'PortugalÅ¡tina', + 'qu' => 'KeÄuánÅ¡tina', + 'rm' => 'RétorománÅ¡tina', + 'rn' => 'Kirundi', + 'ro' => 'RumunÅ¡tina', + 'ru' => 'RuÅ¡tina', + 'rw' => 'KinyarwandÅ¡tina', + 'sa' => 'Sanskrt', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sangho', + 'sh' => 'SrbochorvatÅ¡tina', + 'si' => 'SinhálÅ¡tina', + 'sk' => 'SlovenÅ¡tina', + 'sl' => 'SlovinÅ¡tina', + 'sm' => 'SamoyÅ¡tina', + 'sn' => 'Shona', + 'so' => 'SomálÅ¡tina', + 'sq' => 'AlbánÅ¡tina', + 'sr' => 'SrbÅ¡tina', + 'ss' => 'SiswatÅ¡tina', + 'st' => 'Sesotho', + 'su' => 'SundanÅ¡tina', + 'sv' => 'Å védÅ¡tina', + 'sw' => 'SvahilÅ¡tina', + 'ta' => 'TamilÅ¡tina', + 'te' => 'TelugÅ¡tina', + 'tg' => 'TádžiÄtina', + 'th' => 'ThajÅ¡tina', + 'ti' => 'TigrinijÅ¡tina', + 'tk' => 'TurkmenÅ¡tina', + 'tl' => 'Tagalog', + 'tn' => 'SetswanÅ¡tina', + 'to' => 'Tonga', + 'tr' => 'TureÄtina', + 'ts' => 'Tsonga', + 'tt' => 'TatarÅ¡tina', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'UighurÅ¡tina', + 'uk' => 'UkrajinÅ¡tina', + 'ur' => 'UrdÅ¡tina', + 'uz' => 'UzbeÄtina', + 've' => 'Venda', + 'vi' => 'VietnamÅ¡tina', + 'vo' => 'Volapuk', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'JidiÅ¡', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'ČínÅ¡tina', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/cy.php b/lib/Pear/I18Nv2/Language/cy.php new file mode 100644 index 0000000..2d500b9 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/cy.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabeg', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Cymraeg', + 'da' => 'Danish', + 'de' => 'Almaeneg', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'Saesneg', + 'eo' => 'Esperanto', + 'es' => 'Sbaeneg', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Ffrangeg', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Eidaleg', + 'iu' => 'Inuktitut', + 'ja' => 'Siapaneeg', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portiwgaleg', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Rwsieg', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Tseineeg', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/da.php b/lib/Pear/I18Nv2/Language/da.php new file mode 100644 index 0000000..5b1efbe --- /dev/null +++ b/lib/Pear/I18Nv2/Language/da.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhasisk', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharisk', + 'an' => 'Aragonesisk', + 'ar' => 'Arabisk', + 'as' => 'Assamesisk', + 'av' => 'Avarisk', + 'ay' => 'Aymara', + 'az' => 'Aserbajdsjan', + 'ba' => 'Bashkir', + 'be' => 'Hviderussisk', + 'bg' => 'Bulgarsk', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengalsk', + 'bo' => 'Tibetansk', + 'br' => 'Bretonsk', + 'bs' => 'Bosnisk', + 'ca' => 'Katalansk', + 'ce' => 'Tjetjensk', + 'ch' => 'Chamorro', + 'co' => 'Korsikansk', + 'cr' => 'Cree', + 'cs' => 'Tjekkisk', + 'cu' => 'Kirkeslavisk', + 'cv' => 'Chuvash', + 'cy' => 'Walisisk', + 'da' => 'Dansk', + 'de' => 'Tysk', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Græsk', + 'en' => 'Engelsk', + 'eo' => 'Esperanto', + 'es' => 'Spansk', + 'et' => 'Estisk', + 'eu' => 'Baskisk', + 'fa' => 'Persisk', + 'ff' => 'Fulah', + 'fi' => 'Finsk', + 'fj' => 'Fijian', + 'fo' => 'Færøsk', + 'fr' => 'Fransk', + 'fy' => 'Frisisk', + 'ga' => 'Irsk', + 'gd' => 'Gælisk (skotsk)', + 'gl' => 'Galicisk', + 'gn' => 'Guarani', + 'gu' => 'Gujaratisk', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebraisk', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Kroatisk', + 'ht' => 'Haitisk', + 'hu' => 'Ungarsk', + 'hy' => 'Armensk', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesisk', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Islandsk', + 'it' => 'Italiensk', + 'iu' => 'Inuktitut', + 'ja' => 'Japansk', + 'jv' => 'Javanesisk', + 'ka' => 'Georgisk', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kasakhisk', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannaresisk', + 'ko' => 'Koreansk', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdisk', + 'kv' => 'Komi', + 'kw' => 'Cornisk', + 'ky' => 'Kirgisisk', + 'la' => 'Latin', + 'lb' => 'Luxembourgsk', + 'lg' => 'Ganda', + 'li' => 'Limburgsk', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Litauisk', + 'lu' => 'Luba-Katanga', + 'lv' => 'Lettisk', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Makedonsk', + 'ml' => 'Malayalam', + 'mn' => 'Mongolsk', + 'mo' => 'Moldovisk', + 'mr' => 'Marathisk', + 'ms' => 'Malay', + 'mt' => 'Maltesisk', + 'my' => 'Burmesisk', + 'na' => 'Nauru', + 'nb' => 'Norsk BokmÃ¥l', + 'nd' => 'Ndebele, Nord', + 'ne' => 'Nepalesisk', + 'ng' => 'Ndonga', + 'nl' => 'Hollandsk', + 'nn' => 'Nynorsk', + 'no' => 'Norsk', + 'nr' => 'Ndebele, Syd', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitansk (efter 1500); Provencalsk', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetisk', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polsk', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugisisk', + 'qu' => 'Quechua', + 'rm' => 'Rætoromansk', + 'rn' => 'Rundi', + 'ro' => 'Rumænsk', + 'ru' => 'Russisk', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinsk', + 'sd' => 'Sindhi', + 'se' => 'Nordsamisk', + 'sg' => 'Sango', + 'sh' => 'Serbokroatisk', + 'si' => 'Singalesisk', + 'sk' => 'Slovakisk', + 'sl' => 'Slovensk', + 'sm' => 'Samoansk', + 'sn' => 'Shona', + 'so' => 'Somalisk', + 'sq' => 'Albansk', + 'sr' => 'Serbisk', + 'ss' => 'Swati', + 'st' => 'Sotho, Southern', + 'su' => 'Sundanesisk', + 'sv' => 'Svensk', + 'sw' => 'Swahili', + 'ta' => 'Tamilsk', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thailandsk', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmensk', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tongaøerne)', + 'tr' => 'Tyrkisk', + 'ts' => 'Tsonga', + 'tt' => 'Tatarisk', + 'tw' => 'Twi', + 'ty' => 'Tahitiansk', + 'ug' => 'Uigurisk', + 'uk' => 'Ukrainsk', + 'ur' => 'Urdu', + 'uz' => 'Usbekisk', + 've' => 'Venda', + 'vi' => 'Vietnamesisk', + 'vo' => 'Volapük', + 'wa' => 'Vallonsk', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Jiddisch', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Kinesisk', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/de.php b/lib/Pear/I18Nv2/Language/de.php new file mode 100644 index 0000000..742f912 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/de.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abchasisch', + 'ae' => 'Avestisch', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharisch', + 'an' => 'Aragonesisch', + 'ar' => 'Arabisch', + 'as' => 'Assamesisch', + 'av' => 'Awarisch', + 'ay' => 'Aymará-Sprache', + 'az' => 'Aserbaidschanisch', + 'ba' => 'Baschkirisch', + 'be' => 'Weißrussisch', + 'bg' => 'Bulgarisch', + 'bh' => 'Biharisch', + 'bi' => 'Bislama', + 'bm' => 'Bambara-Sprache', + 'bn' => 'Bengalisch', + 'bo' => 'Tibetisch', + 'br' => 'Bretonisch', + 'bs' => 'Bosnisch', + 'ca' => 'Katalanisch', + 'ce' => 'Tschetschenisch', + 'ch' => 'Chamorro-Sprache', + 'co' => 'Korsisch', + 'cr' => 'Cree', + 'cs' => 'Tschechisch', + 'cu' => 'Kirchenslawisch', + 'cv' => 'Tschuwaschisch', + 'cy' => 'Kymrisch', + 'da' => 'Dänisch', + 'de' => 'Deutsch', + 'dv' => 'Maledivisch', + 'dz' => 'Bhutanisch', + 'ee' => 'Ewe-Sprache', + 'el' => 'Griechisch', + 'en' => 'Englisch', + 'eo' => 'Esperanto', + 'es' => 'Spanisch', + 'et' => 'Estnisch', + 'eu' => 'Baskisch', + 'fa' => 'Persisch', + 'ff' => 'Ful', + 'fi' => 'Finnisch', + 'fj' => 'Fidschianisch', + 'fo' => 'Färöisch', + 'fr' => 'Französisch', + 'fy' => 'Friesisch', + 'ga' => 'Irisch', + 'gd' => 'Schottisch-Gälisch', + 'gl' => 'Galizisch', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebräisch', + 'hi' => 'Hindi', + 'ho' => 'Hiri-Motu', + 'hr' => 'Kroatisch', + 'ht' => 'Kreolisch', + 'hu' => 'Ungarisch', + 'hy' => 'Armenisch', + 'hz' => 'Herero-Sprache', + 'ia' => 'Interlingua', + 'id' => 'Indonesisch', + 'ie' => 'Interlingue', + 'ig' => 'Igbo-Sprache', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiak', + 'io' => 'Ido-Sprache', + 'is' => 'Isländisch', + 'it' => 'Italienisch', + 'iu' => 'Inukitut', + 'ja' => 'Japanisch', + 'jv' => 'Javanisch', + 'ka' => 'Georgisch', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu-Sprache', + 'kj' => 'Kwanyama', + 'kk' => 'Kasachisch', + 'kl' => 'Grönländisch', + 'km' => 'Kambodschanisch', + 'kn' => 'Kannada', + 'ko' => 'Koreanisch', + 'kr' => 'Kanuri-Sprache', + 'ks' => 'Kaschmirisch', + 'ku' => 'Kurdisch', + 'kv' => 'Komi-Sprache', + 'kw' => 'Kornisch', + 'ky' => 'Kirgisisch', + 'la' => 'Latein', + 'lb' => 'Luxemburgisch', + 'lg' => 'Ganda-Sprache', + 'li' => 'Limburgisch', + 'ln' => 'Lingala', + 'lo' => 'Laotisch', + 'lt' => 'Litauisch', + 'lu' => 'Luba', + 'lv' => 'Lettisch', + 'mg' => 'Madagassisch', + 'mh' => 'Marschallesisch', + 'mi' => 'Maori', + 'mk' => 'Mazedonisch', + 'ml' => 'Malayalam', + 'mn' => 'Mongolisch', + 'mo' => 'Moldauisch', + 'mr' => 'Marathi', + 'ms' => 'Malaiisch', + 'mt' => 'Maltesisch', + 'my' => 'Birmanisch', + 'na' => 'Nauruisch', + 'nb' => 'Norwegisch BokmÃ¥l', + 'nd' => 'Ndebele-Sprache (Nord)', + 'ne' => 'Nepalesisch', + 'ng' => 'Ndonga', + 'nl' => 'Niederländisch', + 'nn' => 'Norwegisch Nynorsk', + 'no' => 'Norwegisch', + 'nr' => 'Ndebele-Sprache (Süd)', + 'nv' => 'Navajo-Sprache', + 'ny' => 'Chewa-Sprache', + 'oc' => 'Okzitanisch', + 'oj' => 'Ojibwa-Sprache', + 'om' => 'Oromo', + 'or' => 'Orija', + 'os' => 'Ossetisch', + 'pa' => 'Pandschabisch', + 'pi' => 'Pali', + 'pl' => 'Polnisch', + 'ps' => 'Afghanisch (Paschtu)', + 'pt' => 'Portugiesisch', + 'qu' => 'Quechua', + 'rm' => 'Rätoromanisch', + 'rn' => 'Rundi-Sprache', + 'ro' => 'Rumänisch', + 'ru' => 'Russisch', + 'rw' => 'Ruandisch', + 'sa' => 'Sanskrit', + 'sc' => 'Sardisch', + 'sd' => 'Sindhi', + 'se' => 'Nord-Samisch', + 'sg' => 'Sango', + 'sh' => 'Serbo-Kroatisch', + 'si' => 'Singhalesisch', + 'sk' => 'Slowakisch', + 'sl' => 'Slowenisch', + 'sm' => 'Samoanisch', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanisch', + 'sr' => 'Serbisch', + 'ss' => 'Swazi', + 'st' => 'Süd-Sotho-Sprache', + 'su' => 'Sudanesisch', + 'sv' => 'Schwedisch', + 'sw' => 'Suaheli', + 'ta' => 'Tamilisch', + 'te' => 'Telugu', + 'tg' => 'Tadschikisch', + 'th' => 'Thai', + 'ti' => 'Tigrinja', + 'tk' => 'Turkmenisch', + 'tl' => 'Tagalog', + 'tn' => 'Tswana-Sprache', + 'to' => 'Tongaisch', + 'tr' => 'Türkisch', + 'ts' => 'Tsonga', + 'tt' => 'Tatarisch', + 'tw' => 'Twi', + 'ty' => 'Tahitisch', + 'ug' => 'Uigurisch', + 'uk' => 'Ukrainisch', + 'ur' => 'Urdu', + 'uz' => 'Usbekisch', + 've' => 'Venda-Sprache', + 'vi' => 'Vietnamesisch', + 'vo' => 'Volapük', + 'wa' => 'Wallonisch', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Jiddisch', + 'yo' => 'Joruba', + 'za' => 'Zhuang', + 'zh' => 'Chinesisch', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/dv.php b/lib/Pear/I18Nv2/Language/dv.php new file mode 100644 index 0000000..388d2a0 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/dv.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/dz.php b/lib/Pear/I18Nv2/Language/dz.php new file mode 100644 index 0000000..fec705a --- /dev/null +++ b/lib/Pear/I18Nv2/Language/dz.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ཨེ་ར་སྦིག', + 'as' => 'ཨ་ས་མི་སི', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'བི་ཧ་ལི', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'བེངྒ་ལི', + 'bo' => 'བོད་à½', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ཅེཀ', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'ཌེ་ནིཤ', + 'de' => 'ཇཱར་མཱན', + 'dv' => 'དི་བེ་ཧི', + 'dz' => 'རྫོང་à½', + 'ee' => 'Ewe', + 'el' => 'གིརིཀ', + 'en' => 'ཨིང་ལིཤ', + 'eo' => 'Esperanto', + 'es' => 'སིཔེ་ནིཤ', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'པར་ཤི་ཡན', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'ཕེ་རེནཆེ', + 'fy' => 'Frisian', + 'ga' => 'ཨའི་རིཤ', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'ཧི་བུརུ', + 'hi' => 'ཧིན་དི', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ཨི་ཊ་ལི་རན', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'à½à½ºà¼‹à½˜à½¢', + 'kn' => 'ཀ་ན་ཌ', + 'ko' => 'ཀོ་རིཡན', + 'kr' => 'Kanuri', + 'ks' => 'ཀེཤ་མི་རི', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'ལའོ', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'མ་ལ་ཡ་ལམ', + 'mn' => 'སོག་པོའི་à½', + 'mo' => 'Moldavian', + 'mr' => 'མ་ར་à½à½²', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'བར་མིསི', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ནེ་པ་ལི', + 'ng' => 'Ndonga', + 'nl' => 'ཌཆ', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'ནོར་à½à½²à¼‹à½‡à½²à¼‹à½¡à½“', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'ཨོ་རི་ཡ', + 'os' => 'Ossetic', + 'pa' => 'པཱན་ཇ་བི', + 'pi' => 'པ་ལི', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'ར་ཤི་ཡན', + 'rw' => 'Kinyarwanda', + 'sa' => 'སཾསà¾à¾²à¾€à½', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'སིན་ཧ་ལིསི', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'à½à¼‹à½˜à½²à½£', + 'te' => 'à½à½ºà¼‹à½£à½´à¼‹à½‚ུ', + 'tg' => 'Tajik', + 'th' => 'à½à½±à½ à½º', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'ཨུར་དུ', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'རགྱ་མི་à½', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/el.php b/lib/Pear/I18Nv2/Language/el.php new file mode 100644 index 0000000..17e728b --- /dev/null +++ b/lib/Pear/I18Nv2/Language/el.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ΑÏαβικά', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'ΛευκοÏωσικά', + 'bg' => 'ΒουλγαÏικά', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Θιβετιανά', + 'br' => 'Breton', + 'bs' => 'Βοσνιακά', + 'ca' => 'Καταλανικά', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'ΚοÏσικανικά', + 'cr' => 'Cree', + 'cs' => 'Τσεχικά', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Ουαλικά', + 'da' => 'Δανικά', + 'de' => 'ΓεÏμανικά', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Ελληνικά', + 'en' => 'Αγγλικά', + 'eo' => 'Esperanto', + 'es' => 'Ισπανικά', + 'et' => 'Εσθονικά', + 'eu' => 'Βασκικά', + 'fa' => 'ΠεÏσικά', + 'ff' => 'Fulah', + 'fi' => 'Φινλανδικά', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Γαλλικά', + 'fy' => 'Frisian', + 'ga' => 'ΙÏλανδικά', + 'gd' => 'Σκωτικά Κελτικά', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'ΕβÏαϊκά', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'ΚÏοατικά', + 'ht' => 'Haitian', + 'hu' => 'ΟυγγÏικά', + 'hy' => 'ΑÏμενικά', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Ινδονησιακά', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Ισλανδικά', + 'it' => 'Ιταλικά', + 'iu' => 'Inuktitut', + 'ja' => 'Ιαπωνικά', + 'jv' => 'Javanese', + 'ka' => 'ΓεωÏγιανά', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'ΚοÏεατικά', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Λατινικά', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Λιθουανικά', + 'lu' => 'Luba-Katanga', + 'lv' => 'Λετονικά', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Σλαβομακεδονικά', + 'ml' => 'Malayalam', + 'mn' => 'Μογγολικά', + 'mo' => 'Μολδαβικά', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Μαλτεζικά', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Ολλανδικά', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'ÎοÏβηγικά', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Πολωνικά', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'ΠοÏτογαλικά', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Ρουμανικά', + 'ru' => 'Ρωσικά', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'ΣεÏβοκÏοατικά', + 'si' => 'Sinhalese', + 'sk' => 'Σλοβακικά', + 'sl' => 'Σλοβενικά', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Αλβανικά', + 'sr' => 'ΣεÏβικά', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Σουηδικά', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'ΤουÏκικά', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'ΟυκÏανικά', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Βιετναμεζικά', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Ιουδαϊκά', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Κινεζικά', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/en.php b/lib/Pear/I18Nv2/Language/en.php new file mode 100644 index 0000000..48c0eb3 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/en.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/eo.php b/lib/Pear/I18Nv2/Language/eo.php new file mode 100644 index 0000000..72492b5 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/eo.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afara', + 'ab' => 'AbÄ¥aza', + 'ae' => 'Avestan', + 'af' => 'Afrikansa', + 'ak' => 'Akan', + 'am' => 'Amhara', + 'an' => 'Aragonese', + 'ar' => 'Araba', + 'as' => 'Asama', + 'av' => 'Avaric', + 'ay' => 'Ajmara', + 'az' => 'AzerbajÄana', + 'ba' => 'BaÅkira', + 'be' => 'Belorusa', + 'bg' => 'Bulgara', + 'bh' => 'Bihara', + 'bi' => 'Bislamo', + 'bm' => 'Bambara', + 'bn' => 'Bengala', + 'bo' => 'Tibeta', + 'br' => 'Bretona', + 'bs' => 'Bosnian', + 'ca' => 'Kataluna', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Korsika', + 'cr' => 'Cree', + 'cs' => 'ĈeÄ¥a', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Kimra', + 'da' => 'Dana', + 'de' => 'Germana', + 'dv' => 'Divehi', + 'dz' => 'Dzonko', + 'ee' => 'Ewe', + 'el' => 'Greka', + 'en' => 'Angla', + 'eo' => 'Esperanto', + 'es' => 'Hispana', + 'et' => 'Estona', + 'eu' => 'EÅ­ska', + 'fa' => 'Persa', + 'ff' => 'Fulah', + 'fi' => 'Finna', + 'fj' => 'FiÄia', + 'fo' => 'Feroa', + 'fr' => 'Franca', + 'fy' => 'Frisa', + 'ga' => 'Irlanda', + 'gd' => 'Gaela', + 'gl' => 'Galega', + 'gn' => 'Gvarania', + 'gu' => 'GuÄarata', + 'gv' => 'Manx', + 'ha' => 'HaÅ­sa', + 'he' => 'Hebrea', + 'hi' => 'Hinda', + 'ho' => 'Hiri Motu', + 'hr' => 'Kroata', + 'ht' => 'Haitian', + 'hu' => 'Hungara', + 'hy' => 'Armena', + 'hz' => 'Herero', + 'ia' => 'Interlingvao', + 'id' => 'Indonezia', + 'ie' => 'Okcidentalo', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Eskima', + 'io' => 'Ido', + 'is' => 'Islanda', + 'it' => 'Itala', + 'iu' => 'Inuita', + 'ja' => 'Japana', + 'jv' => 'Java', + 'ka' => 'Kartvela', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'KazaÄ¥a', + 'kl' => 'Gronlanda', + 'km' => 'Kmera', + 'kn' => 'Kanara', + 'ko' => 'Korea', + 'kr' => 'Kanuri', + 'ks' => 'KaÅmira', + 'ku' => 'Kurda', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirgiza', + 'la' => 'Latino', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'LaÅ­a', + 'lt' => 'Litova', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latva', + 'mg' => 'Malagasa', + 'mh' => 'Marshallese', + 'mi' => 'Maoria', + 'mk' => 'Makedona', + 'ml' => 'Malajalama', + 'mn' => 'Mongola', + 'mo' => 'Moldavian', + 'mr' => 'Marata', + 'ms' => 'Malaja', + 'mt' => 'Malta', + 'my' => 'Birma', + 'na' => 'Naura', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepala', + 'ng' => 'Ndonga', + 'nl' => 'Nederlanda', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norvega', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Okcitana', + 'oj' => 'Ojibwa', + 'om' => 'Oroma', + 'or' => 'Orijo', + 'os' => 'Ossetic', + 'pa' => 'PanÄaba', + 'pi' => 'Pali', + 'pl' => 'Pola', + 'ps' => 'PaÅtua', + 'pt' => 'Portugala', + 'qu' => 'Keĉua', + 'rm' => 'Romanĉa', + 'rn' => 'Burunda', + 'ro' => 'Rumana', + 'ru' => 'Rusa', + 'rw' => 'Ruanda', + 'sa' => 'Sanskrito', + 'sc' => 'Sardinian', + 'sd' => 'Sinda', + 'se' => 'Northern Sami', + 'sg' => 'Sangoa', + 'sh' => 'Serbo-Kroata', + 'si' => 'Sinhala', + 'sk' => 'Slovaka', + 'sl' => 'Slovena', + 'sm' => 'Samoa', + 'sn' => 'Åœona', + 'so' => 'Somala', + 'sq' => 'Albana', + 'sr' => 'Serba', + 'ss' => 'Svazia', + 'st' => 'Sota', + 'su' => 'Sunda', + 'sv' => 'Sveda', + 'sw' => 'Svahila', + 'ta' => 'Tamila', + 'te' => 'Telugua', + 'tg' => 'TaÄika', + 'th' => 'Taja', + 'ti' => 'Tigraja', + 'tk' => 'Turkmena', + 'tl' => 'Filipina', + 'tn' => 'Cvana', + 'to' => 'Tongaa', + 'tr' => 'Turka', + 'ts' => 'Conga', + 'tt' => 'Tatara', + 'tw' => 'Akana', + 'ty' => 'Tahitian', + 'ug' => 'Ujgura', + 'uk' => 'Ukraina', + 'ur' => 'Urduo', + 'uz' => 'Uzbeka', + 've' => 'Venda', + 'vi' => 'Vjetnama', + 'vo' => 'Volapuko', + 'wa' => 'Walloon', + 'wo' => 'Volofa', + 'xh' => 'Ksosa', + 'yi' => 'Jida', + 'yo' => 'Joruba', + 'za' => 'Äœuanga', + 'zh' => 'Ĉina', + 'zu' => 'Zulua', +); +?> diff --git a/lib/Pear/I18Nv2/Language/es.php b/lib/Pear/I18Nv2/Language/es.php new file mode 100644 index 0000000..d032af8 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/es.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhaziano', + 'ae' => 'Avéstico', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amárico', + 'an' => 'Aragonés', + 'ar' => 'Ãrabe', + 'as' => 'Asamés', + 'av' => 'Avar', + 'ay' => 'Aymara', + 'az' => 'Azerí', + 'ba' => 'Bashkir', + 'be' => 'Bielorruso', + 'bg' => 'Búlgaro', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengalí', + 'bo' => 'Tibetano', + 'br' => 'Bretón', + 'bs' => 'Bosnio', + 'ca' => 'Catalán', + 'ce' => 'Checheno', + 'ch' => 'Chamorro', + 'co' => 'Corso', + 'cr' => 'Cree', + 'cs' => 'Checo', + 'cu' => 'Eslavo eclesiástico', + 'cv' => 'Chuvash', + 'cy' => 'Galés', + 'da' => 'Danés', + 'de' => 'Alemán', + 'dv' => 'Divehi', + 'dz' => 'Bhutaní', + 'ee' => 'Ewe', + 'el' => 'Griego', + 'en' => 'Inglés', + 'eo' => 'Esperanto', + 'es' => 'Español', + 'et' => 'Estonio', + 'eu' => 'Vasco', + 'fa' => 'Farsi', + 'ff' => 'Fula', + 'fi' => 'Finlandés', + 'fj' => 'Fidji', + 'fo' => 'Feroés', + 'fr' => 'Francés', + 'fy' => 'Frisón', + 'ga' => 'Irlandés', + 'gd' => 'Gaélico escocés', + 'gl' => 'Gallego', + 'gn' => 'Guaraní', + 'gu' => 'Gujarati', + 'gv' => 'Gaélico manés', + 'ha' => 'Hausa', + 'he' => 'Hebreo', + 'hi' => 'Hindi', + 'ho' => 'Hiri motu', + 'hr' => 'Croata', + 'ht' => 'Haitiano', + 'hu' => 'Húngaro', + 'hy' => 'Armenio', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesio', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan yi', + 'ik' => 'Inupiak', + 'io' => 'Ido', + 'is' => 'Islandés', + 'it' => 'Italiano', + 'iu' => 'Inuktitut', + 'ja' => 'Japonés', + 'jv' => 'Javanés', + 'ka' => 'Georgiano', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazajo', + 'kl' => 'Groenlandés', + 'km' => 'Jemer', + 'kn' => 'Canarés', + 'ko' => 'Coreano', + 'kr' => 'Kanuri', + 'ks' => 'Cachemiro', + 'ku' => 'Kurdo', + 'kv' => 'Komi', + 'kw' => 'Córnico', + 'ky' => 'Kirghiz', + 'la' => 'Latín', + 'lb' => 'Luxemburgués', + 'lg' => 'Ganda', + 'li' => 'Limburgués', + 'ln' => 'Lingala', + 'lo' => 'Laosiano', + 'lt' => 'Lituano', + 'lu' => 'Luba-katanga', + 'lv' => 'Letón', + 'mg' => 'Malgache', + 'mh' => 'Marshalés', + 'mi' => 'Maorí', + 'mk' => 'Macedonio', + 'ml' => 'Malayalam', + 'mn' => 'Mongol', + 'mo' => 'Moldavo', + 'mr' => 'Marathi', + 'ms' => 'Malayo', + 'mt' => 'Maltés', + 'my' => 'Birmano', + 'na' => 'Nauruano', + 'nb' => 'Bokmal noruego', + 'nd' => 'Ndebele septentrional', + 'ne' => 'Nepalí', + 'ng' => 'Ndonga', + 'nl' => 'Holandés', + 'nn' => 'Nynorsk noruego', + 'no' => 'Noruego', + 'nr' => 'Ndebele meridional', + 'nv' => 'Navajo', + 'ny' => 'Nyanja', + 'oc' => 'Occitano (después del 1500)', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Osético', + 'pa' => 'Punjabí', + 'pi' => 'Pali', + 'pl' => 'Polaco', + 'ps' => 'Pashto', + 'pt' => 'Portugués', + 'qu' => 'Quechua', + 'rm' => 'Reto-romance', + 'rn' => 'Kiroundi', + 'ro' => 'Rumano', + 'ru' => 'Ruso', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sánscrito', + 'sc' => 'Sardo', + 'sd' => 'Sindhi', + 'se' => 'Sami septentrional', + 'sg' => 'Sango', + 'sh' => 'Serbo-croata', + 'si' => 'Singalés', + 'sk' => 'Eslovaco', + 'sl' => 'Esloveno', + 'sm' => 'Samoano', + 'sn' => 'Shona', + 'so' => 'Somalí', + 'sq' => 'Albanés', + 'sr' => 'Serbio', + 'ss' => 'Siswati', + 'st' => 'Sesotho', + 'su' => 'Sundanés', + 'sv' => 'Sueco', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tayiko', + 'th' => 'Tailandés', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmeno', + 'tl' => 'Tagalo', + 'tn' => 'Setchwana', + 'to' => 'Tonga (Islas Tonga)', + 'tr' => 'Turco', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitiano', + 'ug' => 'Uigur', + 'uk' => 'Ucraniano', + 'ur' => 'Urdu', + 'uz' => 'Uzbeko', + 've' => 'Venda', + 'vi' => 'Vietnamita', + 'vo' => 'Volapuk', + 'wa' => 'Valón', + 'wo' => 'Uolof', + 'xh' => 'Xhosa', + 'yi' => 'Yidish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chino', + 'zu' => 'Zulú', +); +?> diff --git a/lib/Pear/I18Nv2/Language/et.php b/lib/Pear/I18Nv2/Language/et.php new file mode 100644 index 0000000..61370b2 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/et.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Araabia', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgaaria', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'TÅ¡ehhi', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Taani', + 'de' => 'Saksa', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Kreeka', + 'en' => 'Inglise', + 'eo' => 'Esperanto', + 'es' => 'Hispaania', + 'et' => 'Eesti', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Soome', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Prantsuse', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Heebrea', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Horvaadi', + 'ht' => 'Haitian', + 'hu' => 'Ungari', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Itaalia', + 'iu' => 'Inuktitut', + 'ja' => 'Jaapani', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korea', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Leedu', + 'lu' => 'Luba-Katanga', + 'lv' => 'Läti', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Hollandi', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norra', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Poola', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugali', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Rumeenia', + 'ru' => 'Vene', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovaki', + 'sl' => 'Sloveeni', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Rootsi', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Türgi', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Hiina', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/eu.php b/lib/Pear/I18Nv2/Language/eu.php new file mode 100644 index 0000000..9a8520e --- /dev/null +++ b/lib/Pear/I18Nv2/Language/eu.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Euskara', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/fa.php b/lib/Pear/I18Nv2/Language/fa.php new file mode 100644 index 0000000..7a75c4d --- /dev/null +++ b/lib/Pear/I18Nv2/Language/fa.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Ø¢Ùاری', + 'ab' => 'آبخازی', + 'ae' => 'اوستایی', + 'af' => 'Ø¢Ùریکانس', + 'ak' => 'Akan', + 'am' => 'امهری', + 'an' => 'Aragonese', + 'ar' => 'عربی', + 'as' => 'آسامی', + 'av' => 'آواری', + 'ay' => 'آیمارایی', + 'az' => 'ترکی آذربایجانی', + 'ba' => 'باشغیری', + 'be' => 'بلوروسی', + 'bg' => 'بلغاری', + 'bh' => 'بیهاری', + 'bi' => 'بیسلاما', + 'bm' => 'بامبارایی', + 'bn' => 'بنگالی', + 'bo' => 'تبتی', + 'br' => 'برتانیایی', + 'bs' => 'بوسنیایی', + 'ca' => 'کاتالونیایی', + 'ce' => 'Ú†Ú†Ù†ÛŒ', + 'ch' => 'چامورویی', + 'co' => 'Corsican', + 'cr' => 'کریایی', + 'cs' => 'Ú†Ú©ÛŒ', + 'cu' => 'اسلاوی کلیسایی', + 'cv' => 'چوواشی', + 'cy' => 'ویلزی', + 'da' => 'دانمارکی', + 'de' => 'آلمانی', + 'dv' => 'Divehi', + 'dz' => 'جونخایی', + 'ee' => 'اوه‌ای', + 'el' => 'یونانی', + 'en' => 'انگلیسی', + 'eo' => 'اسپرانتو', + 'es' => 'اسپانیایی', + 'et' => 'استونیایی', + 'eu' => 'باسکی', + 'fa' => 'Ùارسی', + 'ff' => 'Ùولایی', + 'fi' => 'Ùنلاندی', + 'fj' => 'Ùیجیایی', + 'fo' => 'Ùارویی', + 'fr' => 'Ùرانسوی', + 'fy' => 'Ùریزی', + 'ga' => 'ایرلندی', + 'gd' => 'گیلی اسکاتلندی', + 'gl' => 'گالیسیایی', + 'gn' => 'گوارانی', + 'gu' => 'گجراتی', + 'gv' => 'مانی', + 'ha' => 'هوسیایی', + 'he' => 'عبری', + 'hi' => 'هندی', + 'ho' => 'Hiri Motu', + 'hr' => 'کرواتی', + 'ht' => 'هائیتیایی', + 'hu' => 'مجاری', + 'hy' => 'ارمنی', + 'hz' => 'هریرویی', + 'ia' => 'میان‌زبان', + 'id' => 'اندونزیایی', + 'ie' => 'Interlingue', + 'ig' => 'ایگبویی', + 'ii' => 'یی سیچوان', + 'ik' => 'اینوپیک', + 'io' => 'Ido', + 'is' => 'ایسلندی', + 'it' => 'ایتالیایی', + 'iu' => 'اینوکتیتوت', + 'ja' => 'ژاپنی', + 'jv' => 'جاوه‌ای', + 'ka' => 'گرجی', + 'kg' => 'کنگویی', + 'ki' => 'کیکویویی', + 'kj' => 'Kuanyama', + 'kk' => 'قزاقی', + 'kl' => 'گرینلندی', + 'km' => 'خمری', + 'kn' => 'کاناده‌ای', + 'ko' => 'کره‌ای', + 'kr' => 'کانوریایی', + 'ks' => 'کشمیری', + 'ku' => 'کردی', + 'kv' => 'کومیایی', + 'kw' => 'کرنوالی', + 'ky' => 'قرقیزی', + 'la' => 'لاتینی', + 'lb' => 'لوگزامبورگی', + 'lg' => 'گاندایی', + 'li' => 'لیمبورگی', + 'ln' => 'لینگالا', + 'lo' => 'لائوسی', + 'lt' => 'لیتوانیایی', + 'lu' => 'لوباییâ€Ú©Ø§ØªØ§Ù†Ú¯Ø§', + 'lv' => 'لتونیایی', + 'mg' => 'مالاگاسیایی', + 'mh' => 'مارشالی', + 'mi' => 'مائوریایی', + 'mk' => 'مقدونی', + 'ml' => 'مالایالامی', + 'mn' => 'مغولی', + 'mo' => 'مولداویایی', + 'mr' => 'مراتی', + 'ms' => 'مالزیایی', + 'mt' => 'مالتی', + 'my' => 'برمه‌ای', + 'na' => 'نائورویی', + 'nb' => 'بوکسمال نروژی', + 'nd' => 'انده‌بله‌ای شمالی', + 'ne' => 'نپالی', + 'ng' => 'ندونگایی', + 'nl' => 'هلندی', + 'nn' => 'نرس جدید نروژی', + 'no' => 'نروژی', + 'nr' => 'انده‌بله‌ای جنوبی', + 'nv' => 'ناواهویی', + 'ny' => 'نیانجایی؛ چوایی', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'اوجیبوایی', + 'om' => 'Oromo', + 'or' => 'اوریه‌ای', + 'os' => 'آسی', + 'pa' => 'پنجابی', + 'pi' => 'پالی', + 'pl' => 'لهستانی', + 'ps' => 'پشتو', + 'pt' => 'پرتغالی', + 'qu' => 'کچوایی', + 'rm' => 'رتوâ€Ø±ÙˆÙ…یایی', + 'rn' => 'روندیایی', + 'ro' => 'رومانیایی', + 'ru' => 'روسی', + 'rw' => 'کینیارواندایی', + 'sa' => 'سنسکریت', + 'sc' => 'ساردینیایی', + 'sd' => 'سندی', + 'se' => 'Northern Sami', + 'sg' => 'سانگویی', + 'sh' => 'صرب Ùˆ کرواتی', + 'si' => 'سینهالی', + 'sk' => 'اسلواکی', + 'sl' => 'اسلووینیایی', + 'sm' => 'ساموآیی', + 'sn' => 'شونایی', + 'so' => 'سومالیایی', + 'sq' => 'آلبانیایی', + 'sr' => 'صربی', + 'ss' => 'Swati', + 'st' => 'سوتویی جنوبی', + 'su' => 'سوندایی', + 'sv' => 'سوئدی', + 'sw' => 'سواحلی', + 'ta' => 'تامیلی', + 'te' => 'تلوگویی', + 'tg' => 'تاجیکی', + 'th' => 'تایلندی', + 'ti' => 'تیگرینیایی', + 'tk' => 'ترکمنی', + 'tl' => 'تاگالوگی', + 'tn' => 'تسوانایی', + 'to' => 'تونگایی (جزایر تونگا)', + 'tr' => 'ترکی استانبولی', + 'ts' => 'تسونگایی', + 'tt' => 'تاتاری', + 'tw' => 'توی‌یایی', + 'ty' => 'تاهیتیایی', + 'ug' => 'اویغوری', + 'uk' => 'اوکراینی', + 'ur' => 'اردو', + 'uz' => 'ازبکی', + 've' => 'وندایی', + 'vi' => 'ویتنامی', + 'vo' => 'ولاپوک', + 'wa' => 'والونی', + 'wo' => 'ولوÙÛŒ', + 'xh' => 'خوسایی', + 'yi' => 'یدی', + 'yo' => 'یوروبایی', + 'za' => 'چوانگی', + 'zh' => 'چینی', + 'zu' => 'زولویی', +); +?> diff --git a/lib/Pear/I18Nv2/Language/fi.php b/lib/Pear/I18Nv2/Language/fi.php new file mode 100644 index 0000000..0d29fd8 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/fi.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abhaasi', + 'ae' => 'Avesta', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amhara', + 'an' => 'Aragonia', + 'ar' => 'Arabia', + 'as' => 'Assami', + 'av' => 'Avaari', + 'ay' => 'Aymara', + 'az' => 'Azeri', + 'ba' => 'Baski', + 'be' => 'Valkovenäjä', + 'bg' => 'Bulgaria', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tiibet', + 'br' => 'Bretoni', + 'bs' => 'Bosnia', + 'ca' => 'Katalaani', + 'ce' => 'TÅ¡etÅ¡eeni', + 'ch' => 'Chamorro', + 'co' => 'Korsika', + 'cr' => 'Cree', + 'cs' => 'TÅ¡ekki', + 'cu' => 'Kirkkoslaavi', + 'cv' => 'TÅ¡uvassi', + 'cy' => 'Kymri', + 'da' => 'Tanska', + 'de' => 'Saksa', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Kreikka', + 'en' => 'Englanti', + 'eo' => 'Esperanto', + 'es' => 'Espanja', + 'et' => 'Viro', + 'eu' => 'Baski', + 'fa' => 'Farsi; persia', + 'ff' => 'Fulani', + 'fi' => 'Suomi', + 'fj' => 'Fidži', + 'fo' => 'Fääri', + 'fr' => 'Ranska', + 'fy' => 'Friisi', + 'ga' => 'Iiri', + 'gd' => 'Gaeli', + 'gl' => 'Galicia', + 'gn' => 'Guarani', + 'gu' => 'Gudžarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Heprea', + 'hi' => 'Hindi', + 'ho' => 'Hiri-motu', + 'hr' => 'Kroatia', + 'ht' => 'Haiti', + 'hu' => 'Unkari', + 'hy' => 'Armenia', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesia', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuanin-yi', + 'ik' => 'Iñupiak', + 'io' => 'Ido', + 'is' => 'Islanti', + 'it' => 'Italia', + 'iu' => 'Inuktitut', + 'ja' => 'Japani', + 'jv' => 'Jaava', + 'ka' => 'Georgia', + 'kg' => 'Kongo', + 'ki' => 'Kikuju', + 'kj' => 'Kwanyama', + 'kk' => 'Kazakki', + 'kl' => 'Kalaallisut; grönlanti', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korea', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdi', + 'kv' => 'Komi', + 'kw' => 'Korni', + 'ky' => 'Kirgiisi', + 'la' => 'Latina', + 'lb' => 'Luxemburg', + 'lg' => 'Ganda', + 'li' => 'Limburg', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Liettua', + 'lu' => 'Luba (Katanga)', + 'lv' => 'Latvia', + 'mg' => 'Malagassi', + 'mh' => 'Marshall', + 'mi' => 'Maori', + 'mk' => 'Makedonia', + 'ml' => 'Malayalam', + 'mn' => 'Mongoli', + 'mo' => 'Moldavia', + 'mr' => 'Marathi', + 'ms' => 'Malaiji', + 'mt' => 'Malta', + 'my' => 'Burma', + 'na' => 'Nauru', + 'nb' => 'Norja (bokmÃ¥l)', + 'nd' => 'Ndebele, pohjois-', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Hollanti', + 'nn' => 'Norja (nynorsk)', + 'no' => 'Norja', + 'nr' => 'Ndebele, etelä-', + 'nv' => 'Navajo', + 'ny' => 'Nyanja', + 'oc' => 'Oksitaani', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Osseetti', + 'pa' => 'Panjabi', + 'pi' => 'Paali', + 'pl' => 'Puola', + 'ps' => 'PaÅ¡to', + 'pt' => 'Portugali', + 'qu' => 'Quechua', + 'rm' => 'Retoromaani', + 'rn' => 'Rundi', + 'ro' => 'Romania', + 'ru' => 'Venäjä', + 'rw' => 'Ruanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardi', + 'sd' => 'Sindhi', + 'se' => 'Saame, pohjois-', + 'sg' => 'Sango', + 'sh' => 'Serbokroatia', + 'si' => 'Sinhali', + 'sk' => 'Slovakki', + 'sl' => 'Sloveeni', + 'sm' => 'Samoa', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albania', + 'sr' => 'Serbia', + 'ss' => 'Swazi', + 'st' => 'Sotho, etelä-', + 'su' => 'Sunda', + 'sv' => 'Ruotsi', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tadžikki', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmeeni', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga)', + 'tr' => 'Turkki', + 'ts' => 'Tsonga', + 'tt' => 'Tataari', + 'tw' => 'Twi', + 'ty' => 'Tahiti', + 'ug' => 'Uiguuri', + 'uk' => 'Ukraina', + 'ur' => 'Urdu', + 'uz' => 'Uzbekki', + 've' => 'Venda', + 'vi' => 'Vietnam', + 'vo' => 'Volapük', + 'wa' => 'Valloni', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'JiddiÅ¡', + 'yo' => 'Joruba', + 'za' => 'Zhuang', + 'zh' => 'Kiina', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/fo.php b/lib/Pear/I18Nv2/Language/fo.php new file mode 100644 index 0000000..6891a0c --- /dev/null +++ b/lib/Pear/I18Nv2/Language/fo.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Føroyskt', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/fr.php b/lib/Pear/I18Nv2/Language/fr.php new file mode 100644 index 0000000..78b10c3 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/fr.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhaze', + 'ae' => 'Avestique', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharique', + 'an' => 'Aragonais', + 'ar' => 'Arabe', + 'as' => 'Assamais', + 'av' => 'Avar', + 'ay' => 'Aymara', + 'az' => 'Azéri', + 'ba' => 'Bachkir', + 'be' => 'Biélorusse', + 'bg' => 'Bulgare', + 'bh' => 'Bihari', + 'bi' => 'Bichlamar', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibétain', + 'br' => 'Breton', + 'bs' => 'Bosniaque', + 'ca' => 'Catalan', + 'ce' => 'Tchétchène', + 'ch' => 'Chamorro', + 'co' => 'Corse', + 'cr' => 'Cree', + 'cs' => 'Tchèque', + 'cu' => 'Slavon d’église', + 'cv' => 'Tchouvache', + 'cy' => 'Gallois', + 'da' => 'Danois', + 'de' => 'Allemand', + 'dv' => 'Maldivien', + 'dz' => 'Dzongkha', + 'ee' => 'Éwé', + 'el' => 'Grec', + 'en' => 'Anglais', + 'eo' => 'Espéranto', + 'es' => 'Espagnol', + 'et' => 'Estonien', + 'eu' => 'Basque', + 'fa' => 'Persan', + 'ff' => 'Peul', + 'fi' => 'Finnois', + 'fj' => 'Fidjien', + 'fo' => 'Féroïen', + 'fr' => 'Français', + 'fy' => 'Frison', + 'ga' => 'Irlandais', + 'gd' => 'Gaélique écossais', + 'gl' => 'Galicien', + 'gn' => 'Guarani', + 'gu' => 'Goudjrati', + 'gv' => 'Manx', + 'ha' => 'Haoussa', + 'he' => 'Hébreu', + 'hi' => 'Hindi', + 'ho' => 'Hiri motu', + 'hr' => 'Croate', + 'ht' => 'Haïtien', + 'hu' => 'Hongrois', + 'hy' => 'Arménien', + 'hz' => 'Héréro', + 'ia' => 'Interlingua', + 'id' => 'Indonésien', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Yi de Sichuan', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Islandais', + 'it' => 'Italien', + 'iu' => 'Inuktitut', + 'ja' => 'Japonais', + 'jv' => 'Javanais', + 'ka' => 'Géorgien', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Groenlandais', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Coréen', + 'kr' => 'Kanouri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurde', + 'kv' => 'Komi', + 'kw' => 'Cornique', + 'ky' => 'Kirghize', + 'la' => 'Latin', + 'lb' => 'Luxembourgeois', + 'lg' => 'Ganda', + 'li' => 'Limbourgeois', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lituanien', + 'lu' => 'Luba-katanga', + 'lv' => 'Letton', + 'mg' => 'Malgache', + 'mh' => 'Marshall', + 'mi' => 'Maori', + 'mk' => 'Macédonien', + 'ml' => 'Malayalam', + 'mn' => 'Mongol', + 'mo' => 'Moldave', + 'mr' => 'Marathe', + 'ms' => 'Malais', + 'mt' => 'Maltais', + 'my' => 'Birman', + 'na' => 'Nauruan', + 'nb' => 'BokmÃ¥l norvégien', + 'nd' => 'Ndébélé du Nord', + 'ne' => 'Népalais', + 'ng' => 'Ndonga', + 'nl' => 'Néerlandais', + 'nn' => 'Nynorsk norvégien', + 'no' => 'Norvégien', + 'nr' => 'Ndébélé du Sud', + 'nv' => 'Navaho', + 'ny' => 'Nyanja', + 'oc' => 'Occitan (après 1500)', + 'oj' => 'Ojibwa', + 'om' => 'Galla', + 'or' => 'Oriya', + 'os' => 'Ossète', + 'pa' => 'Pendjabi', + 'pi' => 'Pali', + 'pl' => 'Polonais', + 'ps' => 'Pachto', + 'pt' => 'Portugais', + 'qu' => 'Quechua', + 'rm' => 'Rhéto-roman', + 'rn' => 'Roundi', + 'ro' => 'Roumain', + 'ru' => 'Russe', + 'rw' => 'Rwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sarde', + 'sd' => 'Sindhi', + 'se' => 'Sami du Nord', + 'sg' => 'Sango', + 'sh' => 'Serbo-croate', + 'si' => 'Singhalais', + 'sk' => 'Slovaque', + 'sl' => 'Slovène', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanais', + 'sr' => 'Serbe', + 'ss' => 'Swati', + 'st' => 'Sotho du Sud', + 'su' => 'Soundanais', + 'sv' => 'Suédois', + 'sw' => 'Swahili', + 'ta' => 'Tamoul', + 'te' => 'Télougou', + 'tg' => 'Tadjik', + 'th' => 'Thaï', + 'ti' => 'Tigrigna', + 'tk' => 'Turkmène', + 'tl' => 'Tagalog', + 'tn' => 'Setswana', + 'to' => 'Tongan (ÃŽles Tonga)', + 'tr' => 'Turc', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitien', + 'ug' => 'Ouïgour', + 'uk' => 'Ukrainien', + 'ur' => 'Ourdou', + 'uz' => 'Ouzbek', + 've' => 'Venda', + 'vi' => 'Vietnamien', + 'vo' => 'Volapük', + 'wa' => 'Wallon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinois', + 'zu' => 'Zoulou', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ga.php b/lib/Pear/I18Nv2/Language/ga.php new file mode 100644 index 0000000..42ddc65 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ga.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abcáisis', + 'ae' => 'Aivéistis', + 'af' => 'Afracáinis', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Araibis', + 'as' => 'Asaimis', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Asarbaiseáinis', + 'ba' => 'Baiscíris', + 'be' => 'Bealarúisis', + 'bg' => 'Bulgáiris', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Beangálais', + 'bo' => 'Tibéadais', + 'br' => 'Briotáinis', + 'bs' => 'Boisnis', + 'ca' => 'Catalóinis', + 'ce' => 'Sisinis', + 'ch' => 'Chamorro', + 'co' => 'Corsaicis', + 'cr' => 'Craíais', + 'cs' => 'Seicis', + 'cu' => 'Slavais na hEaglaise', + 'cv' => 'Suvaisis', + 'cy' => 'Breatnais', + 'da' => 'Danmhairgis', + 'de' => 'Gearmáinis', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Gréigis', + 'en' => 'Béarla', + 'eo' => 'Esperanto', + 'es' => 'Spáinnis', + 'et' => 'Eastóinis', + 'eu' => 'Bascais', + 'fa' => 'Peirsis', + 'ff' => 'Fulah', + 'fi' => 'Fionnlainnis', + 'fj' => 'Fidsis', + 'fo' => 'Faróis', + 'fr' => 'Fraincis', + 'fy' => 'Freaslainnais', + 'ga' => 'Gaeilge', + 'gd' => 'Gaeilge na hAlban', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gúisearáitis', + 'gv' => 'Mannainis', + 'ha' => 'Hausa', + 'he' => 'Eabhrais', + 'hi' => 'Hiondúis', + 'ho' => 'Hiri Motu', + 'hr' => 'Cróitis', + 'ht' => 'Haitian', + 'hu' => 'Ungáiris', + 'hy' => 'Airméinis', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indinéisis', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Ãoslainnais', + 'it' => 'Iodáilis', + 'iu' => 'Ionúitis', + 'ja' => 'Seapáinis', + 'jv' => 'Iávais', + 'ka' => 'Seoirsis', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Casachais', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Cannadais', + 'ko' => 'Cóiréis', + 'kr' => 'Kanuri', + 'ks' => 'Caismíris', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornais', + 'ky' => 'Cirgeasais', + 'la' => 'Laidin', + 'lb' => 'Leitseabuirgis', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Laosais', + 'lt' => 'Liotuáinis', + 'lu' => 'Luba-Katanga', + 'lv' => 'Laitvis', + 'mg' => 'Malagásais', + 'mh' => 'Marshallese', + 'mi' => 'Maorais', + 'mk' => 'Macadóinis', + 'ml' => 'Mailéalaimis', + 'mn' => 'Mongóilis', + 'mo' => 'Moldáivis', + 'mr' => 'Maraitis', + 'ms' => 'Malay', + 'mt' => 'Maltais', + 'my' => 'Burmais', + 'na' => 'Nárúis', + 'nb' => 'Ioruais BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Neipealais', + 'ng' => 'Ndonga', + 'nl' => 'Ollainnais', + 'nn' => 'Ioruais Nynorsk', + 'no' => 'Ioruais', + 'nr' => 'South Ndebele', + 'nv' => 'Navachóis', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Ocatáinis (tar éis 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Óiséitis', + 'pa' => 'Puinseaibis', + 'pi' => 'Pali', + 'pl' => 'Polainnis', + 'ps' => 'Paisteo', + 'pt' => 'Portaingéilis', + 'qu' => 'Ceatsuais', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romáinis', + 'ru' => 'Rúisis', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanscrait', + 'sc' => 'Sairdínis', + 'sd' => 'Sindis', + 'se' => 'Sáimis Thuaidh', + 'sg' => 'Sango', + 'sh' => 'Seirbea-Chróitis', + 'si' => 'Sinhalese', + 'sk' => 'Slóvacais', + 'sl' => 'Slóvéinis', + 'sm' => 'Samóis', + 'sn' => 'Shona', + 'so' => 'Somálais', + 'sq' => 'Albáinis', + 'sr' => 'Seirbis', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Sualainnis', + 'sw' => 'Svahaílis', + 'ta' => 'Tamailis', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Téalainnis', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagálaigis', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Tuircis', + 'ts' => 'Tsonga', + 'tt' => 'Tatarais', + 'tw' => 'Twi', + 'ty' => 'Taihítis', + 'ug' => 'Uighur', + 'uk' => 'Úcráinis', + 'ur' => 'Urdais', + 'uz' => 'Úisbéicis', + 've' => 'Venda', + 'vi' => 'Vítneamais', + 'vo' => 'Volapük', + 'wa' => 'Vallúnais', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Giúdais', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Sínis', + 'zu' => 'Súlúis', +); +?> diff --git a/lib/Pear/I18Nv2/Language/gl.php b/lib/Pear/I18Nv2/Language/gl.php new file mode 100644 index 0000000..7c3dbb4 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/gl.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galego', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/gu.php b/lib/Pear/I18Nv2/Language/gu.php new file mode 100644 index 0000000..5d2f018 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/gu.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'ગà«àªœàª°àª¾àª¤à«€', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/gv.php b/lib/Pear/I18Nv2/Language/gv.php new file mode 100644 index 0000000..92c78c2 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/gv.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Gaelg', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/he.php b/lib/Pear/I18Nv2/Language/he.php new file mode 100644 index 0000000..b7793f4 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/he.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => '×תיופית', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => '×פריקנית', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ערבית', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'בולגרית', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'בנגלית', + 'bo' => 'טיבטית', + 'br' => 'Breton', + 'bs' => 'בוסנית', + 'ca' => 'קטלונית', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'צ׳כית', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'וולשית', + 'da' => 'דנית', + 'de' => 'גרמנית', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'יוונית', + 'en' => '×נגלית', + 'eo' => '×ספרנטו', + 'es' => 'ספרדית', + 'et' => '×סטונית', + 'eu' => 'בסקית', + 'fa' => 'פרסית', + 'ff' => 'Fulah', + 'fi' => 'פינית', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'צרפתית', + 'fy' => 'Frisian', + 'ga' => '×ירית', + 'gd' => 'סקוטית ×’×לית', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'עברית', + 'hi' => 'הינדית', + 'ho' => 'Hiri Motu', + 'hr' => 'קרו×טית', + 'ht' => 'Haitian', + 'hu' => 'הונגרית', + 'hy' => '×רמנית', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => '×ינדונזית', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => '×יסלנדית', + 'it' => '×יטלקית', + 'iu' => 'Inuktitut', + 'ja' => 'יפנית', + 'jv' => 'Javanese', + 'ka' => 'גרוזינית', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'קורי×נית', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'לטינית', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'ליט×ית', + 'lu' => 'Luba-Katanga', + 'lv' => 'לטבית', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'מ×ורית', + 'mk' => 'מקדונית', + 'ml' => 'Malayalam', + 'mn' => 'מונגולית', + 'mo' => 'מולדבית', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'מלטזית', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'נפ×לית', + 'ng' => 'Ndonga', + 'nl' => 'הולנדית', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'נורווגית', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'פולנית', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'פורטוגזית', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'רומנית', + 'ru' => 'רוסית', + 'rw' => 'Kinyarwanda', + 'sa' => 'סנסקרית', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'סרבו-קרו×טית', + 'si' => 'Sinhalese', + 'sk' => 'סלובקית', + 'sl' => 'סלובנית', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'סרבית', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'שוודית', + 'sw' => 'סווהילית', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'ת××™', + 'ti' => 'Tigrinya', + 'tk' => 'טורקמנית', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'טורקית', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => '×וקר×ינית', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'יידיש', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'סינית', + 'zu' => 'זולו', +); +?> diff --git a/lib/Pear/I18Nv2/Language/hi.php b/lib/Pear/I18Nv2/Language/hi.php new file mode 100644 index 0000000..cac2388 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/hi.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'अफ़ार', + 'ab' => 'अबà¥à¤–ाज़ियनà¥', + 'ae' => 'Avestan', + 'af' => 'अफà¥à¤°à¥€à¤•à¥€', + 'ak' => 'Akan', + 'am' => 'अमà¥à¤¹à¤¾à¤°à¤¿à¤•à¥', + 'an' => 'Aragonese', + 'ar' => 'अरबी', + 'as' => 'असामी', + 'av' => 'Avaric', + 'ay' => 'आयमारा', + 'az' => 'अज़रबैंजानी', + 'ba' => 'बशख़िर', + 'be' => 'बैलोरूशियनà¥', + 'bg' => 'बलà¥à¤—ेरियनà¥', + 'bh' => 'बिहारी', + 'bi' => 'बिसà¥à¤²à¤¾à¤®à¤¾', + 'bm' => 'Bambara', + 'bn' => 'बà¤à¤—ाली', + 'bo' => 'तिबà¥à¤¬à¤¤à¥€', + 'br' => 'बà¥à¤°à¥‡à¤Ÿà¤¨', + 'bs' => 'Bosnian', + 'ca' => 'कातालान', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'कोरà¥à¤¸à¥€à¤•à¤¨', + 'cr' => 'Cree', + 'cs' => 'चेक', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'वेलà¥à¤¶', + 'da' => 'डैनीश', + 'de' => 'ज़रà¥à¤®à¤¨', + 'dv' => 'Divehi', + 'dz' => 'भà¥à¤Ÿà¤¾à¤¨à¥€', + 'ee' => 'Ewe', + 'el' => 'गà¥à¤°à¥€à¤•', + 'en' => 'अंगà¥à¤°à¥‡à¤œà¥€', + 'eo' => 'à¤à¤¸à¥à¤ªà¥‡à¤°à¤¾à¤¨à¥à¤¤à¥‹', + 'es' => 'सà¥à¤ªà¥‡à¤¨à¤¿à¤¶', + 'et' => 'à¤à¤¸à¥à¤¤à¥‹à¤¨à¤¿à¤¯à¤¨à¥', + 'eu' => 'बासà¥à¤•à¥', + 'fa' => 'परà¥à¤¶à¤¿à¤¯à¤¨à¥', + 'ff' => 'Fulah', + 'fi' => 'फिनिश', + 'fj' => 'फ़ीजी', + 'fo' => 'फिरोज़ी', + 'fr' => 'फà¥à¤°à¥‡à¤‚च', + 'fy' => 'फà¥à¤°à¥€à¤œà¤¼à¤¨à¥', + 'ga' => 'आईरिश', + 'gd' => 'सà¥à¤•à¤¾à¤Ÿà¥à¤¸à¥ गायेलिकà¥', + 'gl' => 'गैलिशियनà¥', + 'gn' => 'गà¥à¤†à¤°à¤¾à¤¨à¥€', + 'gu' => 'गà¥à¥›à¤°à¤¾à¤¤à¥€', + 'gv' => 'Manx', + 'ha' => 'होउसा', + 'he' => 'हिबà¥à¤°à¥€à¤Š', + 'hi' => 'हिंदी', + 'ho' => 'Hiri Motu', + 'hr' => 'कà¥à¤°à¥‹à¤à¤¶à¤¨à¥', + 'ht' => 'Haitian', + 'hu' => 'हंगेरी', + 'hy' => 'अरमेनियनà¥', + 'hz' => 'Herero', + 'ia' => 'ईनà¥à¤Ÿà¤°à¤²à¤¿à¤‚गà¥à¤†', + 'id' => 'इनà¥à¤¡à¥‹à¤¨à¥‡à¤¶à¤¿à¤¯à¤¨à¥', + 'ie' => 'ईनà¥à¤Ÿà¤°à¤²à¤¿à¤‚गà¥à¤‡', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'इनà¥à¤ªà¤¿à¤¯à¤¾à¤•à¥', + 'io' => 'Ido', + 'is' => 'आईसà¥à¤²à¥ˆà¤‚डिकà¥', + 'it' => 'ईटालियनà¥', + 'iu' => 'इनूकीटूतà¥', + 'ja' => 'जापानी', + 'jv' => 'जावानीस', + 'ka' => 'जॉरà¥à¤œà¥€à¤¯à¤¨à¥', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'कज़ाख', + 'kl' => 'गà¥à¤°à¥€à¤¨à¤²à¥ˆà¤‚डिक', + 'km' => 'कैमà¥à¤¬à¥‹à¤¡à¤¿à¤¯à¤¨à¥', + 'kn' => 'कनà¥à¤¨à¤¡à¤¼', + 'ko' => 'कोरीयनà¥', + 'kr' => 'Kanuri', + 'ks' => 'काशà¥à¤®à¤¿à¤°à¥€', + 'ku' => 'कà¥à¤°à¤¦à¥€à¤¶', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'किरघिज़', + 'la' => 'लैटीन', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'लिंगाला', + 'lo' => 'लाओथीयनà¥', + 'lt' => 'लिथà¥à¤¨à¤¿à¤¯à¤¨à¥', + 'lu' => 'Luba-Katanga', + 'lv' => 'लाटवियनॠ(लेटà¥à¤Ÿà¥€à¤¶)', + 'mg' => 'मालागासी', + 'mh' => 'Marshallese', + 'mi' => 'मेओरी', + 'mk' => 'मैसेडोनियनà¥', + 'ml' => 'मलयालम', + 'mn' => 'मोंगोलियन', + 'mo' => 'मोलडावियनà¥', + 'mr' => 'मराठी', + 'ms' => 'मलय', + 'mt' => 'मालटिसà¥', + 'my' => 'बरà¥à¤²à¤¿à¤¸', + 'na' => 'नायरू', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'नेपाली', + 'ng' => 'Ndonga', + 'nl' => 'डचà¥', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'नारà¥à¤µà¥‡à¤œà¥€à¤¯à¤¨à¥', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ओसीटान', + 'oj' => 'Ojibwa', + 'om' => 'ओरोमो (अफ़ान)', + 'or' => 'उड़िया', + 'os' => 'Ossetic', + 'pa' => 'पंजाबी', + 'pi' => 'Pali', + 'pl' => 'पॉलिश', + 'ps' => 'पॉशतो (पà¥à¤¶à¤¤à¥‹)', + 'pt' => 'पà¥à¤°à¥à¤¤à¥à¤—ी', + 'qu' => 'कà¥à¤µà¥‡à¤¶à¥à¤†', + 'rm' => 'रहेयà¥à¤Ÿà¥‹-रोमानà¥à¤¸', + 'rn' => 'किरूनà¥à¤¦à¥€', + 'ro' => 'रूमानीयनà¥', + 'ru' => 'रà¥à¤¸à¥€', + 'rw' => 'किनà¥à¤¯à¤¾à¤°à¤µà¤¾à¤£à¥à¤¡à¤¾', + 'sa' => 'संसà¥à¤•à¥ƒà¤¤', + 'sc' => 'Sardinian', + 'sd' => 'सिनà¥à¤§à¥€', + 'se' => 'Northern Sami', + 'sg' => 'साà¤à¤—à¥à¤°à¥‹', + 'sh' => 'सेरà¥à¤¬à¥‹-कà¥à¤°à¥‹à¤à¤¶à¤¨à¥', + 'si' => 'शिंघालीसà¥', + 'sk' => 'सà¥à¤²à¥‹à¤µà¤¾à¤•à¥', + 'sl' => 'सà¥à¤²à¥‹à¤µà¥‡à¤¨à¤¿à¤¯à¤¨à¥', + 'sm' => 'सामोन', + 'sn' => 'सोणा', + 'so' => 'सोमाली', + 'sq' => 'अलà¥à¤¬à¥‡à¤¨à¤¿à¤¯à¤¨à¥', + 'sr' => 'सरà¥à¤¬à¤¿à¤¯à¤¨à¥', + 'ss' => 'सीसà¥à¤µà¤¾à¤Ÿà¤¿', + 'st' => 'सेसोथो', + 'su' => 'सà¥à¤¨à¥à¤¦à¤¾à¤¨à¥€à¤¸', + 'sv' => 'सà¥à¤µà¤¿à¤¡à¤¿à¤¶', + 'sw' => 'सà¥à¤µà¤¾à¤¹à¤¿à¤²à¥€', + 'ta' => 'तमिल', + 'te' => 'तेलेगà¥', + 'tg' => 'ताजिकà¥', + 'th' => 'थाई', + 'ti' => 'तिगà¥à¤°à¥€à¤¨à¥à¤¯à¤¾', + 'tk' => 'तà¥à¤•à¥à¤°à¤®à¥‡à¤¨', + 'tl' => 'तागालोग', + 'tn' => 'सेतà¥à¤¸à¥à¤µà¤¾à¤¨à¤¾', + 'to' => 'टोंगा', + 'tr' => 'तà¥à¤•à¥à¤°à¥€à¤¶', + 'ts' => 'सोंगा', + 'tt' => 'टाटर', + 'tw' => 'टà¥à¤µà¥€', + 'ty' => 'Tahitian', + 'ug' => 'उईघà¥à¤°', + 'uk' => 'यूकà¥à¤°à¥‡à¤¨à¤¿à¤¯à¤¨à¥', + 'ur' => 'ऊरà¥à¤¦à¥', + 'uz' => 'उज़बेकà¥', + 've' => 'Venda', + 'vi' => 'वियेतनामी', + 'vo' => 'वोलापà¥à¤•', + 'wa' => 'Walloon', + 'wo' => 'वोलोफ', + 'xh' => 'षोसा', + 'yi' => 'येहà¥à¤¦à¥€', + 'yo' => 'योरूबा', + 'za' => 'ज़à¥à¤†à¤‚ग', + 'zh' => 'चीनी', + 'zu' => 'ज़à¥à¤²à¥‚', +); +?> diff --git a/lib/Pear/I18Nv2/Language/hr.php b/lib/Pear/I18Nv2/Language/hr.php new file mode 100644 index 0000000..0d261a3 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/hr.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arapski', + 'as' => 'Assamese', + 'av' => 'Avarski', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Bjeloruski', + 'bg' => 'Bugarski', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ÄŒeÅ¡ki', + 'cu' => 'Crkvenoslavenski', + 'cv' => 'Chuvash', + 'cy' => 'VelÅ¡ki', + 'da' => 'Danski', + 'de' => 'NjemaÄki', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'GrÄki', + 'en' => 'Engleski', + 'eo' => 'Esperanto', + 'es' => 'Å panjolski', + 'et' => 'Estonijski', + 'eu' => 'Basque', + 'fa' => 'Perzijski', + 'ff' => 'Fulah', + 'fi' => 'Finski', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Francuski', + 'fy' => 'Frizijski', + 'ga' => 'Irski', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrejski', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Hrvatski', + 'ht' => 'Haitian', + 'hu' => 'MaÄ‘arski', + 'hy' => 'Armenski', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Islandski', + 'it' => 'Talijanski', + 'iu' => 'Inuktitut', + 'ja' => 'Japanski', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Kmerski', + 'kn' => 'Kannada', + 'ko' => 'Korejski', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latinski', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Litvanski', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvijski', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Makedonski', + 'ml' => 'Malayalam', + 'mn' => 'Mongolski', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'MalteÅ¡ki', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepalski', + 'ng' => 'Ndonga', + 'nl' => 'Nizozemski', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'NorveÅ¡ki', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Poljski', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugalski', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Rumunjski', + 'ru' => 'Ruski', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'SlovaÄki', + 'sl' => 'Slovenski', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanski', + 'sr' => 'Srpski', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Å vedski', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turski', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrajinski', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vijetnamski', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Kineski', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/hu.php b/lib/Pear/I18Nv2/Language/hu.php new file mode 100644 index 0000000..e5f116b --- /dev/null +++ b/lib/Pear/I18Nv2/Language/hu.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abház', + 'ae' => 'Avestan', + 'af' => 'Afrikai', + 'ak' => 'Akan', + 'am' => 'Amhara', + 'an' => 'Aragonese', + 'ar' => 'Arab', + 'as' => 'Asszámi', + 'av' => 'Avaric', + 'ay' => 'Ajmara', + 'az' => 'Azerbajdzsáni', + 'ba' => 'Baskír', + 'be' => 'Belorusz', + 'bg' => 'Bolgár', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengáli', + 'bo' => 'Tibeti', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Katalán', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Korzikai', + 'cr' => 'Cree', + 'cs' => 'Cseh', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Walesi', + 'da' => 'Dán', + 'de' => 'Német', + 'dv' => 'Divehi', + 'dz' => 'Butáni', + 'ee' => 'Ewe', + 'el' => 'Görög', + 'en' => 'Angol', + 'eo' => 'Eszperantó', + 'es' => 'Spanyol', + 'et' => 'Észt', + 'eu' => 'Baszk', + 'fa' => 'Perzsa', + 'ff' => 'Fulah', + 'fi' => 'Finn', + 'fj' => 'Fidzsi', + 'fo' => 'Feröeri', + 'fr' => 'Francia', + 'fy' => 'Fríz', + 'ga' => 'Ãr', + 'gd' => 'Skót (gael)', + 'gl' => 'Galíciai', + 'gn' => 'Guarani', + 'gu' => 'Gudzsaráti', + 'gv' => 'Manx', + 'ha' => 'Hausza', + 'he' => 'Héber', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Horvát', + 'ht' => 'Haitian', + 'hu' => 'Magyar', + 'hy' => 'Örmény', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonéz', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiak', + 'io' => 'Ido', + 'is' => 'Izlandi', + 'it' => 'Olasz', + 'iu' => 'Inuktitut', + 'ja' => 'Japán', + 'jv' => 'Jávai', + 'ka' => 'Grúz', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazah', + 'kl' => 'Grönlandi', + 'km' => 'Kambodzsai', + 'kn' => 'Kannada', + 'ko' => 'Koreai', + 'kr' => 'Kanuri', + 'ks' => 'Kasmíri', + 'ku' => 'Kurd', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirgiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Laoszi', + 'lt' => 'Litván', + 'lu' => 'Luba-Katanga', + 'lv' => 'Lett', + 'mg' => 'Madagaszkári', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedón', + 'ml' => 'Malajalam', + 'mn' => 'Mongol', + 'mo' => 'Moldvai', + 'mr' => 'Marati', + 'ms' => 'Maláj', + 'mt' => 'Máltai', + 'my' => 'Burmai', + 'na' => 'Naurui', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepáli', + 'ng' => 'Ndonga', + 'nl' => 'Holland', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norvég', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Okszitán', + 'oj' => 'Ojibwa', + 'om' => 'Oromói', + 'or' => 'Orija', + 'os' => 'Ossetic', + 'pa' => 'Pandzsábi', + 'pi' => 'Pali', + 'pl' => 'Lengyel', + 'ps' => 'Pastu (afgán)', + 'pt' => 'Portugál', + 'qu' => 'Kecsua', + 'rm' => 'Rétoromán', + 'rn' => 'Kirundi', + 'ro' => 'Román', + 'ru' => 'Orosz', + 'rw' => 'Kiruanda', + 'sa' => 'Szanszkrit', + 'sc' => 'Sardinian', + 'sd' => 'Szindi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Szerb-horvát', + 'si' => 'Szingaléz', + 'sk' => 'Szlovák', + 'sl' => 'Szlovén', + 'sm' => 'Szamoai', + 'sn' => 'Sona', + 'so' => 'Szomáli', + 'sq' => 'Albán', + 'sr' => 'Szerb', + 'ss' => 'Sziszuati', + 'st' => 'Szeszotó', + 'su' => 'Szundanéz', + 'sv' => 'Svéd', + 'sw' => 'Szuahéli', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tadzsik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Türkmén', + 'tl' => 'Tagalog', + 'tn' => 'Szecsuáni', + 'to' => 'Tonga', + 'tr' => 'Török', + 'ts' => 'Conga', + 'tt' => 'Tatár', + 'tw' => 'Tui', + 'ty' => 'Tahitian', + 'ug' => 'Ujgur', + 'uk' => 'Ukrán', + 'ur' => 'Urdu', + 'uz' => 'Ãœzbég', + 've' => 'Venda', + 'vi' => 'Vietnámi', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Volof', + 'xh' => 'Hosza', + 'yi' => 'Zsidó', + 'yo' => 'Joruba', + 'za' => 'Zsuang', + 'zh' => 'Kínai', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/hy.php b/lib/Pear/I18Nv2/Language/hy.php new file mode 100644 index 0000000..447e700 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/hy.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Õ€Õ¡ÕµÕ¥Ö€Õ§Õ¶', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/id.php b/lib/Pear/I18Nv2/Language/id.php new file mode 100644 index 0000000..b1ef754 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/id.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhaz', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharik', + 'an' => 'Aragonese', + 'ar' => 'Arab', + 'as' => 'Assam', + 'av' => 'Avarik', + 'ay' => 'Aymara', + 'az' => 'Azerbaijan', + 'ba' => 'Bashkir', + 'be' => 'Belarusia', + 'bg' => 'Bulgaria', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengal', + 'bo' => 'Tibet', + 'br' => 'Breton', + 'bs' => 'Bosnia', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Korsika', + 'cr' => 'Cree', + 'cs' => 'Ceko', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Denmark', + 'de' => 'Jerman', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Yunani', + 'en' => 'Inggris', + 'eo' => 'Esperanto', + 'es' => 'Spanyol', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persia', + 'ff' => 'Fulah', + 'fi' => 'Finlandia', + 'fj' => 'Fiji', + 'fo' => 'Faro', + 'fr' => 'Perancis', + 'fy' => 'Frisi', + 'ga' => 'Irlandia', + 'gd' => 'Gaelik Skotlandia', + 'gl' => 'Gallegan', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Ibrani', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Kroasia', + 'ht' => 'Haitian', + 'hu' => 'Hungaria', + 'hy' => 'Armenia', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Bahasa Indonesia', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Jawa', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korea', + 'kr' => 'Kanuri', + 'ks' => 'Kashmir', + 'ku' => 'Kurdi', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourg', + 'lg' => 'Ganda', + 'li' => 'Limburg', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuania', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasi', + 'mh' => 'Marshall', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burma', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepal', + 'ng' => 'Ndonga', + 'nl' => 'Belanda', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugis', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundan', + 'sv' => 'Swedia', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Cina', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/is.php b/lib/Pear/I18Nv2/Language/is.php new file mode 100644 index 0000000..f5a8368 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/is.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkasíska', + 'ae' => 'Avestíska', + 'af' => 'Afríkanska', + 'ak' => 'Akan', + 'am' => 'Amharíska', + 'an' => 'Aragonska', + 'ar' => 'Arabíska', + 'as' => 'Assamska', + 'av' => 'Avaríska', + 'ay' => 'Aímara', + 'az' => 'Aserska', + 'ba' => 'Baskír', + 'be' => 'Hvítrússneska', + 'bg' => 'Búlgarska', + 'bh' => 'Bíharí', + 'bi' => 'Bíslama', + 'bm' => 'Bambara', + 'bn' => 'Bengalska', + 'bo' => 'Tíbeska', + 'br' => 'Bretónska', + 'bs' => 'Bosníska', + 'ca' => 'Katalónska', + 'ce' => 'Tsjetsjenska', + 'ch' => 'Kamorró', + 'co' => 'Korsíska', + 'cr' => 'Krí', + 'cs' => 'Tékkneska', + 'cu' => 'Kirkjuslavneska', + 'cv' => 'Sjúvas', + 'cy' => 'Velska', + 'da' => 'Danska', + 'de' => 'Þýska', + 'dv' => 'Dívehí', + 'dz' => 'Dsongka', + 'ee' => 'Eve', + 'el' => 'Nýgríska (1453-)', + 'en' => 'Enska', + 'eo' => 'Esperantó', + 'es' => 'Spænska', + 'et' => 'Eistneska', + 'eu' => 'Baskneska', + 'fa' => 'Persneska', + 'ff' => 'Fúla', + 'fi' => 'Finnska', + 'fj' => 'Fídjeyska', + 'fo' => 'Færeyska', + 'fr' => 'Franska', + 'fy' => 'Frísneska', + 'ga' => 'Ãrska', + 'gd' => 'Skosk gelíska', + 'gl' => 'Gallegska', + 'gn' => 'Gvaraní', + 'gu' => 'Gújaratí', + 'gv' => 'Manx', + 'ha' => 'Hása', + 'he' => 'Hebreska', + 'hi' => 'Hindí', + 'ho' => 'Hírímótú', + 'hr' => 'Króatíska', + 'ht' => 'Haítíska', + 'hu' => 'Ungverska', + 'hy' => 'Armenska', + 'hz' => 'Hereró', + 'ia' => 'Interlingva', + 'id' => 'Indónesíska', + 'ie' => 'Interlingva', + 'ig' => 'Ãgbó', + 'ii' => 'Sísúanjí', + 'ik' => 'Ãnúpíak', + 'io' => 'Ãdó', + 'is' => 'Ãslenska', + 'it' => 'Ãtalska', + 'iu' => 'Inúktitút', + 'ja' => 'Japanska', + 'jv' => 'Javanska', + 'ka' => 'Georgíska', + 'kg' => 'Kongó', + 'ki' => 'Kíkújú', + 'kj' => 'Kúanjama', + 'kk' => 'Kasakska', + 'kl' => 'Grænlenska', + 'km' => 'Kmer', + 'kn' => 'Kannada', + 'ko' => 'Kóreska', + 'kr' => 'Kanúrí', + 'ks' => 'Kasmírska', + 'ku' => 'Kúrdneska', + 'kv' => 'Komíska', + 'kw' => 'Korníska', + 'ky' => 'Kirgiska', + 'la' => 'Latína', + 'lb' => 'Lúxemborgíska', + 'lg' => 'Ganda', + 'li' => 'Limbúrgíska', + 'ln' => 'Lingala', + 'lo' => 'Laó', + 'lt' => 'Litháíska', + 'lu' => 'Lúbakatanga', + 'lv' => 'Lettneska', + 'mg' => 'Malagasíska', + 'mh' => 'Marshallska', + 'mi' => 'Maórí', + 'mk' => 'Makedónska', + 'ml' => 'Malajalam', + 'mn' => 'Mongólska', + 'mo' => 'Moldóvska', + 'mr' => 'Maratí', + 'ms' => 'Malaíska', + 'mt' => 'Maltneska', + 'my' => 'Burmneska', + 'na' => 'Nárúska', + 'nb' => 'Norskt bókmál', + 'nd' => 'Norðurndebele', + 'ne' => 'Nepalska', + 'ng' => 'Ndonga', + 'nl' => 'Hollenska', + 'nn' => 'Nýnorska', + 'no' => 'Norska', + 'nr' => 'Suðurndebele', + 'nv' => 'Navahó', + 'ny' => 'Njanja; Sísjeva; Sjeva', + 'oc' => 'Okkitíska (eftir 1500); Próvensalska', + 'oj' => 'Ojibva', + 'om' => 'Órómó', + 'or' => 'Óría', + 'os' => 'Ossetíska', + 'pa' => 'Púnjabí', + 'pi' => 'Palí', + 'pl' => 'Pólska', + 'ps' => 'Pastú', + 'pt' => 'Portúgalska', + 'qu' => 'Kvesjúa', + 'rm' => 'Retórómanska', + 'rn' => 'Rúndí', + 'ro' => 'Rúmenska', + 'ru' => 'Rússneska', + 'rw' => 'Kínjarvanda', + 'sa' => 'Sanskrít', + 'sc' => 'Sardínska', + 'sd' => 'Sindí', + 'se' => 'Norðursamíska', + 'sg' => 'Sangó', + 'sh' => 'Serbókróatíska', + 'si' => 'Singalesíska', + 'sk' => 'Slóvakíska', + 'sl' => 'Slóvenska', + 'sm' => 'Samóska', + 'sn' => 'Sínótíbesk mál (önnur)', + 'so' => 'Sómalska', + 'sq' => 'Albanska', + 'sr' => 'Serbneska', + 'ss' => 'Svatí', + 'st' => 'Suðursótó', + 'su' => 'Súndanska', + 'sv' => 'Sænska', + 'sw' => 'Svahílí', + 'ta' => 'Tamílska', + 'te' => 'Telúgú', + 'tg' => 'Tadsjikska', + 'th' => 'Taílenska', + 'ti' => 'Tígrinja', + 'tk' => 'Túrkmenska', + 'tl' => 'Tagalog', + 'tn' => 'Tsúana', + 'to' => 'Tongverska', + 'tr' => 'Tyrkneska', + 'ts' => 'Tsonga', + 'tt' => 'Tatarska', + 'tw' => 'Tví', + 'ty' => 'Tahítíska', + 'ug' => 'Úígúr', + 'uk' => 'Úkraínska', + 'ur' => 'Úrdú', + 'uz' => 'Úsbekska', + 've' => 'Venda', + 'vi' => 'Víetnamska', + 'vo' => 'Volapük', + 'wa' => 'Vallónska', + 'wo' => 'Volof', + 'xh' => 'Sósa', + 'yi' => 'Jiddíska', + 'yo' => 'Jórúba', + 'za' => 'Súang', + 'zh' => 'Kínverska', + 'zu' => 'Súlú', +); +?> diff --git a/lib/Pear/I18Nv2/Language/it.php b/lib/Pear/I18Nv2/Language/it.php new file mode 100644 index 0000000..c14bb1a --- /dev/null +++ b/lib/Pear/I18Nv2/Language/it.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amarico', + 'an' => 'Aragonese', + 'ar' => 'Arabo', + 'as' => 'Assamese', + 'av' => 'Avaro', + 'ay' => 'Aymara', + 'az' => 'Azerbaigiano', + 'ba' => 'Baschiro', + 'be' => 'Bielorusso', + 'bg' => 'Bulgaro', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengalese', + 'bo' => 'Tibetano', + 'br' => 'Bretone', + 'bs' => 'Bosniaco', + 'ca' => 'Catalano', + 'ce' => 'Ceceno', + 'ch' => 'Chamorro', + 'co' => 'Corso', + 'cr' => 'Cree', + 'cs' => 'Ceco', + 'cu' => 'Slavo della Chiesa', + 'cv' => 'Chuvash', + 'cy' => 'Gallese', + 'da' => 'Danese', + 'de' => 'Tedesco', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greco', + 'en' => 'Inglese', + 'eo' => 'Esperanto', + 'es' => 'Spagnolo', + 'et' => 'Estone', + 'eu' => 'Basco', + 'fa' => 'Persiano', + 'ff' => 'Fulah', + 'fi' => 'Finlandese', + 'fj' => 'Figiano', + 'fo' => 'Faroese', + 'fr' => 'Francese', + 'fy' => 'Frisone', + 'ga' => 'Irlandese', + 'gd' => 'Gaelico scozzese', + 'gl' => 'Galiziano', + 'gn' => 'Guarana', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Haussa', + 'he' => 'Ebraico', + 'hi' => 'Hindi', + 'ho' => 'Hiri motu', + 'hr' => 'Croato', + 'ht' => 'Haitiano', + 'hu' => 'Ungherese', + 'hy' => 'Armeno', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesiano', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan yi', + 'ik' => 'Inupiak', + 'io' => 'Ido', + 'is' => 'Islandese', + 'it' => 'Italiano', + 'iu' => 'Inuktitut', + 'ja' => 'Giapponese', + 'jv' => 'Giavanese', + 'ka' => 'Georgiano', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazako', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Coreano', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Curdo', + 'kv' => 'Komi', + 'kw' => 'Cornico', + 'ky' => 'Kirghiso', + 'la' => 'Latino', + 'lb' => 'Lussemburghese', + 'lg' => 'Ganda', + 'li' => 'Limburgese', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lituano', + 'lu' => 'Luba-katanga', + 'lv' => 'Lettone', + 'mg' => 'Malgascio', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedone', + 'ml' => 'Malayalam', + 'mn' => 'Mongolo', + 'mo' => 'Moldavo', + 'mr' => 'Marathi', + 'ms' => 'Malese', + 'mt' => 'Maltese', + 'my' => 'Birmano', + 'na' => 'Nauru', + 'nb' => 'Norvegese bokmÃ¥l', + 'nd' => 'Ndebele del nord', + 'ne' => 'Nepalese', + 'ng' => 'Ndonga', + 'nl' => 'Olandese', + 'nn' => 'Norvegese nynorsk', + 'no' => 'Norvegese', + 'nr' => 'Ndebele del sud', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; chichewa; chewa', + 'oc' => 'Occitano (post 1500); provenzale', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetico', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polacco', + 'ps' => 'Pashto', + 'pt' => 'Portoghese', + 'qu' => 'Quechua', + 'rm' => 'Lingua rhaeto-romance', + 'rn' => 'Rundi', + 'ro' => 'Rumeno', + 'ru' => 'Russo', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanscrito', + 'sc' => 'Sardo', + 'sd' => 'Sindhi', + 'se' => 'Sami del nord', + 'sg' => 'Sango', + 'sh' => 'Serbo-croato', + 'si' => 'Singalese', + 'sk' => 'Slovacco', + 'sl' => 'Sloveno', + 'sm' => 'Samoano', + 'sn' => 'Shona', + 'so' => 'Somalo', + 'sq' => 'Albanese', + 'sr' => 'Serbo', + 'ss' => 'Swati', + 'st' => 'Sotho del sud', + 'su' => 'Sundanese', + 'sv' => 'Svedese', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tagicco', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turcomanno', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Isole Tonga)', + 'tr' => 'Turco', + 'ts' => 'Tsonga', + 'tt' => 'Tatarico', + 'tw' => 'Ci', + 'ty' => 'Taitiano', + 'ug' => 'Uigurico', + 'uk' => 'Ucraino', + 'ur' => 'Urdu', + 'uz' => 'Usbeco', + 've' => 'Venda', + 'vi' => 'Vietnamita', + 'vo' => 'Volapük', + 'wa' => 'Vallone', + 'wo' => 'Volof', + 'xh' => 'Xosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Cinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/iu.php b/lib/Pear/I18Nv2/Language/iu.php new file mode 100644 index 0000000..8e0f4b9 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/iu.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'áƒá“„ᒃᑎá‘ᑦ á‘Žá‘Žá•‹á…ᓯᖅ', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ja.php b/lib/Pear/I18Nv2/Language/ja.php new file mode 100644 index 0000000..f8d77c3 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ja.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'アファール語', + 'ab' => 'アブãƒã‚ºèªž', + 'ae' => 'アヴェスタ語', + 'af' => 'アフリカーンス語', + 'ak' => 'アカン語', + 'am' => 'アムãƒãƒ©èªž', + 'an' => 'アラゴン語', + 'ar' => 'アラビア語', + 'as' => 'アッサム語', + 'av' => 'アヴァル語', + 'ay' => 'アイマラ語', + 'az' => 'アゼルãƒã‚¤ã‚¸ãƒ£ãƒ³èªž', + 'ba' => 'ãƒã‚·ã‚­ãƒ¼ãƒ«èªž', + 'be' => 'ベラルーシ語', + 'bg' => 'ブルガリア語', + 'bh' => 'ビãƒãƒ¼ãƒ«èªž', + 'bi' => 'ビスラマ語', + 'bm' => 'ãƒãƒ³ãƒãƒ©èªž', + 'bn' => 'ベンガル語', + 'bo' => 'ãƒãƒ™ãƒƒãƒˆèªž', + 'br' => 'ブルトン語', + 'bs' => 'ボスニア語', + 'ca' => 'カタロニア語', + 'ce' => 'ãƒã‚§ãƒã‚§ãƒ³èªž', + 'ch' => 'ãƒãƒ£ãƒ¢ãƒ­èªž', + 'co' => 'コルシカ語', + 'cr' => 'クリー語', + 'cs' => 'ãƒã‚§ã‚³èªž', + 'cu' => '教会スラブ語', + 'cv' => 'ãƒãƒ¥ãƒ´ã‚¡ã‚·ãƒ¥èªž', + 'cy' => 'ウェールズ語', + 'da' => 'デンマーク語', + 'de' => 'ドイツ語', + 'dv' => 'ディヴェヒ語', + 'dz' => 'ブータン語', + 'ee' => 'エウェ語', + 'el' => 'ギリシャ語', + 'en' => '英語', + 'eo' => 'エスペラント語', + 'es' => 'スペイン語', + 'et' => 'エストニア語', + 'eu' => 'ãƒã‚¹ã‚¯èªž', + 'fa' => 'ペルシア語', + 'ff' => 'フラニ語', + 'fi' => 'フィンランド語', + 'fj' => 'フィジー語', + 'fo' => 'フェロー語', + 'fr' => 'フランス語', + 'fy' => 'フリジア語', + 'ga' => 'アイルランド語', + 'gd' => 'スコットランド・ゲール語', + 'gl' => 'ガリシア語', + 'gn' => 'グワラニ語', + 'gu' => 'グジャラート語', + 'gv' => 'マン島語', + 'ha' => 'ãƒã‚¦ã‚µèªž', + 'he' => 'ヘブライ語', + 'hi' => 'ヒンディー語', + 'ho' => 'ヒリモトゥ語', + 'hr' => 'クロアãƒã‚¢èªž', + 'ht' => 'ãƒã‚¤ãƒèªž', + 'hu' => 'ãƒãƒ³ã‚¬ãƒªãƒ¼èªž', + 'hy' => 'アルメニア語', + 'hz' => 'ヘレロ語', + 'ia' => '国際語', + 'id' => 'インドãƒã‚·ã‚¢èªž', + 'ie' => '国際語', + 'ig' => 'イボ語', + 'ii' => 'å››å·ã‚¤èªž', + 'ik' => 'イヌピアック語', + 'io' => 'イド語', + 'is' => 'アイスランド語', + 'it' => 'イタリア語', + 'iu' => 'イヌクウティトット語', + 'ja' => '日本語', + 'jv' => 'ジャワ語', + 'ka' => 'グルジア語', + 'kg' => 'コンゴ語', + 'ki' => 'キクユ語', + 'kj' => 'クアニャマ語', + 'kk' => 'カザフ語', + 'kl' => 'グリーンランド語', + 'km' => 'カンボジア語', + 'kn' => 'カンナダ語', + 'ko' => '韓国語', + 'kr' => 'カヌリ語', + 'ks' => 'カシミール語', + 'ku' => 'クルド語', + 'kv' => 'コミ語', + 'kw' => 'コーンウォール語', + 'ky' => 'キルギス語', + 'la' => 'ラテン語', + 'lb' => 'ルクセンブルク語', + 'lg' => 'ガンダ語', + 'li' => 'リンブルフ語', + 'ln' => 'リンガラ語', + 'lo' => 'ラオ語', + 'lt' => 'リトアニア語', + 'lu' => 'ルãƒãƒ»ã‚«ã‚¿ãƒ³ã‚¬èªž', + 'lv' => 'ラトビア語', + 'mg' => 'マラガシー語', + 'mh' => 'マーシャル語', + 'mi' => 'マオリ語', + 'mk' => 'マケドニア語', + 'ml' => 'マラヤーラム語', + 'mn' => 'モンゴル語', + 'mo' => 'モルダビア語', + 'mr' => 'マラーティー語', + 'ms' => 'マレー語', + 'mt' => 'マルタ語', + 'my' => 'ビルマ語', + 'na' => 'ナウル語', + 'nb' => 'ノルウェー語 (ボクモール)', + 'nd' => '北ンデベレ語', + 'ne' => 'ãƒãƒ‘ール語', + 'ng' => 'ンドンガ語', + 'nl' => 'オランダ語', + 'nn' => 'ノルウェー語 (ニューノルスク)', + 'no' => 'ノルウェー語', + 'nr' => 'å—ンデベレ語', + 'nv' => 'ナãƒãƒ›èªž', + 'ny' => 'ニャンジャ語ã€ãƒãƒã‚§ãƒ¯èªžã€ãƒã‚§ãƒ¯èªž', + 'oc' => 'プロヴァンス語', + 'oj' => 'オブジワ語', + 'om' => 'ガラ語', + 'or' => 'オリヤー語', + 'os' => 'オセト語', + 'pa' => 'パンジャブ語', + 'pi' => 'パーリ語', + 'pl' => 'ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªž', + 'ps' => 'パシュトー語', + 'pt' => 'ãƒãƒ«ãƒˆã‚¬ãƒ«èªž', + 'qu' => 'ケãƒãƒ¥ã‚¢èªž', + 'rm' => 'レト・ロマン語', + 'rn' => 'ルンジ語', + 'ro' => 'ルーマニア語', + 'ru' => 'ロシア語', + 'rw' => 'ルワンダ語', + 'sa' => 'サンスクリット語', + 'sc' => 'サルデーニャ語', + 'sd' => 'シンド語', + 'se' => '北サーミ語', + 'sg' => 'サンゴ語', + 'sh' => 'セルボ・クロアãƒã‚¢èªž', + 'si' => 'シンãƒãƒ©èªž', + 'sk' => 'スロãƒã‚­ã‚¢èªž', + 'sl' => 'スロベニア語', + 'sm' => 'サモア語', + 'sn' => 'ショナ語', + 'so' => 'ソマリ語', + 'sq' => 'アルãƒãƒ‹ã‚¢èªž', + 'sr' => 'セルビア語', + 'ss' => 'シスワティ語', + 'st' => 'å—セソト語', + 'su' => 'スンダ語', + 'sv' => 'スウェーデン語', + 'sw' => 'スワヒリ語', + 'ta' => 'タミール語', + 'te' => 'テルグ語', + 'tg' => 'タジク語', + 'th' => 'タイ語', + 'ti' => 'ティグリニア語', + 'tk' => 'トルクメン語', + 'tl' => 'タガログ語', + 'tn' => 'ツワナ語', + 'to' => 'トンガ語', + 'tr' => 'トルコ語', + 'ts' => 'ツォンガ語', + 'tt' => 'タタール語', + 'tw' => 'トゥイ語', + 'ty' => 'タヒãƒèªž', + 'ug' => 'ウイグル語', + 'uk' => 'ウクライナ語', + 'ur' => 'ウルドゥー語', + 'uz' => 'ウズベク語', + 've' => 'ベンダ語', + 'vi' => 'ベトナム語', + 'vo' => 'ボラピュク語', + 'wa' => 'ワロン語', + 'wo' => 'ウォロフ語', + 'xh' => 'コサ語', + 'yi' => 'イディッシュ語', + 'yo' => 'ヨルãƒèªž', + 'za' => 'ãƒãƒ¯ãƒ³èªž', + 'zh' => '中国語', + 'zu' => 'ズールー語', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ka.php b/lib/Pear/I18Nv2/Language/ka.php new file mode 100644 index 0000000..45d25dc --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ka.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'ქáƒáƒ áƒ—ული', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/kk.php b/lib/Pear/I18Nv2/Language/kk.php new file mode 100644 index 0000000..7a30106 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/kk.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Қазақ', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/kl.php b/lib/Pear/I18Nv2/Language/kl.php new file mode 100644 index 0000000..25873bd --- /dev/null +++ b/lib/Pear/I18Nv2/Language/kl.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/km.php b/lib/Pear/I18Nv2/Language/km.php new file mode 100644 index 0000000..e3b7d5b --- /dev/null +++ b/lib/Pear/I18Nv2/Language/km.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'ភាសាអាហ្វារ', + 'ab' => 'Abkhazian', + 'ae' => 'ភាសាអាវែស្ážáž„់', + 'af' => 'ភាសាអាហ្វ្រីកាអាន', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'ភាសាអារ៉ាហ្គោន', + 'ar' => 'ភាសាអារ៉ាប់', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'ភាសាអីម៉ារ៉ា', + 'az' => 'ភាសាអាហ៊្សែរបែហ្សង់', + 'ba' => 'Bashkir', + 'be' => 'ភាសាបáŸáž¡áž¶ážšáž»ážŸáŸ’ស', + 'bg' => 'ភាសាប៊ុលហ្ការី', + 'bh' => 'ភាសាបិហារ', + 'bi' => 'Bislama', + 'bm' => 'ភាសាបាម្បារា', + 'bn' => 'ភាសាបáŸáž“្កាលី', + 'bo' => 'ភាសាទីបáŸ', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'ភាសាកាážáž¶áž¡áž¶áž“', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ភាសាឆáŸáž€', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'ភាសាដាណឺម៉ាក', + 'de' => 'ភាសាអាល្លឺម៉ង់', + 'dv' => 'Divehi', + 'dz' => 'ភាសាប៊ូážáž¶áž“', + 'ee' => 'Ewe', + 'el' => 'ភាសាក្រិច', + 'en' => 'ភាសាអង់គ្លáŸážŸ', + 'eo' => 'ភាសាអáŸážŸáŸ’áž–áŸážšáŸ‰áž¶áž“្ទោ', + 'es' => 'ភាសាអáŸážŸáŸ’ប៉ាញ', + 'et' => 'ភាសាអáŸážŸáŸ’ážáž¼áž“ី', + 'eu' => 'ភាសាបាស្កáŸ', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'ភាសាហ្វាំងឡង់', + 'fj' => 'ហ្វ៉ីហ្ស៉ី', + 'fo' => 'Faroese', + 'fr' => 'ភាសាបារាំង', + 'fy' => 'Frisian', + 'ga' => 'ភាសាហ្កែលិគ', + 'gd' => 'ភាសាហ្កែលិគ', + 'gl' => 'ភាសាហ្កាលីស៉ី', + 'gn' => 'ភាសាហ្កួរ៉ានី', + 'gu' => 'ភាសាហ្កុយ៉ារាទី', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'ភាសាហáŸáž”្រិ', + 'hi' => 'ភាសាហ៉ិនឌី', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'ភាសាហុងគ្រី', + 'hy' => 'ភាសាអារមáŸáž“ី', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'ភាសាឥណ្ឌូនáŸážŸáŸŠáž¸', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'ភាសាអ៉ីស្លង់', + 'it' => 'ភាសាអ៊ីážáž¶áž›áž¸', + 'iu' => 'Inuktitut', + 'ja' => 'ភាសាជប៉ុន', + 'jv' => 'ភាសាយ៉ាវា', + 'ka' => 'ភាសាហ្សកហ្ស៉ី', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'ភាសាកាហ្សាក់ស្ážáž„់់', + 'kl' => 'Kalaallisut', + 'km' => 'ភាសាážáŸ’មែរ', + 'kn' => 'ភាសាកិណាដា', + 'ko' => 'ភាសាកូរ៉áŸ', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'ភាសាឃឺដ', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'ភាសាគៀរហ្គីស្ážáž„់', + 'la' => 'ភាសាឡាážáŸ†áž¶áž„', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'ភាសាឡាវ', + 'lt' => 'ភាសាលីទុយអានី', + 'lu' => 'Luba-Katanga', + 'lv' => 'ភាសាឡាážážœáž¸áž™áŸ‰áž¶', + 'mg' => 'ភាសាម៉ាដាហ្កាសការ', + 'mh' => 'Marshallese', + 'mi' => 'ភាសាម៉ោរី', + 'mk' => 'ភាសាម៉ាសáŸážŠáž¼áž“ី', + 'ml' => 'ភាសាម៉ាឡាឡាយ៉ាន', + 'mn' => 'ភាសាម៉ុងហ្គោលី', + 'mo' => 'ភាសាម៉ុលដាវី', + 'mr' => 'ភាសាម៉ារាធី', + 'ms' => 'ភាសាម៉ាលáŸážŸáŸ‰áž¸', + 'mt' => 'ភាសាម៉ាល់ážáž¶', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ភាសានáŸáž”៉ាល់', + 'ng' => 'Ndonga', + 'nl' => 'ភាសាហុល្លង់', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'ភាសានáŸážšážœáŸ‚ស', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'ភាសាអូរីយ៉ា', + 'os' => 'Ossetic', + 'pa' => 'ភាសាពូនយ៉ាប៊ី', + 'pi' => 'Pali', + 'pl' => 'ភាសាប៉ូឡូញ', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'ភាសាពáŸážšáž‘ុយហ្កាល់', + 'qu' => 'ភាសាកáŸáž‘្ជូអា', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'ភាសារូន្ឌី', + 'ro' => 'ភាសារូម៉ានី', + 'ru' => 'ភាសាรัរូស្ស៉ី', + 'rw' => 'Kinyarwanda', + 'sa' => 'ភាសាសំស្ក្រឹáž', + 'sc' => 'Sardinian', + 'sd' => 'ភាសាស៉ីន្ដី', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'ភាសាស្លូវ៉ាគី', + 'sl' => 'ភាសាស្លូវ៉ានី', + 'sm' => 'ភាសាសាមូអា', + 'sn' => 'Shona', + 'so' => 'ភាសាសូម៉ាលី', + 'sq' => 'ភាសាអាល់បានី', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'ភាំសាស៊ូដង់', + 'sv' => 'ភាសាស៊ុយអែដ', + 'sw' => 'ភាសាស្វាហ៉ីលី', + 'ta' => 'ភាសាážáž¶áž˜áž¸áž›', + 'te' => 'ភាសាážáŸáž›áž¼áž áŸ’áž‚áž¼', + 'tg' => 'ភាសាážáž¶ážŠáž áŸ’ស៉ីគីស្ážáž„់', + 'th' => 'ភាសាážáŸƒ', + 'ti' => 'Tigrinya', + 'tk' => 'ភាសាទួគមáŸáž“ីស្ážáž„់', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'ភាសាážáž»áž„ហ្គោ', + 'tr' => 'ភាសាទួរគី', + 'ts' => 'Tsonga', + 'tt' => 'ភាសាážáž¶ážáž¶ážš', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'ភាសាអ៊ុយក្រែន', + 'ur' => 'ភាសាអ៊ូរ្ឌូ', + 'uz' => 'ភាសាអ៊ូហ្សបáŸáž‚ីស្ážáž„់', + 've' => 'Venda', + 'vi' => 'ភាសាវៀážážŽáž¶áž˜', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'ភាសាឃសា', + 'yi' => 'ភាសាយីឌីហ្ស', + 'yo' => 'ភាសាយរូបា', + 'za' => 'ភាសាចួង', + 'zh' => 'ភាសាចិន', + 'zu' => 'ភាសាហ្ស៉ូលូ', +); +?> diff --git a/lib/Pear/I18Nv2/Language/kn.php b/lib/Pear/I18Nv2/Language/kn.php new file mode 100644 index 0000000..b80e6e3 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/kn.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'ಕನà³à²¨à²¡', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ko.php b/lib/Pear/I18Nv2/Language/ko.php new file mode 100644 index 0000000..8fca2a6 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ko.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => '아파르어', + 'ab' => '압카즈어', + 'ae' => 'Avestan', + 'af' => '남아공 공용어', + 'ak' => '아칸어', + 'am' => '암하ë¼ì–´', + 'an' => 'ì•„ë¼ê³¤ì–´', + 'ar' => 'ì•„ëžì–´', + 'as' => '아샘어', + 'av' => '아바릭어', + 'ay' => 'ì•„ì´ë§ˆë¼ì–´', + 'az' => '아제르바ì´ìž”ì–´', + 'ba' => '바슈키르어', + 'be' => '벨로루시어', + 'bg' => '불가리아어', + 'bh' => '비하르어', + 'bi' => '비슬ë¼ë§ˆì–´', + 'bm' => '밤바ë¼ì–´', + 'bn' => '벵골어', + 'bo' => '티베트어', + 'br' => '브르타뉴어', + 'bs' => '보스니아어', + 'ca' => '카탈로니아어', + 'ce' => 'Chechen', + 'ch' => '차모로어', + 'co' => '코르시카어', + 'cr' => 'í¬ë¦¬ì–´', + 'cs' => '체코어', + 'cu' => 'êµíšŒìŠ¬ë¼ë¸Œì–´', + 'cv' => '추바시어', + 'cy' => '웨ì¼ìŠ¤ì–´', + 'da' => 'ë´ë§ˆí¬ì–´', + 'de' => 'ë…ì¼ì–´', + 'dv' => '디베히어', + 'dz' => '부탄어', + 'ee' => 'ì—웨어', + 'el' => '그리스어', + 'en' => 'ì˜ì–´', + 'eo' => 'ì—스페란토어', + 'es' => '스페ì¸ì–´', + 'et' => 'ì—스토니아어', + 'eu' => '바스í¬ì–´', + 'fa' => 'ì´ëž€ì–´', + 'ff' => 'í’€ë¼ì–´', + 'fi' => '핀란드어', + 'fj' => '피지어', + 'fo' => '페로스어', + 'fr' => '프랑스어', + 'fy' => '프리지아어', + 'ga' => 'ì•„ì¼ëžœë“œì–´', + 'gd' => '스코갤릭어', + 'gl' => '갈리시아어', + 'gn' => '구아ë¼ë‹ˆì–´', + 'gu' => '구ìžë¼íŠ¸ì–´', + 'gv' => '맹í¬ìŠ¤ì–´', + 'ha' => '하우ìžì–´', + 'he' => '히브리어', + 'hi' => '힌디어', + 'ho' => '히리 모투어', + 'hr' => 'í¬ë¡œì•„í‹°ì•„ì–´', + 'ht' => 'ì•„ì´í‹°ì–´', + 'hu' => 'í—가리어', + 'hy' => '아르메니아어', + 'hz' => 'Herero', + 'ia' => 'ì¸í„°ë§ê±°', + 'id' => 'ì¸ë„네시아어', + 'ie' => 'ì¸í„°ë§ê²Œì–´', + 'ig' => 'ì´ê·¸ë³´ì–´', + 'ii' => '시츄안 ì´ì–´', + 'ik' => 'ì´ëˆ„피아í¬ì–´', + 'io' => 'ì´ë„ì–´', + 'is' => 'ì•„ì´ìŠ¬ëž€ë“œì–´', + 'it' => 'ì´íƒˆë¦¬ì•„ì–´', + 'iu' => 'ì´ëˆ…티투트어', + 'ja' => 'ì¼ë³¸ì–´', + 'jv' => 'ìžë°”ì–´', + 'ka' => '그루지야어', + 'kg' => '콩고어', + 'ki' => '키쿠유어', + 'kj' => '쿠안야마어', + 'kk' => 'ì¹´ìžíì–´', + 'kl' => '그린랜드어', + 'km' => '캄보디아어', + 'kn' => '카나다어', + 'ko' => '한국어', + 'kr' => '칸누리어', + 'ks' => '카슈미르어', + 'ku' => 'í¬ë¥´ë“œì–´', + 'kv' => '코미어', + 'kw' => '콘월어', + 'ky' => '키르기스어', + 'la' => 'ë¼í‹´ì–´', + 'lb' => '룩셈부르í¬ì–´', + 'lg' => '간다어', + 'li' => '림버거어', + 'ln' => 'ë§ê°ˆë¼ì–´', + 'lo' => 'ë¼ì˜¤ì–´', + 'lt' => '리투아니아어', + 'lu' => '루바-카탄가어', + 'lv' => 'ë¼íŠ¸ë¹„ì•„ì–´', + 'mg' => '마다가스카르어', + 'mh' => '마셜제ë„ì–´', + 'mi' => '마오리어', + 'mk' => '마케ë„니아어', + 'ml' => 'ë§ë¼ì–„람어', + 'mn' => '몽골어', + 'mo' => '몰다비아어', + 'mr' => '마ë¼í‹°ì–´', + 'ms' => 'ë§ë ˆì´ì–´', + 'mt' => '몰타어', + 'my' => '버마어', + 'na' => '나우루어', + 'nb' => 'ë³´í¬ë§ 노르웨ì´ì–´', + 'nd' => 'ì€ë°ë²¨ë ˆì–´, ë¶ë¶€', + 'ne' => '네팔어', + 'ng' => 'ëŠë™ê°€ì–´', + 'nl' => '네ëœëž€ë“œì–´', + 'nn' => 'ë‰˜ë…¸ë¥´ìŠ¤í¬ ë…¸ë¥´ì›¨ì´ì–´', + 'no' => '노르웨ì´ì–´', + 'nr' => 'ì€ë°ë²¨ë ˆì–´, 남부', + 'nv' => '나바호어', + 'ny' => '니안ìžì–´; 치츄어; 츄어', + 'oc' => '옥시트어', + 'oj' => '오지브웨ì´ì–´', + 'om' => '오로모어 (ì•„íŒ)', + 'or' => '오리야어', + 'os' => '오세트어', + 'pa' => '펀잡어', + 'pi' => '팔리어', + 'pl' => 'í´ëž€ë“œì–´', + 'ps' => '파시토어 (푸시토)', + 'pt' => 'í¬ë¥´íˆ¬ì¹¼ì–´', + 'qu' => '케추아어', + 'rm' => '레토로만어', + 'rn' => '반투어(부룬디)', + 'ro' => '루마니아어', + 'ru' => '러시아어', + 'rw' => '반투어(루완다)', + 'sa' => '산스í¬ë¦¬íŠ¸ì–´', + 'sc' => '사르디니아어', + 'sd' => '신디어', + 'se' => 'ë¶ë¶€ 사미어', + 'sg' => 'ì‚°ê³ ì–´', + 'sh' => '세르보í¬ë¡œì•„í‹°ì•„ì–´', + 'si' => '스리랑카어', + 'sk' => '슬로바키아어', + 'sl' => '슬로베니아어', + 'sm' => '사모아어', + 'sn' => '쇼나어', + 'so' => '소ë§ë¦¬ì•„ì–´', + 'sq' => '알바니아어', + 'sr' => '세르비아어', + 'ss' => '시스와티어', + 'st' => '세소토어', + 'su' => '순단어', + 'sv' => '스웨ë´ì–´', + 'sw' => '스와ížë¦¬ì–´', + 'ta' => '타밀어', + 'te' => '텔루구어', + 'tg' => '타지키스탄어', + 'th' => '태국어', + 'ti' => '티그리ëƒì–´', + 'tk' => '투르í¬ë©˜ì–´', + 'tl' => '타갈로그어', + 'tn' => '세츠와나어', + 'to' => '통가어', + 'tr' => '터키어', + 'ts' => '통가어', + 'tt' => '타타르어', + 'tw' => '트위어', + 'ty' => '타히티어', + 'ug' => '위구르어', + 'uk' => 'ìš°í¬ë¼ì´ë‚˜ì–´', + 'ur' => '우르ë‘ì–´', + 'uz' => '우즈베í¬ì–´', + 've' => '벤다어', + 'vi' => '베트남어', + 'vo' => 'ë³¼ë¼í“Œí¬ì–´', + 'wa' => '왈론어', + 'wo' => '올로프어', + 'xh' => '반투어(남아프리카)', + 'yi' => 'ì´ë””시어', + 'yo' => '요루바어', + 'za' => '주앙어', + 'zh' => '중국어', + 'zu' => '줄루어', +); +?> diff --git a/lib/Pear/I18Nv2/Language/kw.php b/lib/Pear/I18Nv2/Language/kw.php new file mode 100644 index 0000000..c6c0315 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/kw.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Kernewek', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ky.php b/lib/Pear/I18Nv2/Language/ky.php new file mode 100644 index 0000000..7fe83c0 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ky.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Кыргыз', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/lo.php b/lib/Pear/I18Nv2/Language/lo.php new file mode 100644 index 0000000..4b4c635 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/lo.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'ອາຟາ', + 'ab' => 'à»àº­àºšàº„າເຊàº', + 'ae' => 'Avestan', + 'af' => 'ອາຟິຼàºàºàº²', + 'ak' => 'Akan', + 'am' => 'ອຳຮາລິດ', + 'an' => 'Aragonese', + 'ar' => 'ອາລາເບàº', + 'as' => 'ອັດສຳມິດ', + 'av' => 'Avaric', + 'ay' => 'ໄອມາລາ', + 'az' => 'ອາເຊີໄບຈານີ', + 'ba' => 'ບາສສີ', + 'be' => 'ບາàºà»‚ລລັດເຊàº', + 'bg' => 'ບັງàºàº²à»€àº¥àº', + 'bh' => 'ບິຮາລິ', + 'bi' => 'ບິສລາມາ', + 'bm' => 'Bambara', + 'bn' => 'ບຸນàºàº²àº¥àºµ', + 'bo' => 'ທິເບດ', + 'br' => 'ບີທັນ', + 'bs' => 'Bosnian', + 'ca' => 'à»àº„ຕາà»àº¥àº™', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'ຄà»àºŠàº´àºà»‰àº²', + 'cr' => 'Cree', + 'cs' => 'ເຊັàº', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'ເວວ', + 'da' => 'ເດນà»àº²àº', + 'de' => 'ເຢàºàº¥àº°àº¡àº±àº™', + 'dv' => 'Divehi', + 'dz' => 'ພູຖານີ', + 'ee' => 'Ewe', + 'el' => 'àºàºµàº', + 'en' => 'ອັງàºàº´àº”', + 'eo' => 'ເອສເປີລັນໂຕ', + 'es' => 'ສະເປນ', + 'et' => 'ເອສໂຕເນàº', + 'eu' => 'à»àºšàºª', + 'fa' => 'ເປີເຊàº', + 'ff' => 'Fulah', + 'fi' => 'ຟິນ', + 'fj' => 'ຟິຈິ', + 'fo' => 'ຟາໂລດ', + 'fr' => 'àºàº±à»ˆàº¥àº‡à»€àºªàº”', + 'fy' => 'ຟິນà»àº¥àº™', + 'ga' => 'ໄອລິດ', + 'gd' => 'ສະàºàº±àº­àº”ເຄີດ', + 'gl' => 'àºàº°àºªàº´à»€àºŠàº', + 'gn' => 'àºàº»àº§àº¥àº²àº™àºµ', + 'gu' => 'àºàº¹àºˆàº²àº¥àº²àº•àºµ', + 'gv' => 'Manx', + 'ha' => 'ໂອຊາ', + 'he' => 'ຢິວ', + 'hi' => 'ຮິນດິ', + 'ho' => 'Hiri Motu', + 'hr' => 'ໂຄເອເຊàº', + 'ht' => 'Haitian', + 'hu' => 'ຮົງàºàº²àº¥àºµ', + 'hy' => 'ອາມິເນàº', + 'hz' => 'Herero', + 'ia' => 'ອິນເຕີລິງàºàº§àº²', + 'id' => 'ອິນໂດເນເຊàº', + 'ie' => 'ອິນເຕີລິງ', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'ໄອນູປຽàº', + 'io' => 'Ido', + 'is' => 'ໄອà»àº¥àº™àº”ິດ', + 'it' => 'ອິຕາສິ', + 'iu' => 'ໄອນຸàºàº•àº´àº•àº±àº', + 'ja' => 'àºàºµà»ˆàº›àº¸à»ˆàº™', + 'jv' => 'ຊະວາ', + 'ka' => 'ຈà»à»€àºˆàº', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'ຄາຊັàº', + 'kl' => 'àºàº¼àºµàº™à»àº¥àº™àº”ິດ', + 'km' => 'ຂະເà»àº™', + 'kn' => 'àºàº²àº™àº²àº”າ', + 'ko' => 'ເàºàº»àº²àº«àº¥àºµ', + 'kr' => 'Kanuri', + 'ks' => 'ຄັດຊະມີລີ', + 'ku' => 'ເຄີດ', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'ເຄວàºàº´àº”', + 'la' => 'ລາຕິນ', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'ລິງàºàº²àº¥àº²', + 'lo' => 'ລາວ', + 'lt' => 'ລິທົວເນàº', + 'lu' => 'Luba-Katanga', + 'lv' => 'à»àº¥àº•àº°à»€àº§àº(ເລດທະວິດ)', + 'mg' => 'ມາລາàºàº²àºŠàº´', + 'mh' => 'Marshallese', + 'mi' => 'ເມົາລີ', + 'mk' => 'à»àº¡àº±àºàºŠàº´à»‚ດເນàº', + 'ml' => 'à»àº¡àº¥àº°àº¢àº²àº¥àº³', + 'mn' => 'ມອງໂàºàº¼', + 'mo' => 'ໂມຄາເວàº', + 'mr' => 'ມາລາທິ', + 'ms' => 'ມາລາຢູ', + 'mt' => 'ມອນຕາ', + 'my' => 'ພະມ່າ', + 'na' => 'ນà»àº¥àº¹', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ເນປານ', + 'ng' => 'Ndonga', + 'nl' => 'ອà»àº¥àº±àº™àº”າ', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'ນà»à»€àº§àº§', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ອອັàºàºŠàº´àº—ັນ', + 'oj' => 'Ojibwa', + 'om' => 'ໂອໂລໂມ(ອາຟານ)', + 'or' => 'ໂອລິàºàº²', + 'os' => 'Ossetic', + 'pa' => 'ປັນຈາ', + 'pi' => 'Pali', + 'pl' => 'ໂປà»àº¥àº™', + 'ps' => 'ພາສໂຕ(ພຸດໂຕ)', + 'pt' => 'ໂປຕຸເàºàº”', + 'qu' => 'ຄິວຊົວ', + 'rm' => 'ເລໂຕ-ໂລà»àº¡àº™', + 'rn' => 'ຄິລັນສີ', + 'ro' => 'ໂລມັນ', + 'ru' => 'ລັດເຊàº', + 'rw' => 'ຄິນàºàº²àº§àº±àº™àº”າ', + 'sa' => 'ສັນສະàºàº´àº”', + 'sc' => 'Sardinian', + 'sd' => 'ຊິນດິ', + 'se' => 'Northern Sami', + 'sg' => 'ສັນໂຄ', + 'sh' => 'ເຊີໂບ-ໂຄເອທຽນ', + 'si' => 'ສິງຫລà»', + 'sk' => 'ສະໂລວັàº', + 'sl' => 'ສະໂລວາເນàº', + 'sm' => 'ຊາມົວ', + 'sn' => 'ໂຊນາ', + 'so' => 'ໂຊມາສິ', + 'sq' => 'à»àº­àº¥à»€àºšà»€àº™àº', + 'sr' => 'ເຊີເບàº', + 'ss' => 'ຊິສວາຕິ', + 'st' => 'ເຊໂສໂທ', + 'su' => 'ຊັນດານິສ', + 'sv' => 'ສະວີເດນ', + 'sw' => 'ຊະວາຮິລີ', + 'ta' => 'ທະມິບ', + 'te' => 'ທິລູàºàº¹', + 'tg' => 'ທາຈິດ', + 'th' => 'ໄທ', + 'ti' => 'ທິàºàº´àº™àº¢àº²', + 'tk' => 'ເຕີàºà»€àº¡àº™', + 'tl' => 'ຕາàºàº²àº¥àº±àº­àº', + 'tn' => 'ເຊຕະສະວານາ', + 'to' => 'ທອງàºà»‰àº²', + 'tr' => 'ຕຸລາàºàºµ', + 'ts' => 'ຊອງàºàº²', + 'tt' => 'ຕາດ', + 'tw' => 'ທະວີ', + 'ty' => 'Tahitian', + 'ug' => 'ອຸàºàºàº»àº§', + 'uk' => 'ຢູເຄຼນ', + 'ur' => 'ອິນດູ', + 'uz' => 'ອຸດສະເບດ', + 've' => 'Venda', + 'vi' => 'ວຽດນາມ', + 'vo' => 'ໂວລາພຸàº', + 'wa' => 'Walloon', + 'wo' => 'ວູບ', + 'xh' => 'ໂຊສາ', + 'yi' => 'ຢີຄິດ', + 'yo' => 'ໂຢລູບາ', + 'za' => 'ຈວງ', + 'zh' => 'ຈີນ', + 'zu' => 'ຊູລູ', +); +?> diff --git a/lib/Pear/I18Nv2/Language/lt.php b/lib/Pear/I18Nv2/Language/lt.php new file mode 100644 index 0000000..f328b52 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/lt.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabų', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarų', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ÄŒekų', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danų', + 'de' => 'VokieÄių', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Graikų', + 'en' => 'Anglų', + 'eo' => 'Esperanto', + 'es' => 'Ispanų', + 'et' => 'Estų', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Suomių', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'PrancÅ«zų', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrajų', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Kroatų', + 'ht' => 'Haitian', + 'hu' => 'Vengrų', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italų', + 'iu' => 'Inuktitut', + 'ja' => 'Japonų', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'KorÄ—jieÄių', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lietuvių', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvių', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Olandų', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norvegų', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Lenkų', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugalų', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Rumunų', + 'ru' => 'Rusų', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovakų', + 'sl' => 'SlovÄ—nų', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Å vedų', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkų', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Kinų', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/lv.php b/lib/Pear/I18Nv2/Language/lv.php new file mode 100644 index 0000000..ba1657a --- /dev/null +++ b/lib/Pear/I18Nv2/Language/lv.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ArÄbu', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'BulgÄru', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ÄŒehu', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'DÄņu', + 'de' => 'VÄcu', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'GrieÄ·u', + 'en' => 'Angļu', + 'eo' => 'Esperanto', + 'es' => 'SpÄņu', + 'et' => 'Igauņu', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Somu', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'FranÄu', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Ivrits', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'HorvÄtu', + 'ht' => 'Haitian', + 'hu' => 'UngÄru', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ItÄlieÅ¡u', + 'iu' => 'Inuktitut', + 'ja' => 'JapÄņu', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'KorejieÅ¡u', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'LietuvieÅ¡u', + 'lu' => 'Luba-Katanga', + 'lv' => 'LatvieÅ¡u', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'HolandieÅ¡u', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'NorvÄ“Ä£u', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Poļu', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'PortugÄļu', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'RumÄņu', + 'ru' => 'Krievu', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'SlovÄku', + 'sl' => 'Slovēņu', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Zviedru', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turku', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'ĶīnieÅ¡u', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/mk.php b/lib/Pear/I18Nv2/Language/mk.php new file mode 100644 index 0000000..2d6ab1a --- /dev/null +++ b/lib/Pear/I18Nv2/Language/mk.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'МакедонÑки', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ml.php b/lib/Pear/I18Nv2/Language/ml.php new file mode 100644 index 0000000..50eac41 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ml.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'മലയാളം', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/mn.php b/lib/Pear/I18Nv2/Language/mn.php new file mode 100644 index 0000000..4ddfbc7 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/mn.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Монгол Ñ…Ñл', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/mr.php b/lib/Pear/I18Nv2/Language/mr.php new file mode 100644 index 0000000..6a8d2ab --- /dev/null +++ b/lib/Pear/I18Nv2/Language/mr.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'अफार', + 'ab' => 'अबखेजियन', + 'ae' => 'Avestan', + 'af' => 'अफà¥à¤°à¤¿à¤•à¤¾à¤¨à¥à¤¸', + 'ak' => 'Akan', + 'am' => 'अमहारिक', + 'an' => 'Aragonese', + 'ar' => 'अरेबिक', + 'as' => 'असामी', + 'av' => 'Avaric', + 'ay' => 'à¤à¤®à¤°à¤¾', + 'az' => 'अज़रबाइजानी', + 'ba' => 'बषà¥à¤•à¤¿à¤°', + 'be' => 'बैलोरà¥à¤¸à¤¿à¤¯à¤¨', + 'bg' => 'बलà¥à¤—ेरियन', + 'bh' => 'बीहारी', + 'bi' => 'बिसलमा', + 'bm' => 'Bambara', + 'bn' => 'बंगाली', + 'bo' => 'तिबेटियन', + 'br' => 'बà¥à¤°à¥‡à¤Ÿà¤¨', + 'bs' => 'Bosnian', + 'ca' => 'कटलन', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'कोरà¥à¤¸à¤¿à¤•à¤¨', + 'cr' => 'Cree', + 'cs' => 'ज़ेक', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'वेलà¥à¤·', + 'da' => 'डानिष', + 'de' => 'जरà¥à¤®à¤¨', + 'dv' => 'Divehi', + 'dz' => 'भूटानी', + 'ee' => 'Ewe', + 'el' => 'गà¥à¤°à¥€à¤•', + 'en' => 'इंगà¥à¤°à¥‡à¤œà¥€', + 'eo' => 'इसà¥à¤ªà¤°à¤¾à¤¨à¥à¤Ÿà¥‹', + 'es' => 'सà¥à¤ªà¤¾à¤¨à¤¿à¤·', + 'et' => 'इसà¥à¤Ÿà¥‹à¤¨à¤¿à¤¯à¤¨à¥', + 'eu' => 'बासà¥à¤•', + 'fa' => 'परà¥à¤·à¤¿à¤¯à¤¨à¥', + 'ff' => 'Fulah', + 'fi' => 'फिनà¥à¤¨à¤¿à¤·', + 'fj' => 'फिजी', + 'fo' => 'फेरोसà¥', + 'fr' => 'फà¥à¤°à¥‡à¤¨à¥à¤š', + 'fy' => 'फà¥à¤°à¤¿à¤¸à¤¿à¤¯à¤¨à¥', + 'ga' => 'à¤à¤°à¤¿à¤·', + 'gd' => 'सà¥à¤•à¤¾à¤Ÿà¤¸à¥ गेलिक', + 'gl' => 'गेलीशियन', + 'gn' => 'गौरानी', + 'gu' => 'गà¥à¤œà¤°à¤¾à¤¤à¥€', + 'gv' => 'Manx', + 'ha' => 'हौसा', + 'he' => 'हेबृ', + 'hi' => 'हिनà¥à¤¦à¥€', + 'ho' => 'Hiri Motu', + 'hr' => 'कà¥à¤°à¥‹à¤¯à¥‡à¤·à¤¿à¤¯à¤¨à¥', + 'ht' => 'Haitian', + 'hu' => 'हंगेरियनà¥', + 'hy' => 'आरà¥à¤®à¥€à¤¨à¤¿à¤¯à¤¨à¥', + 'hz' => 'Herero', + 'ia' => 'इनà¥à¤Ÿà¤°à¤²à¤¿à¤‚गà¥à¤µà¤¾', + 'id' => 'इनà¥à¤¡à¥‹à¤¨à¥‡à¤·à¤¿à¤¯à¤¨', + 'ie' => 'इनà¥à¤Ÿà¤°à¤²à¤¿à¤‚ग', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'इनूपियाक', + 'io' => 'Ido', + 'is' => 'आईसलानà¥à¤¡à¤¿à¤•', + 'it' => 'इटालियन', + 'iu' => 'इनà¥à¤•à¤¿à¤Ÿà¥à¤Ÿà¥', + 'ja' => 'जापनीसà¥', + 'jv' => 'जावनीसà¥', + 'ka' => 'जारà¥à¤œà¤¿à¤¯à¤¨à¥', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'कज़क', + 'kl' => 'गà¥à¤°à¥€à¤¨à¤²à¤¾à¤¨à¥à¤¡à¤¿à¤•', + 'km' => 'कंबोडियन', + 'kn' => 'कनà¥à¤¨à¤¡', + 'ko' => 'कोरियनà¥', + 'kr' => 'Kanuri', + 'ks' => 'कशà¥à¤®à¥€à¤°à¥€', + 'ku' => 'कà¥à¤°à¥à¤¦à¤¿à¤·', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'किरà¥à¤—िज़', + 'la' => 'लाटिन', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'लिंगाला', + 'lo' => 'लाओतियनà¥', + 'lt' => 'लिथà¥à¤†à¤¨à¤¿à¤¯à¤¨à¥', + 'lu' => 'Luba-Katanga', + 'lv' => 'लाटà¥à¤µà¤¿à¤¯à¤¨à¥ (लेटà¥à¤Ÿà¤¿à¤·)', + 'mg' => 'मलागसी', + 'mh' => 'Marshallese', + 'mi' => 'माओरी', + 'mk' => 'मसीडोनियनà¥', + 'ml' => 'मलियालम', + 'mn' => 'मंगोलियनà¥', + 'mo' => 'मोलà¥à¤¡à¤¾à¤µà¤¿à¤¯à¤¨à¥', + 'mr' => 'मराठी', + 'ms' => 'मलय', + 'mt' => 'मालतीसà¥', + 'my' => 'बरà¥à¤®à¥€à¤¸à¥', + 'na' => 'नौरो', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'नेपाली', + 'ng' => 'Ndonga', + 'nl' => 'डच', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'नोरà¥à¤µà¥‡à¤œà¤¿à¤¯à¤¨', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ओसिटानà¥', + 'oj' => 'Ojibwa', + 'om' => 'ओरोमो (अफान)', + 'or' => 'ओरिया', + 'os' => 'Ossetic', + 'pa' => 'पंजाबी', + 'pi' => 'Pali', + 'pl' => 'पोलिष', + 'ps' => 'पषà¥à¤Ÿà¥‹ (पà¥à¤·à¥à¤Ÿà¥‹)', + 'pt' => 'पोरà¥à¤šà¥à¤—ीसà¥', + 'qu' => 'कà¥à¤µà¥‡à¤šà¤“', + 'rm' => 'रहटो-रोमानà¥à¤¸à¥', + 'rn' => 'किरà¥à¤¨à¥à¤¦à¥€', + 'ro' => 'रोमानियनà¥', + 'ru' => 'रषà¥à¤¯à¤¨à¥', + 'rw' => 'किनà¥à¤¯à¤¾à¤°à¥à¤µà¤¾à¤¨à¥à¤¡à¤¾', + 'sa' => 'संसà¥à¤•à¥ƒà¤¤', + 'sc' => 'Sardinian', + 'sd' => 'सिंधी', + 'se' => 'Northern Sami', + 'sg' => 'सांगà¥à¤°à¥‹', + 'sh' => 'सेरà¥à¤¬à¥‹-कà¥à¤°à¥‹à¤¯à¥‡à¤·à¤¿à¤¯à¤¨à¥', + 'si' => 'सिनà¥à¤¹à¤²à¥€à¤¸à¥', + 'sk' => 'सà¥à¤²à¥‹à¤µà¤¾à¤•', + 'sl' => 'सà¥à¤²à¥‹à¤µà¥‡à¤¨à¤¿à¤¯à¤¨à¥', + 'sm' => 'समोन', + 'sn' => 'शोना', + 'so' => 'सोमाली', + 'sq' => 'आलà¥à¤¬à¥‡à¤¨à¤¿à¤¯à¤¨à¥', + 'sr' => 'सेरà¥à¤¬à¤¿à¤¯à¤¨à¥', + 'ss' => 'सिसà¥à¤µà¤¤à¥€', + 'st' => 'सेसोथो', + 'su' => 'सà¥à¤‚दनीसà¥', + 'sv' => 'सà¥à¤µà¥€à¤¡à¤¿à¤·', + 'sw' => 'सà¥à¤µà¤¾à¤¹à¤¿à¤²à¥€', + 'ta' => 'तमिळ', + 'te' => 'तेलंगू', + 'tg' => 'तजिक', + 'th' => 'थाई', + 'ti' => 'तिगà¥à¤°à¤¿à¤¨à¥à¤¯à¤¾', + 'tk' => 'तà¥à¤°à¥à¤•à¤®à¥‡à¤¨', + 'tl' => 'तगालोग', + 'tn' => 'सेतà¥à¤¸à¥à¤µà¤¾à¤¨à¤¾', + 'to' => 'तोंगा', + 'tr' => 'तà¥à¤°à¥à¤•à¤¿à¤·', + 'ts' => 'तà¥à¤¸à¥‹à¤—ा', + 'tt' => 'टटार', + 'tw' => 'तà¥à¤µà¤¿', + 'ty' => 'Tahitian', + 'ug' => 'उधूर', + 'uk' => 'यà¥à¤•à¥à¤°à¥‡à¤¨à¤¿à¤¯à¤¨à¥', + 'ur' => 'उरà¥à¤¦à¥‚', + 'uz' => 'उज़बेक', + 've' => 'Venda', + 'vi' => 'वियतà¥à¤¨à¤¾à¤®à¥€à¤œà¤¼', + 'vo' => 'ओलापà¥à¤•', + 'wa' => 'Walloon', + 'wo' => 'उलोफ', + 'xh' => 'कà¥à¤¸à¥à¤¹à¥‹à¤¸à¤¾', + 'yi' => 'इदà¥à¤¦à¤¿à¤·', + 'yo' => 'यूरà¥à¤¬à¤¾', + 'za' => 'à¤à¥à¤¹à¥à¤¨à¥à¤—', + 'zh' => 'चिनीसà¥', + 'zu' => 'जà¥à¤²à¥‚', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ms.php b/lib/Pear/I18Nv2/Language/ms.php new file mode 100644 index 0000000..b973f36 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ms.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Bahasa Melayu', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/mt.php b/lib/Pear/I18Nv2/Language/mt.php new file mode 100644 index 0000000..200f3ec --- /dev/null +++ b/lib/Pear/I18Nv2/Language/mt.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkażjan', + 'ae' => 'Avestan', + 'af' => 'Afrikans', + 'ak' => 'Akan', + 'am' => 'Amħariku', + 'an' => 'Aragonese', + 'ar' => 'Għarbi', + 'as' => 'Assamese', + 'av' => 'Avarik', + 'ay' => 'Ajmara', + 'az' => 'AżerbajÄ¡ani', + 'ba' => 'Baxkir', + 'be' => 'Belarussu', + 'bg' => 'Bulgaru', + 'bh' => 'Biħari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetjan', + 'br' => 'Brenton', + 'bs' => 'Bosnijan', + 'ca' => 'Katalan', + 'ce' => 'ÄŠeÄ‹en', + 'ch' => 'ÄŠamorro', + 'co' => 'Korsiku', + 'cr' => 'Krij', + 'cs' => 'ÄŠek', + 'cu' => 'Slaviku tal-Knisja', + 'cv' => 'ÄŠuvax', + 'cy' => 'Welx', + 'da' => 'Daniż', + 'de' => 'Ä ermaniż', + 'dv' => 'Diveħi', + 'dz' => 'Dżongka', + 'ee' => 'Ewe', + 'el' => 'Grieg', + 'en' => 'Ingliż', + 'eo' => 'Esperanto', + 'es' => 'Spanjol', + 'et' => 'Estonjan', + 'eu' => 'Bask', + 'fa' => 'Persjan', + 'ff' => 'Fulaħ', + 'fi' => 'Finlandiż', + 'fj' => 'FiÄ¡i', + 'fo' => 'Fawriż', + 'fr' => 'FranÄ‹iż', + 'fy' => 'Friżjan', + 'ga' => 'Irlandiż', + 'gd' => 'Galliku SkoÄ‹Ä‹iż', + 'gl' => 'Gallegjan', + 'gn' => 'Gwarani', + 'gu' => 'GuÄ¡arati', + 'gv' => 'Manks', + 'ha' => 'Ħawsa', + 'he' => 'Ebrajk', + 'hi' => 'Ħindi', + 'ho' => 'Ħiri Motu', + 'hr' => 'Kroat', + 'ht' => 'Haitian', + 'hu' => 'Ungeriż', + 'hy' => 'Armenjan', + 'hz' => 'Ħerero', + 'ia' => 'Interlingua', + 'id' => 'Indoneżjan', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupjak', + 'io' => 'Ido', + 'is' => 'Iżlandiż', + 'it' => 'Taljan', + 'iu' => 'Inukitut', + 'ja' => 'Ä appuniż', + 'jv' => 'Ä avaniż', + 'ka' => 'Ä orÄ¡jan', + 'kg' => 'Kongo', + 'ki' => 'Kikuju', + 'kj' => 'Kuanyama', + 'kk' => 'Każak', + 'kl' => 'Kalallisut', + 'km' => 'Kmer', + 'kn' => 'Kannada', + 'ko' => 'Korejan', + 'kr' => 'Kanuri', + 'ks' => 'Kaxmiri', + 'ku' => 'Kurdiż', + 'kv' => 'Komi', + 'kw' => 'Korniku', + 'ky' => 'Kirgiż', + 'la' => 'Latin', + 'lb' => 'Letżburgiż', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingaljan', + 'lo' => 'Lao', + 'lt' => 'Litwanjan', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvjan (Lettix)', + 'mg' => 'Malagażi', + 'mh' => 'Marxall', + 'mi' => 'Maori', + 'mk' => 'MaÄ‹edonjan', + 'ml' => 'Malajalam', + 'mn' => 'Mongoljan', + 'mo' => 'Moldavjan', + 'mr' => 'Marati', + 'ms' => 'Malajan', + 'mt' => 'Malti', + 'my' => 'Burmiż', + 'na' => 'Nawuru', + 'nb' => 'Bokmahal NorveÄ¡iż', + 'nd' => 'Ndebele, ta’ Fuq', + 'ne' => 'Nepaliż', + 'ng' => 'Ndonga', + 'nl' => 'Olandiż', + 'nn' => 'Ninorsk NorveÄ¡iż', + 'no' => 'NorveÄ¡iż', + 'nr' => 'Ndebele, t’Isfel', + 'nv' => 'Navaħo', + 'ny' => 'ÄŠiÄ‹ewa; NjanÄ¡a', + 'oc' => 'Provenzal (wara 1500)', + 'oj' => 'OÄ¡ibwa', + 'om' => 'Oromo (Afan)', + 'or' => 'Orija', + 'os' => 'Ossettiku', + 'pa' => 'PunÄ¡abi', + 'pi' => 'Pali', + 'pl' => 'Pollakk', + 'ps' => 'Paxtun', + 'pt' => 'Portugiż', + 'qu' => 'KeÄ‹wa', + 'rm' => 'Reto-Romanz', + 'rn' => 'Rundi', + 'ro' => 'Rumen', + 'ru' => 'Russu', + 'rw' => 'Kinjarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinjan', + 'sd' => 'Sindi', + 'se' => 'Sami ta’ Fuq', + 'sg' => 'Sango', + 'sh' => 'Serbo-Kroat', + 'si' => 'Sinħaliż', + 'sk' => 'Slovakk', + 'sl' => 'Slav', + 'sm' => 'Samojan', + 'sn' => 'Xona', + 'so' => 'Somali', + 'sq' => 'Albaniż', + 'sr' => 'Serb', + 'ss' => 'Swati', + 'st' => 'Soto, t’Isfel', + 'su' => 'Sundaniż', + 'sv' => 'Svediż', + 'sw' => 'Swaħili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'TaÄ¡ik', + 'th' => 'Tajlandiż', + 'ti' => 'Tigrinja', + 'tk' => 'Turkmeni', + 'tl' => 'Tagalog', + 'tn' => 'Zwana', + 'to' => 'Tongan (Gżejjer ta’ Tonga)', + 'tr' => 'Tork', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Taħitjan', + 'ug' => 'Wigur', + 'uk' => 'Ukranjan', + 'ur' => 'Urdu', + 'uz' => 'Użbek', + 've' => 'Venda', + 'vi' => 'Vjetnamiż', + 'vo' => 'Volapuk', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Ħoża', + 'yi' => 'Jiddix', + 'yo' => 'Joruba', + 'za' => 'Å»wang', + 'zh' => 'ÄŠiniż', + 'zu' => 'Å»ulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/nb.php b/lib/Pear/I18Nv2/Language/nb.php new file mode 100644 index 0000000..33bcc4c --- /dev/null +++ b/lib/Pear/I18Nv2/Language/nb.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhasisk', + 'ae' => 'Avestisk', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharisk', + 'an' => 'Aragonsk', + 'ar' => 'Arabisk', + 'as' => 'Assamisk', + 'av' => 'Avarisk', + 'ay' => 'Aymara', + 'az' => 'Aserbajdsjansk', + 'ba' => 'Basjkirsk', + 'be' => 'Hviterussisk', + 'bg' => 'Bulgarsk', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetansk', + 'br' => 'Bretonsk', + 'bs' => 'Bosnisk', + 'ca' => 'Katalansk', + 'ce' => 'Tsjetsjensk', + 'ch' => 'Chamorro', + 'co' => 'Korsikansk', + 'cr' => 'Cree', + 'cs' => 'Tsjekkisk', + 'cu' => 'Kirkeslavisk', + 'cv' => 'Tsjuvansk', + 'cy' => 'Walisisk', + 'da' => 'Dansk', + 'de' => 'Tysk', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Gresk', + 'en' => 'Engelsk', + 'eo' => 'Esperanto', + 'es' => 'Spansk', + 'et' => 'Estisk', + 'eu' => 'Baskisk', + 'fa' => 'Persisk', + 'ff' => 'Fulani', + 'fi' => 'Finsk', + 'fj' => 'Fijiansk', + 'fo' => 'Færøysk', + 'fr' => 'Fransk', + 'fy' => 'Frisisk', + 'ga' => 'Irsk', + 'gd' => 'Skotsk gælisk', + 'gl' => 'Galicisk', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebraisk', + 'hi' => 'Hindi', + 'ho' => 'Hiri motu', + 'hr' => 'Kroatisk', + 'ht' => 'Haitisk', + 'hu' => 'Ungarsk', + 'hy' => 'Armensk', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesisk', + 'ie' => 'Interlingue', + 'ig' => 'Ibo', + 'ii' => 'Sichuan-yi', + 'ik' => 'Unupiak', + 'io' => 'Ido', + 'is' => 'Islandsk', + 'it' => 'Italiensk', + 'iu' => 'Inuktitut', + 'ja' => 'Japansk', + 'jv' => 'Javanesisk', + 'ka' => 'Georgisk', + 'kg' => 'Kikongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kasakhisk', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Koreansk', + 'kr' => 'Kanuri', + 'ks' => 'Kasjmiri', + 'ku' => 'Kurdisk', + 'kv' => 'Komi', + 'kw' => 'Kornisk', + 'ky' => 'Kirgisisk', + 'la' => 'Latin', + 'lb' => 'Luxemburgsk', + 'lg' => 'Ganda', + 'li' => 'Limburgisk', + 'ln' => 'Lingala', + 'lo' => 'Laotisk', + 'lt' => 'Litauisk', + 'lu' => 'Luba-katanga', + 'lv' => 'Latvisk', + 'mg' => 'Madagassisk', + 'mh' => 'Marshallesisk', + 'mi' => 'Maori', + 'mk' => 'Makedonsk', + 'ml' => 'Malayalam', + 'mn' => 'Mongolsk', + 'mo' => 'Moldavisk', + 'mr' => 'Marathi', + 'ms' => 'Malayisk', + 'mt' => 'Maltesisk', + 'my' => 'Burmesisk', + 'na' => 'Nauru', + 'nb' => 'Norsk bokmÃ¥l', + 'nd' => 'Ndebele (nord)', + 'ne' => 'Nepalsk', + 'ng' => 'Ndonga', + 'nl' => 'Nederlandsk', + 'nn' => 'Norsk nynorsk', + 'no' => 'Norsk', + 'nr' => 'Ndebele, sør', + 'nv' => 'Navajo', + 'ny' => 'Nyanja', + 'oc' => 'Oksitansk (etter 1500)', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetisk', + 'pa' => 'Panjabi', + 'pi' => 'Pali', + 'pl' => 'Polsk', + 'ps' => 'Pashto', + 'pt' => 'Portugisisk', + 'qu' => 'Quechua', + 'rm' => 'Retoromansk', + 'rn' => 'Rundi', + 'ro' => 'Rumensk', + 'ru' => 'Russisk', + 'rw' => 'Kinjarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinsk', + 'sd' => 'Sindhi', + 'se' => 'Nordsamisk', + 'sg' => 'Sango', + 'sh' => 'Serbokroatisk', + 'si' => 'Singalesisk', + 'sk' => 'Slovakisk', + 'sl' => 'Slovensk', + 'sm' => 'Samoansk', + 'sn' => 'Shona', + 'so' => 'Somalisk', + 'sq' => 'Albansk', + 'sr' => 'Serbisk', + 'ss' => 'Swati', + 'st' => 'Sotho (sørlig)', + 'su' => 'Sundanesisk', + 'sv' => 'Svensk', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tatsjikisk', + 'th' => 'Thai', + 'ti' => 'Tigrinja', + 'tk' => 'Turkmensk', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga-øyene)', + 'tr' => 'Tyrkisk', + 'ts' => 'Tsonga', + 'tt' => 'Tatarisk', + 'tw' => 'Twi', + 'ty' => 'Tahitisk', + 'ug' => 'Uigurisk', + 'uk' => 'Ukrainsk', + 'ur' => 'Urdu', + 'uz' => 'Usbekisk', + 've' => 'Venda', + 'vi' => 'Vietnamesisk', + 'vo' => 'Volapyk', + 'wa' => 'Vallonsk', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Jiddisk', + 'yo' => 'Joruba', + 'za' => 'Zhuang', + 'zh' => 'Kinesisk', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/nl.php b/lib/Pear/I18Nv2/Language/nl.php new file mode 100644 index 0000000..06925a8 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/nl.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abchazisch', + 'ae' => 'Avestisch', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amhaars', + 'an' => 'Aragonees', + 'ar' => 'Arabisch', + 'as' => 'Assamees', + 'av' => 'Avarisch', + 'ay' => 'Aymara', + 'az' => 'Azerbeidzjaans', + 'ba' => 'Basjkiers', + 'be' => 'Wit-Russisch', + 'bg' => 'Bulgaars', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengalees', + 'bo' => 'Tibetaans', + 'br' => 'Bretons', + 'bs' => 'Bosnisch', + 'ca' => 'Catalaans', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsicaans', + 'cr' => 'Cree', + 'cs' => 'Tsjechisch', + 'cu' => 'Kerkslavisch', + 'cv' => 'Tsjoevasjisch', + 'cy' => 'Welsh', + 'da' => 'Deens', + 'de' => 'Duits', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Grieks', + 'en' => 'Engels', + 'eo' => 'Esperanto', + 'es' => 'Spaans', + 'et' => 'Estlands', + 'eu' => 'Baskisch', + 'fa' => 'Perzisch', + 'ff' => 'Fulah', + 'fi' => 'Fins', + 'fj' => 'Fijisch', + 'fo' => 'Faeröers', + 'fr' => 'Frans', + 'fy' => 'Fries', + 'ga' => 'Iers', + 'gd' => 'Schots Gaelic', + 'gl' => 'Galicisch', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebreeuws', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Kroatisch', + 'ht' => 'Haïtiaans', + 'hu' => 'Hongaars', + 'hy' => 'Armeens', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesisch', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'IJslands', + 'it' => 'Italiaans', + 'iu' => 'Inuktitut', + 'ja' => 'Japans', + 'jv' => 'Javaans', + 'ka' => 'Georgisch', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazachs', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Koreaans', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Koerdisch', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirgizisch', + 'la' => 'Latijn', + 'lb' => 'Luxemburgs', + 'lg' => 'Ganda', + 'li' => 'Limburgs', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Litouws', + 'lu' => 'Luba-Katanga', + 'lv' => 'Letlands', + 'mg' => 'Malagasisch', + 'mh' => 'Marshallees', + 'mi' => 'Maori', + 'mk' => 'Macedonisch', + 'ml' => 'Malayalam', + 'mn' => 'Mongools', + 'mo' => 'Moldavisch', + 'mr' => 'Marathi', + 'ms' => 'Maleis', + 'mt' => 'Maltees', + 'my' => 'Birmees', + 'na' => 'Nauru', + 'nb' => 'Noors - BokmÃ¥l', + 'nd' => 'Ndebele, noord-', + 'ne' => 'Nepalees', + 'ng' => 'Ndonga', + 'nl' => 'Nederlands', + 'nn' => 'Noors - Nynorsk', + 'no' => 'Noors', + 'nr' => 'Ndebele, zuid-', + 'nv' => 'Navajo', + 'ny' => 'Nyanja', + 'oc' => 'Langue d’Oc (na 1500)', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetisch', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Pools', + 'ps' => 'Pashto', + 'pt' => 'Portugees', + 'qu' => 'Quechua', + 'rm' => 'Retoromaans', + 'rn' => 'Rundi', + 'ro' => 'Roemeens', + 'ru' => 'Russisch', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinisch', + 'sd' => 'Sindhi', + 'se' => 'Noord-Samisch', + 'sg' => 'Sango', + 'sh' => 'Servokroatisch', + 'si' => 'Singalees', + 'sk' => 'Slowaaks', + 'sl' => 'Sloveens', + 'sm' => 'Samoaans', + 'sn' => 'Shona', + 'so' => 'Somalisch', + 'sq' => 'Albanees', + 'sr' => 'Servisch', + 'ss' => 'Swati', + 'st' => 'Sotho, zuid', + 'su' => 'Sundanees', + 'sv' => 'Zweeds', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Teloegoe', + 'tg' => 'Tadzjik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmeens', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga-eilanden)', + 'tr' => 'Turks', + 'ts' => 'Tsonga', + 'tt' => 'Tataars', + 'tw' => 'Twi', + 'ty' => 'Tahitisch', + 'ug' => 'Uighur', + 'uk' => 'Oekraïens', + 'ur' => 'Urdu', + 'uz' => 'Oezbeeks', + 've' => 'Venda', + 'vi' => 'Vietnamees', + 'vo' => 'Volapük', + 'wa' => 'Wallonisch', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Jiddisch', + 'yo' => 'Joruba', + 'za' => 'Zhuang', + 'zh' => 'Chinees', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/nn.php b/lib/Pear/I18Nv2/Language/nn.php new file mode 100644 index 0000000..82538f9 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/nn.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabisk', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'Tysk', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'Engelsk', + 'eo' => 'Esperanto', + 'es' => 'Spansk', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Fransk', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italiensk', + 'iu' => 'Inuktitut', + 'ja' => 'Japansk', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norsk bokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norsk nynorsk', + 'no' => 'Norsk', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugisisk', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russisk', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Kinesisk', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/om.php b/lib/Pear/I18Nv2/Language/om.php new file mode 100644 index 0000000..6e1396d --- /dev/null +++ b/lib/Pear/I18Nv2/Language/om.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromoo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/or.php b/lib/Pear/I18Nv2/Language/or.php new file mode 100644 index 0000000..fd20b9c --- /dev/null +++ b/lib/Pear/I18Nv2/Language/or.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'ଓଡ଼ିଆ', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/pa.php b/lib/Pear/I18Nv2/Language/pa.php new file mode 100644 index 0000000..bdee95d --- /dev/null +++ b/lib/Pear/I18Nv2/Language/pa.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'ਪੰਜਾਬੀ', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/pl.php b/lib/Pear/I18Nv2/Language/pl.php new file mode 100644 index 0000000..3ef45b3 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/pl.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabski', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'BuÅ‚garski', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czeski', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'DuÅ„ski', + 'de' => 'Niemiecki', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Grecki', + 'en' => 'Angielski', + 'eo' => 'Esperanto', + 'es' => 'HiszpaÅ„ski', + 'et' => 'EstoÅ„ski', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'FiÅ„ski', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Francuski', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrajski', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Chorwacki', + 'ht' => 'Haitian', + 'hu' => 'WÄ™gierski', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'WÅ‚oski', + 'iu' => 'Inuktitut', + 'ja' => 'JapoÅ„ski', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'KoreaÅ„ski', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Litewski', + 'lu' => 'Luba-Katanga', + 'lv' => 'Åotewski', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Holenderski', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norweski', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polski', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugalski', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'RumuÅ„ski', + 'ru' => 'Rosyjski', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'SÅ‚owacki', + 'sl' => 'SÅ‚oweÅ„ski', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Szwedzki', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turecki', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'ChiÅ„ski', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ps.php b/lib/Pear/I18Nv2/Language/ps.php new file mode 100644 index 0000000..44e3b6e --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ps.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'عربي', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'الماني', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'یوناني', + 'en' => 'انګلیسي', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'حبشي', + 'eu' => 'Basque', + 'fa' => 'Ùارسي', + 'ff' => 'Fulah', + 'fi' => 'Ùینلنډي', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Ùرانسوي', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'عبري', + 'hi' => 'هندي', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'ارمني', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ایټالوي', + 'iu' => 'Inuktitut', + 'ja' => 'جاپانی', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'کردي', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'لاتیني', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'ملغاسي', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'مقدوني', + 'ml' => 'Malayalam', + 'mn' => 'مغولي', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'ملایا', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'پولنډي', + 'ps' => 'پښتو', + 'pt' => 'پورتګالي', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'روسي', + 'rw' => 'Kinyarwanda', + 'sa' => 'سنسکریټ', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'سویډنی', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'تاجک', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'ترکمني', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'تاتار', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'ازبکي', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'چیني', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/pt.php b/lib/Pear/I18Nv2/Language/pt.php new file mode 100644 index 0000000..0b1208a --- /dev/null +++ b/lib/Pear/I18Nv2/Language/pt.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avéstico', + 'af' => 'Africâner', + 'ak' => 'Akan', + 'am' => 'Amárico', + 'an' => 'Aragonês', + 'ar' => 'Ãrabe', + 'as' => 'Assamês', + 'av' => 'Avaric', + 'ay' => 'Aimara', + 'az' => 'Azerbaijano', + 'ba' => 'Bashkir', + 'be' => 'Bielo-russo', + 'bg' => 'Búlgaro', + 'bh' => 'Biari', + 'bi' => 'Bislamá', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetano', + 'br' => 'Bretão', + 'bs' => 'Bósnio', + 'ca' => 'Catalão', + 'ce' => 'Chechene', + 'ch' => 'Chamorro', + 'co' => 'Córsico', + 'cr' => 'Cree', + 'cs' => 'Tcheco', + 'cu' => 'Eslavo eclesiástico', + 'cv' => 'Chuvash', + 'cy' => 'Galês', + 'da' => 'Dinamarquês', + 'de' => 'Alemão', + 'dv' => 'Divehi', + 'dz' => 'Dzonga', + 'ee' => 'Eve', + 'el' => 'Grego', + 'en' => 'Inglês', + 'eo' => 'Esperanto', + 'es' => 'Espanhol', + 'et' => 'Estoniano', + 'eu' => 'Basco', + 'fa' => 'Persa', + 'ff' => 'Fula', + 'fi' => 'Finlandês', + 'fj' => 'Fijiano', + 'fo' => 'Feroês', + 'fr' => 'Francês', + 'fy' => 'Frisão', + 'ga' => 'Irlandês', + 'gd' => 'Gaélico escocês', + 'gl' => 'Galego', + 'gn' => 'Guarani', + 'gu' => 'Guzerate', + 'gv' => 'Manx', + 'ha' => 'Hauçá', + 'he' => 'Hebraico', + 'hi' => 'Hindi', + 'ho' => 'Hiri motu', + 'hr' => 'Croata', + 'ht' => 'Haitiano', + 'hu' => 'Húngaro', + 'hy' => 'Armênio', + 'hz' => 'Herero', + 'ia' => 'Interlíngua', + 'id' => 'Indonésio', + 'ie' => 'Interlingue', + 'ig' => 'Ibo', + 'ii' => 'Sichuan yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Islandês', + 'it' => 'Italiano', + 'iu' => 'Inuktitut', + 'ja' => 'Japonês', + 'jv' => 'Javanese', + 'ka' => 'Georgiano', + 'kg' => 'Congolês', + 'ki' => 'Quicuio', + 'kj' => 'Kuanyama', + 'kk' => 'Cazaque', + 'kl' => 'Groenlandês', + 'km' => 'Cmer', + 'kn' => 'Canarês', + 'ko' => 'Coreano', + 'kr' => 'Canúri', + 'ks' => 'Kashmiri', + 'ku' => 'Curdo', + 'kv' => 'Komi', + 'kw' => 'Córnico', + 'ky' => 'Quirguiz', + 'la' => 'Latim', + 'lb' => 'Luxemburguês', + 'lg' => 'Luganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Laosiano', + 'lt' => 'Lituano', + 'lu' => 'Luba-catanga', + 'lv' => 'Letão', + 'mg' => 'Malgaxe', + 'mh' => 'Marshallês', + 'mi' => 'Maori', + 'mk' => 'Macedônio', + 'ml' => 'Malaiala', + 'mn' => 'Mongol', + 'mo' => 'Moldávio', + 'mr' => 'Marata', + 'ms' => 'Malaio', + 'mt' => 'Maltês', + 'my' => 'Birmanês', + 'na' => 'Nauruano', + 'nb' => 'BokmÃ¥l norueguês', + 'nd' => 'Ndebele, north', + 'ne' => 'Nepali', + 'ng' => 'Dongo', + 'nl' => 'Holandês', + 'nn' => 'Nynorsk norueguês', + 'no' => 'Norueguês', + 'nr' => 'Ndebele, south', + 'nv' => 'Navajo', + 'ny' => 'Nianja; chicheua; cheua', + 'oc' => 'Occitânico (após 1500); provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Panjabi', + 'pi' => 'Páli', + 'pl' => 'Polonês', + 'ps' => 'Pashto (pushto)', + 'pt' => 'Português', + 'qu' => 'Quíchua', + 'rm' => 'Rhaeto-romance', + 'rn' => 'Rundi', + 'ro' => 'Romeno', + 'ru' => 'Russo', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sânscrito', + 'sc' => 'Sardo', + 'sd' => 'Sindi', + 'se' => 'Northern sami', + 'sg' => 'Sango', + 'sh' => 'Servo-croata', + 'si' => 'Cingalês', + 'sk' => 'Eslovaco', + 'sl' => 'Eslovênio', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanês', + 'sr' => 'Sérvio', + 'ss' => 'Swati', + 'st' => 'Soto, do sul', + 'su' => 'Sundanês', + 'sv' => 'Sueco', + 'sw' => 'Suaíli', + 'ta' => 'Tâmil', + 'te' => 'Telugu', + 'tg' => 'Tadjique', + 'th' => 'Tailandês', + 'ti' => 'Tigrínia', + 'tk' => 'Turcomano', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (ilhas tonga)', + 'tr' => 'Turco', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Taitiano', + 'ug' => 'Uighur', + 'uk' => 'Ucraniano', + 'ur' => 'Urdu', + 'uz' => 'Usbeque', + 've' => 'Venda', + 'vi' => 'Vietnamita', + 'vo' => 'Volapuque', + 'wa' => 'Walloon', + 'wo' => 'Uolofe', + 'xh' => 'Xosa', + 'yi' => 'Iídiche', + 'yo' => 'Ioruba', + 'za' => 'Zhuang', + 'zh' => 'Chinês', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ro.php b/lib/Pear/I18Nv2/Language/ro.php new file mode 100644 index 0000000..c520b8e --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ro.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabă', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgară', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Cehă', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Daneză', + 'de' => 'Germană', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greacă', + 'en' => 'Engleză', + 'eo' => 'Esperanto', + 'es' => 'Spaniolă', + 'et' => 'Estoniană', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finlandeză', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Franceză', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Ebraică', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croată', + 'ht' => 'Haitian', + 'hu' => 'Maghiară', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italiană', + 'iu' => 'Inuktitut', + 'ja' => 'Japoneză', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Coreeană', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lituaniană', + 'lu' => 'Luba-Katanga', + 'lv' => 'Letonă', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Olandeză', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norvegiană', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Poloneză', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugheză', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Română', + 'ru' => 'Rusă', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovacă', + 'sl' => 'Slovenă', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Suedeză', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turcă', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chineză', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ru.php b/lib/Pear/I18Nv2/Language/ru.php new file mode 100644 index 0000000..19aa48c --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ru.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Ðфар', + 'ab' => 'ÐбхазÑкий', + 'ae' => 'Avestan', + 'af' => 'ÐфрикаанÑ', + 'ak' => 'Akan', + 'am' => 'ÐмхарÑкий', + 'an' => 'Aragonese', + 'ar' => 'ÐрабÑкий', + 'as' => 'ÐÑÑамÑкий', + 'av' => 'Avaric', + 'ay' => 'Ðймара', + 'az' => 'ÐзербайджанÑкий', + 'ba' => 'БашкирÑкий', + 'be' => 'БелоруÑÑкий', + 'bg' => 'БолгарÑкий', + 'bh' => 'Бихари', + 'bi' => 'БиÑлама', + 'bm' => 'Bambara', + 'bn' => 'БенгальÑкий', + 'bo' => 'ТибетÑкий', + 'br' => 'БретонÑкий', + 'bs' => 'Bosnian', + 'ca' => 'КаталанÑкий', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'КорÑиканÑкий', + 'cr' => 'Cree', + 'cs' => 'ЧешÑкий', + 'cu' => 'Church Slavic', + 'cv' => 'ЧувашÑкий', + 'cy' => 'ВаллийÑкий', + 'da' => 'ДатÑкий', + 'de' => 'Ðемецкий', + 'dv' => 'Divehi', + 'dz' => 'Дзонг-кÑ', + 'ee' => 'Ewe', + 'el' => 'ГречеÑкий', + 'en' => 'ÐнглийÑкий', + 'eo' => 'ЭÑперанто', + 'es' => 'ИÑпанÑкий', + 'et' => 'ЭÑтонÑкий', + 'eu' => 'БаÑкÑкий', + 'fa' => 'ПерÑидÑкий', + 'ff' => 'Fulah', + 'fi' => 'ФинÑкий', + 'fj' => 'Фиджи', + 'fo' => 'ФарерÑкий', + 'fr' => 'ФранцузÑкий', + 'fy' => 'ФризÑкий', + 'ga' => 'ИрландÑкий', + 'gd' => 'ГаÑльÑкий', + 'gl' => 'ГалиÑийÑкий', + 'gn' => 'Гуарани', + 'gu' => 'Гуджарати', + 'gv' => 'Manx', + 'ha' => 'ХауÑа', + 'he' => 'Иврит', + 'hi' => 'Хинди', + 'ho' => 'Hiri Motu', + 'hr' => 'ХорватÑкий', + 'ht' => 'Haitian', + 'hu' => 'ВенгерÑкий', + 'hy' => 'ÐрмÑнÑкий', + 'hz' => 'Herero', + 'ia' => 'Интерлингва', + 'id' => 'ИндонезийÑкий', + 'ie' => 'Интерлингве', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Инупиак', + 'io' => 'Ido', + 'is' => 'ИÑландÑкий', + 'it' => 'ИтальÑнÑкий', + 'iu' => 'Инуктитут', + 'ja' => 'ЯпонÑкий', + 'jv' => 'ЯванÑкий', + 'ka' => 'ГрузинÑкий', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'КазахÑкий', + 'kl' => 'ЭÑкимоÑÑкий (гренландÑкий)', + 'km' => 'КхмерÑкий', + 'kn' => 'Каннада', + 'ko' => 'КорейÑкий', + 'kr' => 'Kanuri', + 'ks' => 'Кашмири', + 'ku' => 'КурдÑкий', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'КиргизÑкий', + 'la' => 'ЛатинÑкий', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Лингала', + 'lo' => 'ЛаоÑÑкий', + 'lt' => 'ЛитовÑкий', + 'lu' => 'Луба-Катанга', + 'lv' => 'ЛатышÑкий', + 'mg' => 'МалагаÑийÑкий', + 'mh' => 'Marshallese', + 'mi' => 'Маори', + 'mk' => 'МакедонÑкий', + 'ml' => 'МалаÑлам', + 'mn' => 'МонгольÑкий', + 'mo' => 'МолдавÑкий', + 'mr' => 'Маратхи', + 'ms' => 'МалайÑкий', + 'mt' => 'МальтийÑкий', + 'my' => 'БирманÑкий', + 'na' => 'Ðауру', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ÐепальÑкий', + 'ng' => 'Ndonga', + 'nl' => 'ÐидерландÑкий (голландÑкий)', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'ÐорвежÑкий', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ОкÑитанÑкий', + 'oj' => 'Оджибва', + 'om' => 'Оромо', + 'or' => 'ОриÑ', + 'os' => 'ОÑетинÑкий', + 'pa' => 'Панджаби (пенджаби)', + 'pi' => 'Пали', + 'pl' => 'ПольÑкий', + 'ps' => 'Пашто (пушту)', + 'pt' => 'ПортугальÑкий', + 'qu' => 'Кечуа', + 'rm' => 'РетороманÑкий', + 'rn' => 'Рунди', + 'ro' => 'РумынÑкий', + 'ru' => 'РуÑÑкий', + 'rw' => 'КиньÑруанда', + 'sa' => 'СанÑкрит', + 'sc' => 'Sardinian', + 'sd' => 'Синдхи', + 'se' => 'Northern Sami', + 'sg' => 'Санго', + 'sh' => 'СербÑкохорватÑкий', + 'si' => 'СингальÑкий', + 'sk' => 'Словацкий', + 'sl' => 'СловенÑкий', + 'sm' => 'СамоанÑкий', + 'sn' => 'Шона', + 'so' => 'Сомали', + 'sq' => 'ÐлбанÑкий', + 'sr' => 'СербÑкий', + 'ss' => 'Свази', + 'st' => 'Сото южный', + 'su' => 'СунданÑкий', + 'sv' => 'ШведÑкий', + 'sw' => 'Суахили', + 'ta' => 'ТамильÑкий', + 'te' => 'Телугу', + 'tg' => 'ТаджикÑкий', + 'th' => 'ТайÑкий', + 'ti' => 'ТигриньÑ', + 'tk' => 'ТуркменÑкий', + 'tl' => 'Тагалог', + 'tn' => 'ТÑвана', + 'to' => 'Тонга', + 'tr' => 'Турецкий', + 'ts' => 'ТÑонга', + 'tt' => 'ТатарÑкий', + 'tw' => 'Тви', + 'ty' => 'Tahitian', + 'ug' => 'УйгурÑкий', + 'uk' => 'УкраинÑкий', + 'ur' => 'Урду', + 'uz' => 'УзбекÑкий', + 've' => 'Venda', + 'vi' => 'ВьетнамÑкий', + 'vo' => 'Волапюк', + 'wa' => 'Walloon', + 'wo' => 'Волоф', + 'xh' => 'КоÑа', + 'yi' => 'Идиш', + 'yo' => 'Йоруба', + 'za' => 'Чжуань', + 'zh' => 'КитайÑкий', + 'zu' => 'Зулу', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sa.php b/lib/Pear/I18Nv2/Language/sa.php new file mode 100644 index 0000000..b5ed74b --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sa.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'संसà¥à¤•à¥ƒà¤¤', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sh.php b/lib/Pear/I18Nv2/Language/sh.php new file mode 100644 index 0000000..405a745 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sh.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sk.php b/lib/Pear/I18Nv2/Language/sk.php new file mode 100644 index 0000000..e926833 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sk.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabský', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulharský', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ÄŒeský', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Dánsky', + 'de' => 'Nemecký', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Grécky', + 'en' => 'Anglický', + 'eo' => 'Esperanto', + 'es' => 'Å panielsky', + 'et' => 'Estónsky', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Fínsky', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Francúzsky', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrejský', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Chorvátsky', + 'ht' => 'Haitian', + 'hu' => 'MaÄarský', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Taliansky', + 'iu' => 'Inuktitut', + 'ja' => 'Japonský', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Kórejský', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Litovský', + 'lu' => 'Luba-Katanga', + 'lv' => 'LotyÅ¡ský', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Holandský', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Nórsky', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Poľský', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugalský', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Rumunský', + 'ru' => 'Ruský', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovenský', + 'sl' => 'Slovinský', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Å védsky', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turecký', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Čínsky', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sl.php b/lib/Pear/I18Nv2/Language/sl.php new file mode 100644 index 0000000..661e429 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sl.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ArabÅ¡Äina', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'BolgarÅ¡Äina', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'ÄŒeÅ¡Äina', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'DanÅ¡Äina', + 'de' => 'NemÅ¡Äina', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'GrÅ¡Äina', + 'en' => 'AngleÅ¡Äina', + 'eo' => 'Esperanto', + 'es' => 'Å panÅ¡Äina', + 'et' => 'EstonÅ¡Äina', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'FinÅ¡Äina', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'FrancoÅ¡Äina', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'HebrejÅ¡Äina', + 'hi' => 'HindujÅ¡Äina', + 'ho' => 'Hiri Motu', + 'hr' => 'HrvaÅ¡Äina', + 'ht' => 'Haitian', + 'hu' => 'MadžarÅ¡Äina', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ItalijanÅ¡Äina', + 'iu' => 'Inuktitut', + 'ja' => 'JaponÅ¡Äina', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'KorejÅ¡Äina', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'LitovÅ¡Äina', + 'lu' => 'Luba-Katanga', + 'lv' => 'LetonÅ¡Äina', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'NizozemÅ¡Äina', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'NorveÅ¡Äina', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'PoljÅ¡Äina', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'PortugalÅ¡Äina', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'RomunÅ¡Äina', + 'ru' => 'RuÅ¡Äina', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'SlovaÅ¡Äina', + 'sl' => 'SlovenÅ¡Äina', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Å vedÅ¡Äina', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'TurÅ¡Äina', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'KitajÅ¡Äina', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/so.php b/lib/Pear/I18Nv2/Language/so.php new file mode 100644 index 0000000..d791d1c --- /dev/null +++ b/lib/Pear/I18Nv2/Language/so.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Soomaali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sq.php b/lib/Pear/I18Nv2/Language/sq.php new file mode 100644 index 0000000..f7b8aa9 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sq.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabisht', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'Gjermanisht', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'Anglisht', + 'eo' => 'Esperanto', + 'es' => 'Spanjisht', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Frengjisht', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italisht', + 'iu' => 'Inuktitut', + 'ja' => 'Japanisht', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portugeze', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Rusisht', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Shqipe', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Kineze', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sr.php b/lib/Pear/I18Nv2/Language/sr.php new file mode 100644 index 0000000..b78a899 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sr.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'ÐфриканерÑки', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'ÐрапÑки', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'БелоруÑки', + 'bg' => 'БугарÑки', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'БретонÑки', + 'bs' => 'Bosnian', + 'ca' => 'КаталонÑки', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'КорзиканÑки', + 'cr' => 'Cree', + 'cs' => 'Чешки', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'ДанÑки', + 'de' => 'Ðемачки', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Грчки', + 'en' => 'ЕнглеÑки', + 'eo' => 'ЕÑперанто', + 'es' => 'ШпанÑки', + 'et' => 'ЕÑтонÑки', + 'eu' => 'БаÑкијÑки', + 'fa' => 'ПерÑијÑки', + 'ff' => 'Fulah', + 'fi' => 'ФинÑки', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'ФранцуÑки', + 'fy' => 'Frisian', + 'ga' => 'ИрÑки', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'ХебрејÑки', + 'hi' => 'Хинди', + 'ho' => 'Hiri Motu', + 'hr' => 'ХрватÑки', + 'ht' => 'Haitian', + 'hu' => 'МађарÑки', + 'hy' => 'ÐрменÑки', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'ИндонезијÑки', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'ИÑландÑки', + 'it' => 'ИталијанÑки', + 'iu' => 'Inuktitut', + 'ja' => 'ЈапанÑки', + 'jv' => 'Javanese', + 'ka' => 'ГрузијÑки', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'КмерÑки', + 'kn' => 'Kannada', + 'ko' => 'КорејÑки', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'КурдÑки', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'КиргиÑки', + 'la' => 'ЛатинÑки', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'ЛитванÑки', + 'lu' => 'Luba-Katanga', + 'lv' => 'ЛетонÑки', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'МакедонÑки', + 'ml' => 'Malayalam', + 'mn' => 'МонголÑки', + 'mo' => 'МолдавÑки', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'БурманÑки', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'ХоландÑки', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Ðорвешки', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'ПољÑки', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'ПортугалÑки', + 'qu' => 'Quechua', + 'rm' => 'Рето-РоманÑки', + 'rn' => 'Rundi', + 'ro' => 'РумунÑки', + 'ru' => 'РуÑки', + 'rw' => 'Kinyarwanda', + 'sa' => 'СанÑкрит', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'СрпÑко-ХрватÑки', + 'si' => 'Sinhalese', + 'sk' => 'Словачки', + 'sl' => 'Словеначки', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'ÐлбанÑки', + 'sr' => 'СрпÑки', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'ШведÑки', + 'sw' => 'Свахили', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'ТурÑки', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'УкрајинÑки', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'ВијетнамÑки', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Јидиш', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'КинеÑки', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sv.php b/lib/Pear/I18Nv2/Language/sv.php new file mode 100644 index 0000000..9d1cc9e --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sv.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhaziska', + 'ae' => 'Avestiska', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amhariska', + 'an' => 'Aragonesiska', + 'ar' => 'Arabiska', + 'as' => 'Assami', + 'av' => 'Avariska', + 'ay' => 'Aymara', + 'az' => 'Azerbajdzjanska', + 'ba' => 'Basjkiriska', + 'be' => 'Vitryska', + 'bg' => 'Bulgariska', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetanska', + 'br' => 'Bretonska', + 'bs' => 'Bosniska', + 'ca' => 'Katalanska', + 'ce' => 'Tjetjenska', + 'ch' => 'Chamorro', + 'co' => 'Korsikanska', + 'cr' => 'Cree', + 'cs' => 'Tjeckiska', + 'cu' => 'Kyrkoslaviska', + 'cv' => 'Tjuvasjiska', + 'cy' => 'Walesiska', + 'da' => 'Danska', + 'de' => 'Tyska', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Grekiska', + 'en' => 'Engelska', + 'eo' => 'Esperanto', + 'es' => 'Spanska', + 'et' => 'Estniska', + 'eu' => 'Baskiska', + 'fa' => 'Persiska', + 'ff' => 'Fulani', + 'fi' => 'Finska', + 'fj' => 'Fidjianska', + 'fo' => 'Färöiska', + 'fr' => 'Franska', + 'fy' => 'Frisiska', + 'ga' => 'Irländsk gaeliska', + 'gd' => 'Skotsk gaeliska', + 'gl' => 'Galiciska', + 'gn' => 'Guaraní', + 'gu' => 'Gujarati', + 'gv' => 'Manx gaeliska', + 'ha' => 'Haussa', + 'he' => 'Hebreiska', + 'hi' => 'Hindi', + 'ho' => 'Hiri motu', + 'hr' => 'Kroatiska', + 'ht' => 'Haitiska', + 'hu' => 'Ungerska', + 'hy' => 'Armeniska', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesiska', + 'ie' => 'Interlingue', + 'ig' => 'Ibo', + 'ii' => 'Sichuan yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Isländska', + 'it' => 'Italienska', + 'iu' => 'Inuktitut', + 'ja' => 'Japanska', + 'jv' => 'Javanesiska', + 'ka' => 'Georgiska', + 'kg' => 'Kikongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakstanska', + 'kl' => 'Grönländska', + 'km' => 'Kambodjanska; khmeriska', + 'kn' => 'Kanaresiska; kannada', + 'ko' => 'Koreanska', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiriska', + 'ku' => 'Kurdiska', + 'kv' => 'Kome', + 'kw' => 'Korniska', + 'ky' => 'Kirgisiska', + 'la' => 'Latin', + 'lb' => 'Luxemburgiska', + 'lg' => 'Luganda', + 'li' => 'Limburgiska', + 'ln' => 'Lingala', + 'lo' => 'Laotiska', + 'lt' => 'Litauiska', + 'lu' => 'Luba-katanga', + 'lv' => 'Lettiska', + 'mg' => 'Malagassiska', + 'mh' => 'Marshalliska', + 'mi' => 'Maori', + 'mk' => 'Makedonska', + 'ml' => 'Malayalam', + 'mn' => 'Mongoliska', + 'mo' => 'Moldaviska', + 'mr' => 'Marathi', + 'ms' => 'Malajiska', + 'mt' => 'Maltesiska', + 'my' => 'Burmanska', + 'na' => 'Nauru', + 'nb' => 'Norskt bokmÃ¥l', + 'nd' => 'Nord­ndebele', + 'ne' => 'Nepalesisika', + 'ng' => 'Ndonga', + 'nl' => 'Nederländska', + 'nn' => 'Ny­norsk', + 'no' => 'Norska', + 'nr' => 'Syd­ndebele', + 'nv' => 'Navaho', + 'ny' => 'Nyanja', + 'oc' => 'Provensalska (efter 1500); occitanska', + 'oj' => 'Odjibwa; chippewa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetiska', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polska', + 'ps' => 'Pashto; afghanska', + 'pt' => 'Portugisiska', + 'qu' => 'Quechua', + 'rm' => 'Räto­romanska', + 'rn' => 'Rundi', + 'ro' => 'Rumänska', + 'ru' => 'Ryska', + 'rw' => 'Rwanda; kinjarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardiska', + 'sd' => 'Sindhi', + 'se' => 'Nord­samiska', + 'sg' => 'Sango', + 'sh' => 'Serbokroatiska', + 'si' => 'Singalesiska', + 'sk' => 'Slovakiska', + 'sl' => 'Slovenska', + 'sm' => 'Samoanska', + 'sn' => 'Shona; manshona', + 'so' => 'Somaliska', + 'sq' => 'Albanska', + 'sr' => 'Serbiska', + 'ss' => 'Swati', + 'st' => 'Syd­sotho', + 'su' => 'Sundanesiska', + 'sv' => 'Svenska', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tadzjikiska', + 'th' => 'Thailändska', + 'ti' => 'Tigrinja', + 'tk' => 'Turkmeniska', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonganska', + 'tr' => 'Turkiska', + 'ts' => 'Tsonga', + 'tt' => 'Tatariska', + 'tw' => 'Twi', + 'ty' => 'Tahitiska', + 'ug' => 'Uiguriska', + 'uk' => 'Ukrainska', + 'ur' => 'Urdu', + 'uz' => 'Uzbekiska', + 've' => 'Venda', + 'vi' => 'Vietnamesiska', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Jiddisch', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Kinesiska', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/sw.php b/lib/Pear/I18Nv2/Language/sw.php new file mode 100644 index 0000000..0415292 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/sw.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Kiswahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ta.php b/lib/Pear/I18Nv2/Language/ta.php new file mode 100644 index 0000000..ca1546b --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ta.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'அபாரà¯', + 'ab' => 'அபà¯à®•à®¾à®¸à®¿à®©à¯', + 'ae' => 'Avestan', + 'af' => 'ஆபà¯à®°à®¿à®•à®©à¯à®¸à¯', + 'ak' => 'Akan', + 'am' => 'à®…à®®à¯à®¹à®¾à®°à®¿à®•à¯', + 'an' => 'Aragonese', + 'ar' => 'அரபà¯', + 'as' => 'அஸà¯à®¸à®¾à®®à®¿', + 'av' => 'Avaric', + 'ay' => 'அயமரா', + 'az' => 'அசரà¯à®ªà®¾à®¯à¯à®œà®¾à®©à®¿', + 'ba' => 'பாஷà¯à®•à®¿à®°à¯0', + 'be' => 'பைலோரà¯à®·à¯à®©à¯', + 'bg' => 'பலà¯à®•à¯‡à®°à®¿à®¯à®©à¯', + 'bh' => 'பிஹாரி', + 'bi' => 'பிஸà¯à®²à®¾à®®à®¾', + 'bm' => 'Bambara', + 'bn' => 'வஙà¯à®•à®¾à®³à®®à¯', + 'bo' => 'திபெதà¯à®¤à¯', + 'br' => 'பிரிடனà¯', + 'bs' => 'Bosnian', + 'ca' => 'காடலானà¯', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'காரà¯à®šà®¿à®¯à®©à¯', + 'cr' => 'Cree', + 'cs' => 'செகà¯', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'வெலà¯à®·à¯', + 'da' => 'டானிஷà¯', + 'de' => 'ஜெரà¯à®®à®©à¯', + 'dv' => 'Divehi', + 'dz' => 'பà¯à®Ÿà®¾à®©à®¿', + 'ee' => 'Ewe', + 'el' => 'கிரேகà¯à®•à®®à¯', + 'en' => 'ஆஙà¯à®•à®¿à®²à®®à¯', + 'eo' => 'எஸà¯à®ªà®°à¯‡à®©à¯à®Ÿà¯‹', + 'es' => 'ஸà¯à®ªà¯‡à®©à®¿à®·à¯', + 'et' => 'எஸà¯à®Ÿà¯‹à®©à®¿à®¯à®©à¯', + 'eu' => 'பஸà¯à®•à¯', + 'fa' => 'பரà¯à®¸à®¿à®¯à®©à¯', + 'ff' => 'Fulah', + 'fi' => 'பினà¯à®©à®¿à®·à¯', + 'fj' => 'பிஜி', + 'fo' => 'பைரோஸி', + 'fr' => 'பிரெஞà¯à®šà¯', + 'fy' => 'பிரிஷியனà¯', + 'ga' => 'à®à®°à®¿à®·à¯', + 'gd' => 'ஸà¯à®•à®¾à®Ÿà¯à®¸à¯ காலெகà¯', + 'gl' => 'கெலிஸியனà¯', + 'gn' => 'கà¯à®°à®¾à®©à®¿', + 'gu' => 'கà¯à®œà®°à®¾à®¤à¯à®¤à®¿', + 'gv' => 'Manx', + 'ha' => 'ஹொஸா', + 'he' => 'ஹà¯à®ªà¯à®°à¯', + 'hi' => 'இநà¯à®¤à®¿', + 'ho' => 'Hiri Motu', + 'hr' => 'கரோஷியனà¯', + 'ht' => 'Haitian', + 'hu' => 'ஹஙà¯à®•à¯‡à®°à®¿à®¯à®©à¯', + 'hy' => 'ஆரà¯à®®à¯‡à®©à®¿à®¯à®©à¯', + 'hz' => 'Herero', + 'ia' => 'இனà¯à®Ÿà®°à¯à®²à®¿à®™à¯à®•à¯à®µà®¾', + 'id' => 'இநà¯à®¤à¯‹à®©à¯‡à®·à®¿à®¯à®©à¯', + 'ie' => 'இனà¯à®Ÿà®°à¯à®²à®¿à®™à¯à®•à¯à®µà®¾', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'இனà¯à®ªà¯†à®•à¯', + 'io' => 'Ido', + 'is' => 'à®à®¸à¯à®²à¯†à®©à¯à®Ÿà®¿à®•à¯', + 'it' => 'இதà¯à®¤à®¾à®²à®¿à®¯à®©à¯', + 'iu' => 'இனà¯à®•à®¿à®Ÿà®Ÿà¯', + 'ja' => 'ஜபà¯à®ªà®¾à®©à¯€à®¸à¯', + 'jv' => 'ஜாவானீஸà¯', + 'ka' => 'கனà¯à®©à®Ÿà®®à¯', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'கசாகà¯', + 'kl' => 'கிரினà¯à®²à¯†à®©à¯à®Ÿà®¿à®•à¯', + 'km' => 'கமà¯à®ªà¯‹à®Ÿà®¿à®¯à®©à¯', + 'kn' => 'கனà¯à®©à®Ÿà®¾', + 'ko' => 'கொரியனà¯', + 'kr' => 'Kanuri', + 'ks' => 'காஷà¯à®®à®¿à®°à®¿', + 'ku' => 'கà¯à®°à¯à®¤à®¿à®·à¯', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'கிரà¯à®•à®¿à®·à¯', + 'la' => 'லாதினà¯', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'லிஙà¯à®•à®¾à®²à®¾', + 'lo' => 'லோதà¯à®¤à®¿à®¯à®©à¯', + 'lt' => 'லà¯à®¤à¯à®¤à¯‡à®©à®¿à®¯à®©à¯', + 'lu' => 'Luba-Katanga', + 'lv' => 'லேடà¯à®µà®¿à®¯à®©à¯ (லேடà¯à®Ÿà®¿à®·à¯)', + 'mg' => 'மலகெஸி', + 'mh' => 'Marshallese', + 'mi' => 'மோரி', + 'mk' => 'மெகà¯à®•à®Ÿà¯‹à®©à®¿à®¯à®©à¯', + 'ml' => 'மலையாளமà¯', + 'mn' => 'மஙà¯à®•à¯‹à®²à®¿à®¯à®©à¯', + 'mo' => 'மோலà¯à®Ÿà¯‡à®µà®¿à®¯à®©à¯', + 'mr' => 'மராதà¯à®¤à®¿', + 'ms' => 'மலாயà¯', + 'mt' => 'மாலà¯à®Ÿà®¿à®¸à¯', + 'my' => 'பரà¯à®®à®¿à®¸à¯', + 'na' => 'நாரூ', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'நேபà¯à®ªà®¾à®²à®¿', + 'ng' => 'Ndonga', + 'nl' => 'டசà¯à®šà¯', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'நாரà¯à®µà¯‡à®•à®¿à®¯à®©à¯', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ஆகிடியனà¯', + 'oj' => 'Ojibwa', + 'om' => 'ஒரோம (அபனà¯)', + 'or' => 'ஒரியா', + 'os' => 'Ossetic', + 'pa' => 'பஞà¯à®šà®¾à®ªà®¿', + 'pi' => 'Pali', + 'pl' => 'போலிஷà¯', + 'ps' => 'பேஷà¯à®Ÿà¯‹ (பà¯à®·à¯à®Ÿà¯‹)', + 'pt' => 'போரà¯à®¤à¯à®¤à¯à®•à¯€à®¸à¯', + 'qu' => 'கியà¯à®šà®¾', + 'rm' => 'ரைடà¯à®Ÿà¯‹-ரோமெனà¯à®¸à¯', + 'rn' => 'கிரà¯à®¨à¯à®¤à®¿', + 'ro' => 'ரோமேனியனà¯', + 'ru' => 'ரஷியனà¯', + 'rw' => 'கினà¯à®¯à®°à¯à®µà¯†à®©à¯à®Ÿà®¾', + 'sa' => 'சமஸà¯à®•à®¿à®°à¯à®¤à®®à¯', + 'sc' => 'Sardinian', + 'sd' => 'சிநà¯à®¤à®¿', + 'se' => 'Northern Sami', + 'sg' => 'செனà¯à®•à¯à®°à¯‹', + 'sh' => 'செரà¯à®ªà¯‹-கà¯à®°à¯‹à®·à®¿à®¯à®©à¯', + 'si' => 'சிஙà¯à®•à®³à®®à¯', + 'sk' => 'ஸà¯à®²à¯‹à®µà¯†à®•à¯', + 'sl' => 'ஸà¯à®²à¯‹à®µà®¿à®©à¯‡à®¯à®¿à®©à¯', + 'sm' => 'ஸெமோனà¯', + 'sn' => 'ஷோனா', + 'so' => 'சோமாலி', + 'sq' => 'அலà¯à®ªà¯†à®©à®¿à®¯à®©à¯', + 'sr' => 'சரà¯à®ªà®¿à®¯à®©à¯', + 'ss' => 'ஷிஸà¯à®µà®¾à®¤à®¿', + 'st' => 'ஷெஸà¯à®¸à¯‹à®¤à¯‹', + 'su' => 'சà¯à®Ÿà®¾à®©à¯€à®¸à¯', + 'sv' => 'ஷீவிடிஸà¯', + 'sw' => 'சà¯à®µà®¾à®¹à®¿à®²à®¿', + 'ta' => 'தமிழà¯', + 'te' => 'தெலà¯à®™à¯à®•à¯', + 'tg' => 'தாஜிகà¯', + 'th' => 'தாயà¯', + 'ti' => 'டிகà¯à®°à®¿à®©à¯à®¯à®¾', + 'tk' => 'டரà¯à®•à¯à®®à¯†à®©à¯', + 'tl' => 'டாகாலோகà¯', + 'tn' => 'ஸெடà¯à®¸à¯à®µà®¾à®©à®¾', + 'to' => 'டோஙà¯à®•à®¾', + 'tr' => 'டரà¯à®•à®¿à®·à¯', + 'ts' => 'ஸோஙà¯à®•à®¾', + 'tt' => 'டாடரà¯', + 'tw' => 'தà¯à®¤à®¿à®µà®¿', + 'ty' => 'Tahitian', + 'ug' => 'யà¯à®•à¯à®°à¯', + 'uk' => 'உகà¯à®°à¯‡à®©à®¿à®¯à®©à¯', + 'ur' => 'உரà¯à®¤à¯', + 'uz' => 'உஸà¯à®ªà¯†à®•à¯', + 've' => 'Venda', + 'vi' => 'வியடà¯à®¨à®¾à®®à®¿à®¸à¯', + 'vo' => 'ஒலபà¯à®•à¯', + 'wa' => 'Walloon', + 'wo' => 'ஒலோபà¯', + 'xh' => 'ஹோஷா', + 'yi' => 'ஈதà¯à®¤à®¿à®·', + 'yo' => 'யோரà¯à®ªà¯à®ªà®¾', + 'za' => 'ஜà¯à®µà®¾à®™à¯', + 'zh' => 'சீனமà¯', + 'zu' => 'ஜூலூ', +); +?> diff --git a/lib/Pear/I18Nv2/Language/te.php b/lib/Pear/I18Nv2/Language/te.php new file mode 100644 index 0000000..3efdc65 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/te.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'అరబికà±', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'ఙరà±à°®à°¨à±', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'ఆంగà±à°²à°‚', + 'eo' => 'Esperanto', + 'es' => 'à°¸à±à°ªà°¾à°¨à°¿à°·à±', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'à°«à±à°°à±†à°‚à°šà±', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'హిందీ', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ఇటాలియనౠభాష', + 'iu' => 'Inuktitut', + 'ja' => 'జపానౠభాష', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'పొరà±à°šà±à°—లౠభాష', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'à°°à°·à±à°¯à°¨à± భాష', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'తెలà±à°—à±', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'చైనా భాష', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/th.php b/lib/Pear/I18Nv2/Language/th.php new file mode 100644 index 0000000..152e862 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/th.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'อาฟา', + 'ab' => 'à¹à¸­à¸šà¸à¸²à¹€à¸‹à¸µà¸¢', + 'ae' => 'Avestan', + 'af' => 'à¹à¸­à¸Ÿà¸£à¸´à¸à¸±à¸™', + 'ak' => 'Akan', + 'am' => 'อัมฮาริค', + 'an' => 'Aragonese', + 'ar' => 'อาราบิค', + 'as' => 'อัสสัมมิส', + 'av' => 'Avaric', + 'ay' => 'ไอมารา', + 'az' => 'อาเซอร์ไบจานี', + 'ba' => 'บาสช์à¸à¸µà¸£à¹Œ', + 'be' => 'บายโลรัสเซีย', + 'bg' => 'บัลà¹à¸à¹€à¸£à¸µà¸¢', + 'bh' => 'บิฮารี', + 'bi' => 'บิสลามา', + 'bm' => 'Bambara', + 'bn' => 'เบนà¸à¸²à¸£à¸µ', + 'bo' => 'ทิเบต', + 'br' => 'บรีทัน', + 'bs' => 'Bosnian', + 'ca' => 'à¹à¸„ตาà¹à¸¥à¸™', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'คอร์ซิà¸à¸²', + 'cr' => 'Cree', + 'cs' => 'เช็ค', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'เวลส์', + 'da' => 'เดนมาร์à¸', + 'de' => 'เยอรมัน', + 'dv' => 'Divehi', + 'dz' => 'ภูà¸à¸²à¸™à¸µ', + 'ee' => 'Ewe', + 'el' => 'à¸à¸£à¸µà¸', + 'en' => 'อังà¸à¸¤à¸©', + 'eo' => 'เอสเปอรันโต', + 'es' => 'สเปน', + 'et' => 'เอสโตเนีย', + 'eu' => 'à¹à¸šà¸ªà¸à¹Œ', + 'fa' => 'เปอร์เซีย', + 'ff' => 'Fulah', + 'fi' => 'ฟิน', + 'fj' => 'ฟิจิ', + 'fo' => 'ฟาโรส', + 'fr' => 'à¸à¸£à¸±à¹ˆà¸‡à¹€à¸¨à¸ª', + 'fy' => 'ฟรีสà¹à¸¥à¸™à¸”์', + 'ga' => 'ไอริช', + 'gd' => 'สà¸à¹‡à¸­à¸•à¸ªà¹Œà¹€à¸à¸¥à¸´à¸„', + 'gl' => 'à¸à¸°à¸¥à¸µà¹€à¸Šà¸µà¸¢', + 'gn' => 'à¸à¸±à¸§à¸£à¸²à¸™à¸µ', + 'gu' => 'à¸à¸¹à¸ˆà¸²à¸£à¸²à¸•à¸´', + 'gv' => 'Manx', + 'ha' => 'โฮซา', + 'he' => 'ฮิบรู', + 'hi' => 'ฮินดี', + 'ho' => 'Hiri Motu', + 'hr' => 'โครเอเทีย', + 'ht' => 'Haitian', + 'hu' => 'ฮังà¸à¸²à¸£à¸µ', + 'hy' => 'อาร์มีเนีย', + 'hz' => 'Herero', + 'ia' => 'อินเตอร์ลิงà¸à¸§à¸²', + 'id' => 'อินโดนีเชีย', + 'ie' => 'อินเตอร์ลิงค์', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'ไอนูเปียà¸', + 'io' => 'Ido', + 'is' => 'ไอซ์à¹à¸¥à¸™à¸”์ดิค', + 'it' => 'อิตาลี', + 'iu' => 'ไอนุà¸à¸•à¸´à¸•à¸±à¸—', + 'ja' => 'à¸à¸µà¹ˆà¸›à¸¸à¹ˆà¸™', + 'jv' => 'ชวา', + 'ka' => 'จอร์เจียน', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'คาซัค', + 'kl' => 'à¸à¸£à¸µà¸™à¹à¸¥à¸™à¸”์ดิค', + 'km' => 'เขมร', + 'kn' => 'à¸à¸²à¸™à¸²à¸”า', + 'ko' => 'เà¸à¸²à¸«à¸¥à¸µ', + 'kr' => 'Kanuri', + 'ks' => 'คัชมีรี', + 'ku' => 'เคิด', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'เคอร์à¸à¸´à¸‹', + 'la' => 'ละติน', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'ลิงà¸à¸²à¸¥à¸²', + 'lo' => 'ลาว', + 'lt' => 'ลิธัวเนีย', + 'lu' => 'Luba-Katanga', + 'lv' => 'à¹à¸¥à¸•à¹€à¸§à¸µà¸¢ (เลททิสช์)', + 'mg' => 'มาลาà¸à¸²à¸‹à¸µ', + 'mh' => 'Marshallese', + 'mi' => 'เมารี', + 'mk' => 'à¹à¸¡à¸‹à¸µà¹‚ดเนีย', + 'ml' => 'มาลายาลัม', + 'mn' => 'มองโà¸à¸¥', + 'mo' => 'โมดาเวีย', + 'mr' => 'มาราที', + 'ms' => 'มลายู', + 'mt' => 'มอลตา', + 'my' => 'พม่า', + 'na' => 'นอรู', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'เนปาล', + 'ng' => 'Ndonga', + 'nl' => 'ฮอลันดา', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'นอร์เวย์', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'ออà¸à¸‹à¸´à¸—ัน', + 'oj' => 'Ojibwa', + 'om' => 'โอโรโม (อาฟาน)', + 'or' => 'โอริยา', + 'os' => 'Ossetic', + 'pa' => 'ปัà¸à¸ˆà¸²à¸›', + 'pi' => 'Pali', + 'pl' => 'โปà¹à¸¥à¸™à¸”์', + 'ps' => 'พาสช์โต (พุสช์โต)', + 'pt' => 'โปรตุเà¸à¸ª', + 'qu' => 'คิวชัว', + 'rm' => 'เรโต-โรà¹à¸¡à¸™à¸‹à¹Œ', + 'rn' => 'คิรันดี', + 'ro' => 'โรมัน', + 'ru' => 'รัสเซีย', + 'rw' => 'คินยาวันดา', + 'sa' => 'สันสà¸à¸¤à¸•', + 'sc' => 'Sardinian', + 'sd' => 'ซินดิ', + 'se' => 'Northern Sami', + 'sg' => 'สันโค', + 'sh' => 'เซอร์โบ-โครเอเทียน', + 'si' => 'สิงหล', + 'sk' => 'สโลวัค', + 'sl' => 'สโลเวเนีย', + 'sm' => 'ซามัว', + 'sn' => 'โซนา', + 'so' => 'โซมาลี', + 'sq' => 'à¹à¸­à¸¥à¹€à¸šà¹€à¸™à¸µà¸¢', + 'sr' => 'เซอร์เบีย', + 'ss' => 'ซีสวาติ', + 'st' => 'เซโสโท', + 'su' => 'ซันดานีส', + 'sv' => 'สวีเดน', + 'sw' => 'ซวาฮิรี', + 'ta' => 'ทมิฬ', + 'te' => 'ทิลูà¸à¸¹', + 'tg' => 'ทาจิค', + 'th' => 'ไทย', + 'ti' => 'ทิà¸à¸£à¸´à¸™à¸¢à¸²', + 'tk' => 'เติร์à¸à¹€à¸¡à¸™', + 'tl' => 'ตาà¸à¸²à¸¥à¹‡à¸­à¸', + 'tn' => 'เซตสวานา', + 'to' => 'ทองà¸à¹‰à¸²', + 'tr' => 'ตุรà¸à¸µ', + 'ts' => 'ซองà¸à¸²', + 'tt' => 'ตาด', + 'tw' => 'ทวี', + 'ty' => 'Tahitian', + 'ug' => 'อุยà¸à¸±à¸§', + 'uk' => 'ยูเครน', + 'ur' => 'อิรดู', + 'uz' => 'อุสเบค', + 've' => 'Venda', + 'vi' => 'เวียดนาม', + 'vo' => 'โวลาพุà¸', + 'wa' => 'Walloon', + 'wo' => 'วูลอฟ', + 'xh' => 'โซสา', + 'yi' => 'ยีดิช', + 'yo' => 'โยรูบา', + 'za' => 'จวง', + 'zh' => 'จีน', + 'zu' => 'ซูลู', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ti.php b/lib/Pear/I18Nv2/Language/ti.php new file mode 100644 index 0000000..0844253 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ti.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/tr.php b/lib/Pear/I18Nv2/Language/tr.php new file mode 100644 index 0000000..5ab16ab --- /dev/null +++ b/lib/Pear/I18Nv2/Language/tr.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abazca', + 'ae' => 'Avestan', + 'af' => 'Afrikaan Dili', + 'ak' => 'Akan', + 'am' => 'Amharik', + 'an' => 'Aragonese', + 'ar' => 'Arapça', + 'as' => 'Assamese', + 'av' => 'Avar Dili', + 'ay' => 'Aymara', + 'az' => 'Azerice', + 'ba' => 'BaÅŸkırt Dili', + 'be' => 'Beyaz Rusça', + 'bg' => 'Bulgarca', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengal Dili', + 'bo' => 'Tibetçe', + 'br' => 'Breton Dili', + 'bs' => 'Bosna Dili', + 'ca' => 'Katalan Dili', + 'ce' => 'Çeçence', + 'ch' => 'Chamorro', + 'co' => 'Korsika Dili', + 'cr' => 'Cree', + 'cs' => 'Çekçe', + 'cu' => 'Kilise Slavcası', + 'cv' => 'ÇuvaÅŸ', + 'cy' => 'Gal Dili', + 'da' => 'Danca', + 'de' => 'Almanca', + 'dv' => 'Divehi', + 'dz' => 'Bhutan Dili', + 'ee' => 'Ewe', + 'el' => 'Yunanca', + 'en' => 'Ä°ngilizce', + 'eo' => 'Esperanto', + 'es' => 'Ä°spanyolca', + 'et' => 'Estonya Dili', + 'eu' => 'Bask Dili', + 'fa' => 'Farsça', + 'ff' => 'Fulah', + 'fi' => 'Fince', + 'fj' => 'Fiji Dili', + 'fo' => 'Faroe Dili', + 'fr' => 'Fransızca', + 'fy' => 'Frizye Dili', + 'ga' => 'Ä°rlanda Dili', + 'gd' => 'Ä°skoç Gal Dili', + 'gl' => 'Galiçya Dili', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Ä°branice', + 'hi' => 'Hint Dili', + 'ho' => 'Hiri Motu', + 'hr' => 'Hırvatça', + 'ht' => 'Haiti Dili', + 'hu' => 'Macarca', + 'hy' => 'Ermenice', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Endonezya Dili', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiak', + 'io' => 'Ido', + 'is' => 'Ä°zlandaca', + 'it' => 'Ä°talyanca', + 'iu' => 'Inuktitut', + 'ja' => 'Japonca', + 'jv' => 'Java Dili', + 'ka' => 'Gürcüce', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazak Dili', + 'kl' => 'Grönland Dili', + 'km' => 'Kamboçya Dili', + 'kn' => 'Kannada', + 'ko' => 'Korece', + 'kr' => 'Kanuri', + 'ks' => 'KeÅŸmirce', + 'ku' => 'Kürtçe', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kırgızca', + 'la' => 'Latince', + 'lb' => 'Lüksemburg Dili', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Laos Dili', + 'lt' => 'Litvanya Dili', + 'lu' => 'Luba-Katanga', + 'lv' => 'Letonya Dili', + 'mg' => 'Malaga Dili', + 'mh' => 'Marshall Adaları Dili', + 'mi' => 'Maori', + 'mk' => 'Makedonca', + 'ml' => 'Malayalam', + 'mn' => 'MoÄŸol Dili', + 'mo' => 'Moldavya Dili', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Malta Dili', + 'my' => 'Birmanya Dili', + 'na' => 'Nauru', + 'nb' => 'Norveç Kitap Dili', + 'nd' => 'Kuzey Ndebele', + 'ne' => 'Nepal Dili', + 'ng' => 'Ndonga', + 'nl' => 'Hollanda Dili', + 'nn' => 'Norveççe Nynorsk', + 'no' => 'Norveççe', + 'nr' => 'Güney Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (1500 sonrası); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo (Afan)', + 'or' => 'Oriya', + 'os' => 'Oset', + 'pa' => 'Pencap Dili', + 'pi' => 'Pali', + 'pl' => 'Polonya Dili', + 'ps' => 'PeÅŸtun Dili', + 'pt' => 'Portekizce', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Roman Dili', + 'rn' => 'Kirundi', + 'ro' => 'Romence', + 'ru' => 'Rusça', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskritçe', + 'sc' => 'Sardunya Dili', + 'sd' => 'Sindhi', + 'se' => 'Kuzey Sami', + 'sg' => 'Sangho', + 'sh' => 'Sırp-Hırvat Dili', + 'si' => 'Sinhal Dili', + 'sk' => 'Slovakça', + 'sl' => 'Slovence', + 'sm' => 'Samoa Dili', + 'sn' => 'Shona', + 'so' => 'Somali Dili', + 'sq' => 'Arnavutça', + 'sr' => 'Sırpça', + 'ss' => 'Siswati', + 'st' => 'Sesotho', + 'su' => 'Sudan Dili', + 'sv' => 'Ä°sveççe', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tacik Dili', + 'th' => 'Tay Dili', + 'ti' => 'Tigrinya', + 'tk' => 'Türkmence', + 'tl' => 'Tagalog', + 'tn' => 'Setswana', + 'to' => 'Tonga (Tonga Adaları)', + 'tr' => 'Türkçe', + 'ts' => 'Tsonga', + 'tt' => 'Tatarca', + 'tw' => 'Twi', + 'ty' => 'Tahiti Dili', + 'ug' => 'Uygurca', + 'uk' => 'Ukraynaca', + 'ur' => 'Urduca', + 'uz' => 'Özbekçe', + 've' => 'Venda', + 'vi' => 'Vietnam Dili', + 'vo' => 'Volapuk', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'YiddiÅŸ', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Çince', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/tt.php b/lib/Pear/I18Nv2/Language/tt.php new file mode 100644 index 0000000..331de92 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/tt.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Татар', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/uk.php b/lib/Pear/I18Nv2/Language/uk.php new file mode 100644 index 0000000..be3b11e --- /dev/null +++ b/lib/Pear/I18Nv2/Language/uk.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'ÐфарÑька', + 'ab' => 'Ðбхазька', + 'ae' => 'Avestan', + 'af' => 'ÐфриканÑ', + 'ak' => 'Akan', + 'am' => 'Ðмхарік', + 'an' => 'Aragonese', + 'ar' => 'ÐрабÑька', + 'as' => 'ÐÑÑамÑька', + 'av' => 'Avaric', + 'ay' => 'Ðймара', + 'az' => 'ÐзербайджанÑька', + 'ba' => 'БашкирÑька', + 'be' => 'БілоруÑька', + 'bg' => 'БолгарÑька', + 'bh' => 'БіхарійÑька', + 'bi' => 'БіÑламійÑька', + 'bm' => 'Bambara', + 'bn' => 'БенгальÑька', + 'bo' => 'ТибетÑька', + 'br' => 'БретонÑька', + 'bs' => 'Bosnian', + 'ca' => 'КаталонÑька', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'КорÑиканÑька', + 'cr' => 'Cree', + 'cs' => 'ЧеÑька', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'ВаллійÑька', + 'da' => 'ДатÑька', + 'de' => 'Ðімецька', + 'dv' => 'Divehi', + 'dz' => 'Дзонг-ке', + 'ee' => 'Ewe', + 'el' => 'Грецька', + 'en' => 'ÐнглійÑька', + 'eo' => 'ЕÑперанто', + 'es' => 'ІÑпанÑька', + 'et' => 'ЕÑтонÑька', + 'eu' => 'БаÑків', + 'fa' => 'ПерÑька', + 'ff' => 'Fulah', + 'fi' => 'ФінÑька', + 'fj' => 'Фіджі', + 'fo' => 'ФарерÑька', + 'fr' => 'Французька', + 'fy' => 'Фризька', + 'ga' => 'ІрландÑька', + 'gd' => 'ГаельÑька', + 'gl' => 'ГаліÑійÑька', + 'gn' => 'Гуарані', + 'gu' => 'ГуÑраті', + 'gv' => 'Manx', + 'ha' => 'ХауÑа', + 'he' => 'Іврит', + 'hi' => 'Гінді', + 'ho' => 'Hiri Motu', + 'hr' => 'ХорватÑька', + 'ht' => 'Haitian', + 'hu' => 'УгорÑька', + 'hy' => 'ВірменÑька', + 'hz' => 'Herero', + 'ia' => 'Інтерлінгва', + 'id' => 'ІндонезійÑька', + 'ie' => 'Інтерлінгва', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Інупіак', + 'io' => 'Ido', + 'is' => 'ІÑландÑька', + 'it' => 'ІталійÑька', + 'iu' => 'Inuktitut', + 'ja' => 'ЯпонÑька', + 'jv' => 'ЯванÑька', + 'ka' => 'ГрузинÑька', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'КазахÑька', + 'kl' => 'КалаалліÑут', + 'km' => 'КхмерÑька', + 'kn' => 'Каннада', + 'ko' => 'КорейÑька', + 'kr' => 'Kanuri', + 'ks' => 'КашмірÑька', + 'ku' => 'КурдÑька', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Киргизька', + 'la' => 'ЛатинÑька', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Лінгала', + 'lo' => 'ЛаоÑька', + 'lt' => 'ЛитовÑька', + 'lu' => 'Luba-Katanga', + 'lv' => 'ЛатвійÑька', + 'mg' => 'МалагаÑійÑька', + 'mh' => 'Marshallese', + 'mi' => 'Маорі', + 'mk' => 'МакедонÑька', + 'ml' => 'МалайÑлам', + 'mn' => 'МонгольÑька', + 'mo' => 'МолдавÑька', + 'mr' => 'Маратхі', + 'ms' => 'МалайÑька', + 'mt' => 'МальтійÑька', + 'my' => 'БірманÑька', + 'na' => 'Ðауру', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'ÐепальÑька', + 'ng' => 'Ndonga', + 'nl' => 'ГолландÑька', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Ðорвезька', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Окитан', + 'oj' => 'Ojibwa', + 'om' => 'Оромо', + 'or' => 'ОріÑ', + 'os' => 'Ossetic', + 'pa' => 'Панджабі', + 'pi' => 'Pali', + 'pl' => 'ПольÑька', + 'ps' => 'Пашто', + 'pt' => 'ПортугальÑька', + 'qu' => 'Кечуа', + 'rm' => 'РетророманÑькі діалекти', + 'rn' => 'КірундійÑька', + 'ro' => 'РумунÑька', + 'ru' => 'РоÑійÑька', + 'rw' => 'Кінаруанда', + 'sa' => 'СанÑкрит', + 'sc' => 'Sardinian', + 'sd' => 'Сіндтхі', + 'se' => 'Northern Sami', + 'sg' => 'Сангро', + 'sh' => 'СербÑько-хорватÑька', + 'si' => 'СингальÑька', + 'sk' => 'Словацька', + 'sl' => 'СловенÑька', + 'sm' => 'СамоанÑька', + 'sn' => 'Шона', + 'so' => 'Сомалі', + 'sq' => 'ÐлбанÑька', + 'sr' => 'СербÑька', + 'ss' => 'СіÑваті', + 'st' => 'Сото, південний діалект', + 'su' => 'СуданÑька', + 'sv' => 'ШведÑька', + 'sw' => 'Суахілі', + 'ta' => 'ТамільÑька', + 'te' => 'Телугу', + 'tg' => 'Таджицька', + 'th' => 'ТайÑька', + 'ti' => 'Тигріні', + 'tk' => 'ТуркменÑька', + 'tl' => 'ТагальÑька', + 'tn' => 'СетÑванÑька', + 'to' => 'Тонга (оÑтрови Тонга)', + 'tr' => 'Турецька', + 'ts' => 'ТÑонго', + 'tt' => 'ТатарÑька', + 'tw' => 'Тві', + 'ty' => 'Tahitian', + 'ug' => 'УйгурÑька', + 'uk' => 'УкраїнÑька', + 'ur' => 'Урду', + 'uz' => 'Узбецька', + 've' => 'Venda', + 'vi' => 'ВʼєтнамÑька', + 'vo' => 'Волапак', + 'wa' => 'Walloon', + 'wo' => 'Волоф', + 'xh' => 'КхоÑа', + 'yi' => 'Ідиш', + 'yo' => 'Йоруба', + 'za' => 'Зуанг', + 'zh' => 'КитайÑька', + 'zu' => 'ЗулуÑька', +); +?> diff --git a/lib/Pear/I18Nv2/Language/ur.php b/lib/Pear/I18Nv2/Language/ur.php new file mode 100644 index 0000000..4cc2bcb --- /dev/null +++ b/lib/Pear/I18Nv2/Language/ur.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'اردو', + 'uz' => 'Uzbek', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/uz.php b/lib/Pear/I18Nv2/Language/uz.php new file mode 100644 index 0000000..3332b99 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/uz.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Ðрабча', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Belarusian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Catalan', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Czech', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'Олмонча', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Greek', + 'en' => 'Инглизча', + 'eo' => 'Esperanto', + 'es' => 'ИÑпанча', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'ff' => 'Fulah', + 'fi' => 'Finnish', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Французча', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Ҳиндча', + 'ho' => 'Hiri Motu', + 'hr' => 'Croatian', + 'ht' => 'Haitian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'hz' => 'Herero', + 'ia' => 'Interlingua', + 'id' => 'Indonesian', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Icelandic', + 'it' => 'ИталÑнча', + 'iu' => 'Inuktitut', + 'ja' => 'Японча', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Khmer', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Lao', + 'lt' => 'Lithuanian', + 'lu' => 'Luba-Katanga', + 'lv' => 'Latvian', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Nepali', + 'ng' => 'Ndonga', + 'nl' => 'Dutch', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Norwegian', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Polish', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Португалча', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Romanian', + 'ru' => 'РуÑча', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Ўзбек', + 've' => 'Venda', + 'vi' => 'Vietnamese', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Хитойча', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/vi.php b/lib/Pear/I18Nv2/Language/vi.php new file mode 100644 index 0000000..05aa461 --- /dev/null +++ b/lib/Pear/I18Nv2/Language/vi.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => 'Afar', + 'ab' => 'Abkhazian', + 'ae' => 'Avestan', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'Amharic', + 'an' => 'Aragonese', + 'ar' => 'Tiếng A-rập', + 'as' => 'Assamese', + 'av' => 'Avaric', + 'ay' => 'Aymara', + 'az' => 'Tiếng Ai-déc-bai-gian', + 'ba' => 'Bashkir', + 'be' => 'Tiếng Bê-la-rút', + 'bg' => 'Tiếng Bun-ga-ri', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bm' => 'Bambara', + 'bn' => 'Bengali', + 'bo' => 'Tiếng Tây Tạng', + 'br' => 'Breton', + 'bs' => 'Bosnian', + 'ca' => 'Tiếng Ca-ta-lăng', + 'ce' => 'Chechen', + 'ch' => 'Chamorro', + 'co' => 'Corsican', + 'cr' => 'Cree', + 'cs' => 'Tiếng Séc', + 'cu' => 'Church Slavic', + 'cv' => 'Chuvash', + 'cy' => 'Welsh', + 'da' => 'Tiếng Äan Mạch', + 'de' => 'Tiếng Äức', + 'dv' => 'Divehi', + 'dz' => 'Dzongkha', + 'ee' => 'Ewe', + 'el' => 'Tiếng Hy Lạp', + 'en' => 'Tiếng Anh', + 'eo' => 'Tiếng Quốc Tế Ngữ', + 'es' => 'Tiếng Tây Ban Nha', + 'et' => 'Tiếng E-xtô-ni-a', + 'eu' => 'Basque', + 'fa' => 'Tiếng Ba TÆ°', + 'ff' => 'Fulah', + 'fi' => 'Tiếng Phần Lan', + 'fj' => 'Fijian', + 'fo' => 'Faroese', + 'fr' => 'Tiếng Pháp', + 'fy' => 'Frisian', + 'ga' => 'Tiếng Ai-len', + 'gd' => 'Scottish Gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'gv' => 'Manx', + 'ha' => 'Hausa', + 'he' => 'Tiếng Hê-brÆ¡', + 'hi' => 'Tiếng Hin-Ä‘i', + 'ho' => 'Hiri Motu', + 'hr' => 'Tiếng Crô-a-ti-a', + 'ht' => 'Haitian', + 'hu' => 'Tiếng Hung-ga-ri', + 'hy' => 'Tiếng Ãc-mê-ni', + 'hz' => 'Herero', + 'ia' => 'Tiếng Khoa Há»c Quốc Tế', + 'id' => 'Tiếng In-đô-nê-xia', + 'ie' => 'Interlingue', + 'ig' => 'Igbo', + 'ii' => 'Sichuan Yi', + 'ik' => 'Inupiaq', + 'io' => 'Ido', + 'is' => 'Tiếng Ai-xÆ¡-len', + 'it' => 'Tiếng Ã', + 'iu' => 'Inuktitut', + 'ja' => 'Tiếng Nhật', + 'jv' => 'Tiếng Gia-va', + 'ka' => 'Georgian', + 'kg' => 'Kongo', + 'ki' => 'Kikuyu', + 'kj' => 'Kuanyama', + 'kk' => 'Kazakh', + 'kl' => 'Kalaallisut', + 'km' => 'Tiếng Campuchia', + 'kn' => 'Tiếng Kan-na-Ä‘a', + 'ko' => 'Tiếng Hàn Quốc', + 'kr' => 'Kanuri', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'kv' => 'Komi', + 'kw' => 'Cornish', + 'ky' => 'Kirghiz', + 'la' => 'Tiếng La-tinh', + 'lb' => 'Luxembourgish', + 'lg' => 'Ganda', + 'li' => 'Limburgish', + 'ln' => 'Lingala', + 'lo' => 'Tiếng Lào', + 'lt' => 'Tiếng Lít-va', + 'lu' => 'Luba-Katanga', + 'lv' => 'Tiếng Lát-vi-a', + 'mg' => 'Malagasy', + 'mh' => 'Marshallese', + 'mi' => 'Maori', + 'mk' => 'Tiếng Ma-xê-đô-ni-a', + 'ml' => 'Malayalam', + 'mn' => 'Tiếng Mông Cổ', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Tiếng Ma-lay-xi-a', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'nb' => 'Norwegian BokmÃ¥l', + 'nd' => 'North Ndebele', + 'ne' => 'Tiếng Nê-pan', + 'ng' => 'Ndonga', + 'nl' => 'Tiếng Hà Lan', + 'nn' => 'Norwegian Nynorsk', + 'no' => 'Tiếng Na Uy', + 'nr' => 'South Ndebele', + 'nv' => 'Navajo', + 'ny' => 'Nyanja; Chichewa; Chewa', + 'oc' => 'Occitan (post 1500); Provençal', + 'oj' => 'Ojibwa', + 'om' => 'Oromo', + 'or' => 'Oriya', + 'os' => 'Ossetic', + 'pa' => 'Punjabi', + 'pi' => 'Pali', + 'pl' => 'Tiếng Ba Lan', + 'ps' => 'Pashto (Pushto)', + 'pt' => 'Tiếng Bồ Äào Nha', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-Romance', + 'rn' => 'Rundi', + 'ro' => 'Tiếng Ru-ma-ni', + 'ru' => 'Tiếng Nga', + 'rw' => 'Kinyarwanda', + 'sa' => 'Tiếng Phạn', + 'sc' => 'Sardinian', + 'sd' => 'Sindhi', + 'se' => 'Northern Sami', + 'sg' => 'Sango', + 'sh' => 'Serbo-Croatian', + 'si' => 'Sinhalese', + 'sk' => 'Tiếng Xlô-vác', + 'sl' => 'Tiếng Xlô-ven', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Tiếng Xô-ma-li', + 'sq' => 'Tiếng An-ba-ni', + 'sr' => 'Tiếng Séc-bi', + 'ss' => 'Swati', + 'st' => 'Southern Sotho', + 'su' => 'Sundanese', + 'sv' => 'Tiếng Thụy Äiển', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Tiếng Thái', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Tswana', + 'to' => 'Tonga (Tonga Islands)', + 'tr' => 'Tiếng Thổ NhÄ© Kỳ', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ty' => 'Tahitian', + 'ug' => 'Uighur', + 'uk' => 'Tiếng U-crai-na', + 'ur' => 'Urdu', + 'uz' => 'Tiếng U-dÆ¡-bếch', + 've' => 'Venda', + 'vi' => 'Tiếng Việt', + 'vo' => 'Volapük', + 'wa' => 'Walloon', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Tiếng Y-Ä‘it', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Tiếng Trung Quốc', + 'zu' => 'Zulu', +); +?> diff --git a/lib/Pear/I18Nv2/Language/zh.php b/lib/Pear/I18Nv2/Language/zh.php new file mode 100644 index 0000000..c51eabb --- /dev/null +++ b/lib/Pear/I18Nv2/Language/zh.php @@ -0,0 +1,193 @@ +codes = array( + 'aa' => '阿法文', + 'ab' => '阿布哈西亚文', + 'ae' => '阿维斯塔文', + 'af' => 'å—éžè·å…°æ–‡', + 'ak' => '阿肯文', + 'am' => '阿姆哈拉文', + 'an' => 'Aragonese', + 'ar' => '阿拉伯文', + 'as' => '阿è¨å§†æ–‡', + 'av' => '阿瓦尔文', + 'ay' => '艾马拉文', + 'az' => '阿塞拜疆文', + 'ba' => '巴什客尔文', + 'be' => '白俄罗斯文', + 'bg' => 'ä¿åŠ åˆ©äºšæ–‡', + 'bh' => '比哈尔文', + 'bi' => '比斯拉马文', + 'bm' => 'ç­å·´æ‹‰æ–‡', + 'bn' => '孟加拉文', + 'bo' => '西è—æ–‡', + 'br' => '布里多尼文', + 'bs' => '波斯尼亚文', + 'ca' => '加泰罗尼亚文', + 'ce' => '车臣文', + 'ch' => '查莫罗文', + 'co' => '科西嘉文', + 'cr' => '克里æ—æ–‡', + 'cs' => 'æ·å…‹æ–‡', + 'cu' => '宗教斯拉夫文', + 'cv' => '楚瓦什文', + 'cy' => 'å¨å°”士文', + 'da' => '丹麦文', + 'de' => 'å¾·æ–‡', + 'dv' => '迪维希文', + 'dz' => 'ä¸ä¸¹æ–‡', + 'ee' => '幽文', + 'el' => '希腊文', + 'en' => '英文', + 'eo' => '世界文', + 'es' => '西ç­ç‰™æ–‡', + 'et' => '爱沙尼亚文', + 'eu' => '巴斯克文', + 'fa' => '波斯文', + 'ff' => '夫拉文', + 'fi' => '芬兰文', + 'fj' => 'æ–济文', + 'fo' => '法罗文', + 'fr' => '法文', + 'fy' => '弗里斯兰文', + 'ga' => '爱尔兰文', + 'gd' => 'è‹æ ¼å…°- 盖尔文', + 'gl' => '加利西亚文', + 'gn' => '瓜拉尼文', + 'gu' => 'å¤åŠ æ‹‰ææ–‡', + 'gv' => '马æ©å²›æ–‡', + 'ha' => '豪撒文', + 'he' => '希伯æ¥æ–‡', + 'hi' => 'å°åœ°æ–‡', + 'ho' => '新里木托文', + 'hr' => '克罗地亚文', + 'ht' => 'Haitian', + 'hu' => '匈牙利文', + 'hy' => '亚美尼亚文', + 'hz' => '赫雷罗文', + 'ia' => '拉ä¸å›½é™…æ–‡', + 'id' => 'å°åº¦å°¼è¥¿äºšæ–‡', + 'ie' => '拉ä¸å›½é™…æ–‡', + 'ig' => '伊格åšæ–‡', + 'ii' => 'å››å·è¯', + 'ik' => 'ä¾å¥´çš®ç»´å…‹æ–‡', + 'io' => '爱德莪文(人工语言)', + 'is' => '冰岛文', + 'it' => 'æ„大利文', + 'iu' => '爱斯基摩文', + 'ja' => '日文', + 'jv' => '爪哇文', + 'ka' => 'æ ¼é²å‰äºšæ–‡', + 'kg' => '刚果文', + 'ki' => 'å‰åº“尤文', + 'kj' => 'å…³çŠçŽ›æ–‡', + 'kk' => '哈è¨å…‹æ–‡', + 'kl' => '格陵兰文', + 'km' => '柬埔寨文', + 'kn' => '埃纳德文', + 'ko' => '韩文', + 'kr' => 'å¡åŠªé‡Œæ–‡', + 'ks' => '克什米尔文', + 'ku' => '库尔德文', + 'kv' => '科米文', + 'kw' => '凯尔特文', + 'ky' => 'å‰å°”å‰æ–¯æ–‡', + 'la' => '拉ä¸æ–‡', + 'lb' => 'å¢æ£®å ¡æ–‡', + 'lg' => 'å¢å¹²è¾¾æ–‡', + 'li' => '淋布尔å‰æ–‡', + 'ln' => '林加拉文', + 'lo' => 'è€æŒæ–‡', + 'lt' => '立陶宛文', + 'lu' => 'é²å·´åŠ ä¸¹åŠ æ–‡', + 'lv' => '拉脫維亞文', + 'mg' => '马尔加什文', + 'mh' => '马ç»å°”æ–‡', + 'mi' => '毛利文', + 'mk' => '马其顿文', + 'ml' => '马æ¥äºšæ‹‰å§†æ–‡', + 'mn' => 'è’™å¤æ–‡', + 'mo' => '摩尔多瓦文', + 'mr' => '马拉地文', + 'ms' => '马æ¥æ–‡', + 'mt' => '马耳他文', + 'my' => '缅甸文', + 'na' => 'ç‘™é²æ–‡', + 'nb' => '挪å¨åšå…‹é©¬å°”æ–‡', + 'nd' => '北æ©å¾·è´å‹’æ–‡', + 'ne' => '尼泊尔文', + 'ng' => 'æ©ä¸œåŠ æ–‡', + 'nl' => 'è·å…°æ–‡', + 'nn' => '挪å¨å°¼è¯ºæ–¯å…‹æ–‡', + 'no' => '挪å¨æ–‡', + 'nr' => 'å—部æ©å¾·è´å‹’æ–‡', + 'nv' => '纳瓦éœæ–‡', + 'ny' => '尼昂加文;切瓦文;切瓦文', + 'oc' => '奥西å¦æ–‡', + 'oj' => '奥季布瓦文', + 'om' => '阿曼文', + 'or' => '欧里亚文', + 'os' => '奥塞ææ–‡', + 'pa' => 'æ—é®æ™®æ–‡', + 'pi' => '帕利文', + 'pl' => '波兰文', + 'ps' => '普什图文', + 'pt' => 'è‘¡è„牙文', + 'qu' => '盖丘亚文', + 'rm' => '里托罗曼斯文', + 'rn' => '基隆迪文', + 'ro' => '罗马尼亚文', + 'ru' => 'ä¿„æ–‡', + 'rw' => 'å¢æ—ºè¾¾æ–‡', + 'sa' => '梵文', + 'sc' => 'è¨ä¸æ–‡', + 'sd' => 'è‹ä¸¹æ–‡', + 'se' => '北è¨è¿·æ–‡', + 'sg' => '桑戈文', + 'sh' => '塞波尼斯-克罗地亚文', + 'si' => '僧伽罗文', + 'sk' => '斯洛ä¼å…‹æ–‡', + 'sl' => '斯洛文尼亚文', + 'sm' => 'è¨æ‘©äºšæ–‡', + 'sn' => '塞内加尔文', + 'so' => '索马里文', + 'sq' => '阿尔巴尼亚文', + 'sr' => '塞尔维亚文', + 'ss' => '辛辛那ææ–‡', + 'st' => '塞索托文', + 'su' => 'è‹ä¸¹æ–‡', + 'sv' => '瑞典文', + 'sw' => '斯瓦希里文', + 'ta' => '泰米尔文', + 'te' => 'æ³°å¢å›ºæ–‡', + 'tg' => 'å¡”å‰å…‹æ–‡', + 'th' => 'æ³°æ–‡', + 'ti' => 'æ格里尼亚文', + 'tk' => '土库曼文', + 'tl' => '塔加路æ—æ–‡', + 'tn' => 'çªå°¼æ–¯æ–‡', + 'to' => '汤加文', + 'tr' => '土耳其文', + 'ts' => '特æ¾åŠ æ–‡', + 'tt' => 'éž‘é¼æ–‡', + 'tw' => 'å°æ¹¾æ–‡', + 'ty' => '塔西ææ–‡', + 'ug' => 'ç»´å¾å°”æ–‡', + 'uk' => '乌克兰文', + 'ur' => '乌尔都文', + 'uz' => '乌兹别克文', + 've' => '文达文', + 'vi' => '越å—æ–‡', + 'vo' => '沃拉普克文', + 'wa' => 'è¯éš†æ–‡', + 'wo' => '沃尔夫文', + 'xh' => 'ç­å›¾æ–‡', + 'yi' => 'ä¾åœ°æ–‡', + 'yo' => '约é²å·´æ–‡', + 'za' => 'è—æ–‡', + 'zh' => '中文', + 'zu' => '祖é²æ–‡', +); +?> diff --git a/lib/Pear/I18Nv2/Negotiator.php b/lib/Pear/I18Nv2/Negotiator.php new file mode 100644 index 0000000..98b1cf5 --- /dev/null +++ b/lib/Pear/I18Nv2/Negotiator.php @@ -0,0 +1,377 @@ + | +// | Wolfram Kriesing | +// | Michael Wallner | +// +----------------------------------------------------------------------+ +// +// $Id: Negotiator.php,v 1.11 2005/11/28 15:33:22 mike Exp $ + +/** + * I18Nv2::Negotiator + * + * @package I18Nv2 + * @category Internationalization + */ + +/** + * I18Nv2_Negotiator + * + * @author Naoki Shima + * @author Wolfram Kriesing + * @author Michael Wallner + * @version $Revision: 1.11 $ + * @access public + * @package I18Nv2 + */ +class I18Nv2_Negotiator +{ + /** + * I18Nv2_Language + * + * @var object + * @access public + */ + var $I18NLang = null; + + /** + * I18Nv2_Country + * + * @var object + * @access public + */ + var $I18NCountry = null; + + /** + * Save default country code. + * + * @var string + * @access private + */ + var $_defaultCountry; + + /** + * Save default language code. + * + * @var string + * @access private + */ + var $_defaultLanguage; + + /** + * Save default encoding code. + * + * @var string + * @access private + */ + var $_defaultEncoding; + + /** + * HTTP_ACCEPT_CHARSET + * + * @var array + * @access private + */ + var $_acceptEncoding = array(); + + /** + * HTTP_ACCEPT_LANGUAGE + * + * @var array + * @access private + */ + var $_acceptLanguage = array(); + + /** + * Language variations + * + * @var array + * @access private + */ + var $_langVariation = array(); + + /** + * Countries + * + * @var array + * @access private + */ + var $_country = array(); + + /** + * Constructor + * + * Find language code, country code, encoding code, and dialect or variant + * of Locale setting in HTTP request headers. + * + * @access public + * @param string $defaultLanguage Default Language + * @param string $defaultEncoding Default Encoding + * @param string $defaultCountry Default Country + */ + function I18Nv2_Negotiator($defaultLanguage = 'en', $defaultEncoding = 'iso-8859-1', $defaultCountry = '') + { + $this->__construct($defaultLanguage, $defaultEncoding, $defaultCountry); + } + + /** + * ZE2 Constructor + * @ignore + */ + function __construct($defaultLanguage = 'en', $defaultEncoding = 'iso-8859-1', $defaultCountry = '') + { + $this->_defaultCountry = $defaultCountry; + $this->_defaultLanguage = $defaultLanguage; + $this->_defaultEncoding = $defaultEncoding; + + $this->_negotiateLanguage(); + $this->_negotiateEncoding(); + } + + /** + * Negotiate Language + * + * @access private + * @return void + */ + function _negotiateLanguage() + { + if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + return; + } + foreach(explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) { + // Cut off any q-value that might come after a semi-colon + if ($pos = strpos($lang, ';')) { + $lang = trim(substr($lang, 0, $pos)); + } + if (strstr($lang, '-')) { + list($pri, $sub) = explode('-', $lang); + if ($pri == 'i') { + /** + * Language not listed in ISO 639 that are not variants + * of any listed language, which can be registerd with the + * i-prefix, such as i-cherokee + */ + $lang = $sub; + } else { + $lang = $pri; + $this->singleI18NCountry(); + if ($this->I18NCountry->isValidCode($sub)) { + $this->_country[$lang][] = strToUpper($sub); + } else { + $this->_langVariation[$lang][] = $sub; + } + } + } + $this->_acceptLanguage[] = $lang; + } + } + + /** + * Negotiate Encoding + * + * @access private + * @return void + */ + function _negotiateEncoding() + { + if (!isset($_SERVER['HTTP_ACCEPT_CHARSET'])) { + return; + } + foreach (explode(',', $_SERVER['HTTP_ACCEPT_CHARSET']) as $encoding) { + if (!empty($encoding)) { + $this->_acceptEncoding[] = preg_replace('/;.*/', '', $encoding); + } + } + } + + /** + * Find Country Match + * + * @access public + * @return array + * @param string $lang + * @param array $countries + */ + function getCountryMatch($lang, $countries = null) + { + return $this->_getMatch( + $countries, + @$this->_country[$lang], + $this->_defaultCountry + ); + } + + /** + * Return variant info for passed parameter. + * + * @access public + * @return string + * @param string $lang + */ + function getVariantInfo($lang) + { + return isset($this->_langVariation[$lang]) ? $this->_langVariation[$lang] : null; + } + + /** + * Find Encoding match + * + * @deprecated + * @access public + * @return string + * @param array $encodings + */ + function getCharsetMatch($encodings = null) + { + return $this->_getMatch( + $encodings, + $this->_acceptEncoding, + $this->_defaultEncoding + ); + } + + /** + * Find Encoding match + * + * @access public + * @return string + * @param array $encodings + */ + function getEncodingMatch($encodings = null) + { + return $this->_getMatch( + $encodings, + $this->_acceptEncoding, + $this->_defaultEncoding + ); + } + + /** + * Find Language match + * + * @access public + * @return string + * @param array $langs + */ + function getLanguageMatch($langs = null) + { + return $this->_getMatch( + $langs, + $this->_acceptLanguage, + $this->_defaultLanguage + ); + } + + /** + * Find locale match + * + * @access public + * @return string + * @param array $langs + * @param array $countries + */ + function getLocaleMatch($langs = null, $countries = null) + { + $lang = $this->_getMatch($langs, $this->_acceptLanguage, $this->_defaultLanguage); + $ctry = $this->_getMatch($countries, @$this->_country[$lang], $this->_defaultCountry); + return $lang . ($ctry ? '_' . $ctry : ''); + } + + /** + * Return first matched value from first and second parameter. + * If there is no match found, then return third parameter. + * + * @access private + * @return string + * @param array $needle + * @param array $haystack + * @param string $default + */ + function _getMatch($needle, $haystack, $default = '') + { + if (!$haystack) { + return $default; + } + if (!$needle) { + return current($haystack); + } + if ($result = current($a = array_intersect($haystack, $needle))) { + return $result; + } + return $default; + } + + /** + * Find Country name for country code passed + * + * @access private + * @return void + * @param string $code country code + */ + function getCountryName($code) + { + $this->singleI18NCountry(); + return $this->I18NCountry->getName($code); + } + + /** + * Find Country name for country code passed + * + * @access private + * @return void + * @param string $code language code + */ + function getLanguageName($code) + { + $this->singleI18NLanguage(); + return $this->I18NLang->getName($code); + } + + /** + * Create the Language helper object + * + * @access public + * @return object + */ + function &singleI18NLanguage() + { + if (!isset($this->I18NLang)) { + include_once 'I18Nv2/Language.php'; + $this->I18NLang = &new I18Nv2_Language( + $this->_defaultLanguage, + $this->_defaultEncoding + ); + } + return $this->I18NLang; + } + + /** + * Create the Country helper object + * + * @access public + * @return object + */ + function &singleI18NCountry() + { + if (!isset($this->I18NCountry)) { + include_once 'I18Nv2/Country.php'; + $this->I18NCountry = &new I18Nv2_Country( + $this->_defaultLanguage, + $this->_defaultEncoding + ); + } + return $this->I18NCountry; + } +} +?> diff --git a/lib/Pear/Image/GraphViz.php b/lib/Pear/Image/GraphViz.php new file mode 100644 index 0000000..cb2264a --- /dev/null +++ b/lib/Pear/Image/GraphViz.php @@ -0,0 +1,877 @@ + and + * Sebastian Bergmann . All rights reserved. + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category Image + * @package GraphViz + * @author Dr. Volker Göbbels + * @author Sebastian Bergmann + * @author Karsten Dambekalns + * @author Michael Lively Jr. + * @author Philippe Jausions + * @copyright 2001-2007 Dr. Volker Göbbels and Sebastian Bergmann + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: GraphViz.php,v 1.29 2008/02/05 19:39:35 jausions Exp $ + * @link http://pear.php.net/package/Image_GraphViz + * @link http://www.graphviz.org/ + * @since File available since Release 0.1.0 + */ + +/** + * Required PEAR classes + */ +require_once 'System.php'; + +/** + * Interface to AT&T's GraphViz tools. + * + * The GraphViz class allows for the creation of and to work with directed + * and undirected graphs and their visualization with AT&T's GraphViz tools. + * + * + * addNode( + * 'Node1', + * array( + * 'URL' => 'http://link1', + * 'label' => 'This is a label', + * 'shape' => 'box' + * ) + * ); + * + * $graph->addNode( + * 'Node2', + * array( + * 'URL' => 'http://link2', + * 'fontsize' => '14' + * ) + * ); + * + * $graph->addNode( + * 'Node3', + * array( + * 'URL' => 'http://link3', + * 'fontsize' => '20' + * ) + * ); + * + * $graph->addEdge( + * array( + * 'Node1' => 'Node2' + * ), + * array( + * 'label' => 'Edge Label' + * ) + * ); + * + * $graph->addEdge( + * array( + * 'Node1' => 'Node2' + * ), + * array( + * 'color' => 'red' + * ) + * ); + * + * $graph->image(); + * ?> + * + * + * @category Image + * @package GraphViz + * @author Sebastian Bergmann + * @author Dr. Volker Göbbels + * @author Karsten Dambekalns + * @author Michael Lively Jr. + * @author Philippe Jausions + * @copyright 2001-2007 Dr. Volker Göbbels and Sebastian Bergmann + * @license http://www.php.net/license/3_0.txt The PHP License, Version 3.0 + * @version Release: 1.3.0RC3 + * @link http://pear.php.net/package/Image_GraphViz + * @link http://www.graphviz.org/ + * @since Class available since Release 0.1 + */ +class Image_GraphViz +{ + /** + * Base path to GraphViz commands + * + * @var string + */ + var $binPath = ''; + + /** + * Path to GraphViz/dot command + * + * @var string + */ + var $dotCommand = 'dot'; + + /** + * Path to GraphViz/neato command + * + * @var string + */ + var $neatoCommand = 'neato'; + + /** + * Representation of the graph + * + * @var array + */ + var $graph = array('edgesFrom' => array(), + 'nodes' => array(), + 'attributes' => array(), + 'directed' => true, + 'clusters' => array(), + 'name' => 'G', + 'strict' => true, + ); + + /** + * Whether to return PEAR_Error instance on failures instead of FALSE + * + * @var boolean + * @access protected + */ + var $_returnFalseOnError = true; + + /** + * Constructor. + * + * Setting the name of the Graph is useful for including multiple image + * maps on one page. If not set, the graph will be named 'G'. + * + * @param boolean $directed Directed (TRUE) or undirected (FALSE) graph. + * Note: You MUST pass a boolean, and not just + * an expression that evaluates to TRUE or + * FALSE (i.e. NULL, empty string, 0 will NOT + * work) + * @param array $attributes Attributes of the graph + * @param string $name Name of the Graph + * @param boolean $strict Whether to collapse multiple edges between + * same nodes + * @param boolean $returnError Set to TRUE to return PEAR_Error instances + * on failures instead of FALSE + * + * @access public + */ + function Image_GraphViz($directed = true, $attributes = array(), + $name = 'G', $strict = true, $returnError = false) + { + $this->setDirected($directed); + $this->setAttributes($attributes); + $this->graph['name'] = $name; + $this->graph['strict'] = (boolean)$strict; + + $this->_returnFalseOnError = !$returnError; + } + + /** + * Outputs image of the graph in a given format + * + * This methods send HTTP headers + * + * @param string $format Format of the output image. This may be one + * of the formats supported by GraphViz. + * @param string $command "dot" or "neato" + * + * @return boolean TRUE on success, FALSE or PEAR_Error otherwise + * @access public + */ + function image($format = 'svg', $command = null) + { + $file = $this->saveParsedGraph(); + if (!$file || PEAR::isError($file)) { + return $file; + } + + $outputfile = $file . '.' . $format; + + $rendered = $this->renderDotFile($file, $outputfile, $format, + $command); + if ($rendered !== true) { + return $rendered; + } + + $sendContentLengthHeader = true; + + switch (strtolower($format)) { + case 'gif': + case 'png': + case 'bmp': + case 'jpeg': + case 'tiff': + header('Content-Type: image/' . $format); + break; + + case 'tif': + header('Content-Type: image/tiff'); + break; + + case 'jpg': + header('Content-Type: image/jpeg'); + break; + + case 'ico': + header('Content-Type: image/x-icon'); + break; + + case 'wbmp': + header('Content-Type: image/vnd.wap.wbmp'); + break; + + case 'pdf': + header('Content-Type: application/pdf'); + break; + + case 'mif': + header('Content-Type: application/vnd.mif'); + break; + + case 'vrml': + header('Content-Type: application/x-vrml'); + break; + + case 'svg': + header('Content-Type: image/svg+xml'); + break; + + case 'plain': + case 'plain-ext': + header('Content-Type: text/plain'); + break; + + default: + header('Content-Type: application/octet-stream'); + $sendContentLengthHeader = false; + } + + if ($sendContentLengthHeader) { + header('Content-Length: ' . filesize($outputfile)); + } + + $return = true; + if (readfile($outputfile) === false) { + $return = false; + } + @unlink($outputfile); + + return $return; + } + + /** + * Returns image (data) of the graph in a given format. + * + * @param string $format Format of the output image. This may be one + * of the formats supported by GraphViz. + * @param string $command "dot" or "neato" + * + * @return string The image (data) created by GraphViz, FALSE or PEAR_Error + * on error + * @access public + * @since Method available since Release 1.1.0 + */ + function fetch($format = 'svg', $command = null) + { + $file = $this->saveParsedGraph(); + if (!$file || PEAR::isError($file)) { + return $file; + } + + $outputfile = $file . '.' . $format; + + $rendered = $this->renderDotFile($file, $outputfile, $format, + $command); + if ($rendered !== true) { + return $rendered; + } + + @unlink($file); + + $fp = fopen($outputfile, 'rb'); + + if (!$fp) { + if ($this->_returnFalseOnError) { + return false; + } + $error = PEAR::raiseError('Could not read rendered file'); + return $error; + } + + $data = fread($fp, filesize($outputfile)); + fclose($fp); + @unlink($outputfile); + + return $data; + } + + /** + * Renders a given dot file into a given format. + * + * @param string $dotfile The absolute path of the dot file to use. + * @param string $outputfile The absolute path of the file to save to. + * @param string $format Format of the output image. This may be one + * of the formats supported by GraphViz. + * @param string $command "dot" or "neato" + * + * @return boolean TRUE if the file was saved, FALSE or PEAR_Error + * otherwise. + * @access public + */ + function renderDotFile($dotfile, $outputfile, $format = 'svg', + $command = null) + { + if (!file_exists($dotfile)) { + if ($this->_returnFalseOnError) { + return false; + } + $error = PEAR::raiseError('Could not find dot file'); + return $error; + } + + $oldmtime = file_exists($outputfile) ? filemtime($outputfile) : 0; + + switch ($command) { + case 'dot': + case 'neato': + break; + default: + $command = $this->graph['directed'] ? 'dot' : 'neato'; + } + $command_orig = $command; + + $command = $this->binPath.(($command == 'dot') ? $this->dotCommand + : $this->neatoCommand); + + $command .= ' -T'.escapeshellarg($format) + .' -o'.escapeshellarg($outputfile) + .' '.escapeshellarg($dotfile) + .' 2>&1'; + exec($command, $msg, $return_val); + + clearstatcache(); + if (file_exists($outputfile) && filemtime($outputfile) > $oldmtime + && $return_val == 0) { + return true; + } elseif ($this->_returnFalseOnError) { + return false; + } + $error = PEAR::raiseError($command_orig.' command failed: ' + .implode("\n", $msg)); + return $error; + } + + /** + * Adds a cluster to the graph. + * + * @param string $id ID. + * @param array $title Title. + * @param array $attributes Attributes of the cluster. + * + * @return void + * @access public + */ + function addCluster($id, $title, $attributes = array()) + { + $this->graph['clusters'][$id]['title'] = $title; + $this->graph['clusters'][$id]['attributes'] = $attributes; + } + + /** + * Adds a note to the graph. + * + * @param string $name Name of the node. + * @param array $attributes Attributes of the node. + * @param string $group Group of the node. + * + * @return void + * @access public + */ + function addNode($name, $attributes = array(), $group = 'default') + { + $this->graph['nodes'][$group][$name] = $attributes; + } + + /** + * Removes a node from the graph. + * + * This method doesn't remove edges associated with the node. + * + * @param string $name Name of the node to be removed. + * @param string $group Group of the node. + * + * @return void + * @access public + */ + function removeNode($name, $group = 'default') + { + if (isset($this->graph['nodes'][$group][$name])) { + unset($this->graph['nodes'][$group][$name]); + } + } + + /** + * Adds an edge to the graph. + * + * Examples: + * + * $g->addEdge(array('node1' => 'node2')); + * $attr = array( + * 'label' => '+1', + * 'style' => 'dashed', + * ); + * $g->addEdge(array('node3' => 'node4'), $attr); + * + * // With port specification + * $g->addEdge(array('node5' => 'node6'), $attr, array('node6' => 'portA')); + * $g->addEdge(array('node7' => 'node8'), null, array('node7' => 'portC', + * 'node8' => 'portD')); + * + * + * @param array $edge Start => End node of the edge. + * @param array $attributes Attributes of the edge. + * @param array $ports Start node => port, End node => port + * + * @return integer an edge ID that can be used with {@link removeEdge()} + * @access public + */ + function addEdge($edge, $attributes = array(), $ports = array()) + { + if (!is_array($edge)) { + return; + } + + $from = key($edge); + $to = $edge[$from]; + $info = array(); + + if (is_array($ports)) { + if (array_key_exists($from, $ports)) { + $info['portFrom'] = $ports[$from]; + } + + if (array_key_exists($to, $ports)) { + $info['portTo'] = $ports[$to]; + } + } + + if (is_array($attributes)) { + $info['attributes'] = $attributes; + } + + if (!empty($this->graph['strict'])) { + if (!isset($this->graph['edgesFrom'][$from][$to][0])) { + $this->graph['edgesFrom'][$from][$to][0] = $info; + } else { + $this->graph['edgesFrom'][$from][$to][0] = array_merge($this->graph['edgesFrom'][$from][$to][0], $info); + } + } else { + $this->graph['edgesFrom'][$from][$to][] = $info; + } + + return count($this->graph['edgesFrom'][$from][$to]) - 1; + } + + /** + * Removes an edge from the graph. + * + * @param array $edge Start and End node of the edge to be removed. + * @param integer $id specific edge ID (only usefull when multiple edges + * exist between the same 2 nodes) + * + * @return void + * @access public + */ + function removeEdge($edge, $id = null) + { + if (!is_array($edge)) { + return; + } + + $from = key($edge); + $to = $edge[$from]; + + if (!is_null($id)) { + if (isset($this->graph['edgesFrom'][$from][$to][$id])) { + unset($this->graph['edgesFrom'][$from][$to][$id]); + + if (count($this->graph['edgesFrom'][$from][$to]) == 0) { + unset($this->graph['edgesFrom'][$from][$to]); + } + } + } elseif (isset($this->graph['edgesFrom'][$from][$to])) { + unset($this->graph['edgesFrom'][$from][$to]); + } + } + + /** + * Adds attributes to the graph. + * + * @param array $attributes Attributes to be added to the graph. + * + * @return void + * @access public + */ + function addAttributes($attributes) + { + if (is_array($attributes)) { + $this->graph['attributes'] = array_merge($this->graph['attributes'], $attributes); + } + } + + /** + * Sets attributes of the graph. + * + * @param array $attributes Attributes to be set for the graph. + * + * @return void + * @access public + */ + function setAttributes($attributes) + { + if (is_array($attributes)) { + $this->graph['attributes'] = $attributes; + } + } + + /** + * Escapes an (attribute) array + * + * Detects if an attribute is , contains double-quotes, etc... + * + * @param array $input input to escape + * + * @return array input escaped + * @access protected + */ + function _escapeArray($input) + { + $output = array(); + + foreach ((array)$input as $k => $v) { + switch ($k) { + case 'label': + case 'headlabel': + case 'taillabel': + $v = $this->_escape($v, true); + break; + default: + $v = $this->_escape($v); + $k = $this->_escape($k); + } + + $output[$k] = $v; + } + + return $output; + } + + /** + * Returns a safe "ID" in DOT syntax + * + * @param string $input string to use as "ID" + * @param boolean $html whether to attempt detecting HTML-like content + * + * @return string + * @access protected + */ + function _escape($input, $html = false) + { + switch (strtolower($input)) { + case 'node': + case 'edge': + case 'graph': + case 'digraph': + case 'subgraph': + case 'strict': + return '"'.$input.'"'; + } + + if (is_bool($input)) { + return ($input) ? 'true' : 'false'; + } + + if ($html && (strpos($input, '') !== false)) { + return '<'.$input.'>'; + } + + if (preg_match('/^([a-z_][a-z_0-9]*|-?(\.[0-9]+|[0-9]+(\.[0-9]*)?))$/i', + $input)) { + return $input; + } + + return '"'.str_replace(array("\r\n", "\n", "\r", '"'), + array('\n', '\n', '\n', '\"'), $input).'"'; + } + + /** + * Sets directed/undirected flag for the graph. + * + * Note: You MUST pass a boolean, and not just an expression that evaluates + * to TRUE or FALSE (i.e. NULL, empty string, 0 will not work) + * + * @param boolean $directed Directed (TRUE) or undirected (FALSE) graph. + * + * @return void + * @access public + */ + function setDirected($directed) + { + if (is_bool($directed)) { + $this->graph['directed'] = $directed; + } + } + + /** + * Loads a graph from a file in Image_GraphViz format + * + * @param string $file File to load graph from. + * + * @return void + * @access public + */ + function load($file) + { + if ($serializedGraph = implode('', @file($file))) { + $g = unserialize($serializedGraph); + + if (!is_array($g)) { + return; + } + + // Convert old storage format to new one + $defaults = array('edgesFrom' => array(), + 'nodes' => array(), + 'attributes' => array(), + 'directed' => true, + 'clusters' => array(), + 'name' => 'G', + 'strict' => true, + ); + + $this->graph = array_merge($defaults, $g); + + if (isset($this->graph['edges'])) { + foreach ($this->graph['edges'] as $id => $nodes) { + $attr = (isset($this->graph['edgeAttributes'][$id])) + ? $this->graph['edgeAttributes'][$id] + : array(); + + $this->addEdge($nodes, $attr); + } + + unset($this->graph['edges']); + unset($this->graph['edgeAttributes']); + } + } + } + + /** + * Save graph to file in Image_GraphViz format + * + * This saves the serialized version of the instance, not the + * rendered graph. + * + * @param string $file File to save the graph to. + * + * @return string File the graph was saved to, FALSE or PEAR_Error on + * failure. + * @access public + */ + function save($file = '') + { + $serializedGraph = serialize($this->graph); + + if (empty($file)) { + $file = System::mktemp('graph_'); + } + + if ($fp = @fopen($file, 'wb')) { + @fputs($fp, $serializedGraph); + @fclose($fp); + + return $file; + } + + if ($this->_returnFalseOnError) { + return false; + } + $error = PEAR::raiseError('Could not save serialized graph instance'); + return $error; + } + + /** + * Parses the graph into GraphViz markup. + * + * @return string GraphViz markup + * @access public + */ + function parse() + { + $parsedGraph = (empty($this->graph['strict'])) ? '' : 'strict '; + $parsedGraph .= (empty($this->graph['directed'])) ? 'graph ' : 'digraph '; + $parsedGraph .= $this->_escape($this->graph['name'])." {\n"; + + $indent = ' '; + + $attr = $this->_escapeArray($this->graph['attributes']); + + foreach ($attr as $key => $value) { + $parsedGraph .= $indent.$key.'='.$value.";\n"; + } + + foreach ($this->graph['nodes'] as $group => $nodes) { + if ($group != 'default') { + $parsedGraph .= $indent.'subgraph '.$this->_escape($group)." {\n"; + + $indent .= ' '; + + if (isset($this->graph['clusters'][$group])) { + $cluster = $this->graph['clusters'][$group]; + $attr = $this->_escapeArray($cluster['attributes']); + + foreach ($attr as $key => $value) { + $attr[] = $key.'='.$value; + } + + if (strlen($cluster['title'])) { + $attr[] = 'label=' + .$this->_escape($cluster['title'], true); + } + + if ($attr) { + $parsedGraph .= $indent.'graph [ '.implode(',', $attr) + ." ];\n"; + } + } + } + + foreach ($nodes as $node => $attributes) { + $parsedGraph .= $indent.$this->_escape($node); + + $attributeList = array(); + + foreach ($this->_escapeArray($attributes) as $key => $value) { + $attributeList[] = $key.'='.$value; + } + + if (!empty($attributeList)) { + $parsedGraph .= ' [ '.implode(',', $attributeList).' ]'; + } + + $parsedGraph .= ";\n"; + } + + if ($group != 'default') { + $indent = substr($indent, 0, -4); + + $parsedGraph .= $indent."}\n"; + } + } + + if (!empty($this->graph['directed'])) { + $separator = ' -> '; + } else { + $separator = ' -- '; + } + + foreach ($this->graph['edgesFrom'] as $from => $toNodes) { + $from = $this->_escape($from); + + foreach ($toNodes as $to => $edges) { + $to = $this->_escape($to); + + foreach ($edges as $info) { + $f = $from; + $t = $to; + + if (array_key_exists('portFrom', $info)) { + $f .= ':'.$this->_escape($info['portFrom']); + } + + if (array_key_exists('portTo', $info)) { + $t .= ':'.$this->_escape($info['portTo']); + } + + $parsedGraph .= $indent.$f.$separator.$t; + + if (!empty($info['attributes'])) { + $attributeList = array(); + + foreach ($this->_escapeArray($info['attributes']) as $key => $value) { + $attributeList[] = $key.'='.$value; + } + + $parsedGraph .= ' [ '.implode(',', $attributeList).' ]'; + } + + $parsedGraph .= ";\n"; + } + } + } + + return $parsedGraph . "}\n"; + } + + /** + * Saves GraphViz markup to file (in DOT language) + * + * @param string $file File to write the GraphViz markup to. + * + * @return string File to which the GraphViz markup was written, FALSE or + * or PEAR_Error on failure. + * @access public + */ + function saveParsedGraph($file = '') + { + $parsedGraph = $this->parse(); + + if (!empty($parsedGraph)) { + if (empty($file)) { + $file = System::mktemp('graph_'); + } + + if ($fp = @fopen($file, 'wb')) { + @fputs($fp, $parsedGraph); + @fclose($fp); + + return $file; + } + } + + if ($this->_returnFalseOnError) { + return false; + } + $error = PEAR::raiseError('Could not save graph'); + return $error; + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ +?> \ No newline at end of file diff --git a/lib/Pear/MDB2.php b/lib/Pear/MDB2.php new file mode 100644 index 0000000..691bc9b --- /dev/null +++ b/lib/Pear/MDB2.php @@ -0,0 +1,4325 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: MDB2.php,v 1.318 2008/03/08 14:18:38 quipo Exp $ +// + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + */ + +require_once 'PEAR.php'; + +// {{{ Error constants + +/** + * The method mapErrorCode in each MDB2_dbtype implementation maps + * native error codes to one of these. + * + * If you add an error code here, make sure you also add a textual + * version of it in MDB2::errorMessage(). + */ + +define('MDB2_OK', true); +define('MDB2_ERROR', -1); +define('MDB2_ERROR_SYNTAX', -2); +define('MDB2_ERROR_CONSTRAINT', -3); +define('MDB2_ERROR_NOT_FOUND', -4); +define('MDB2_ERROR_ALREADY_EXISTS', -5); +define('MDB2_ERROR_UNSUPPORTED', -6); +define('MDB2_ERROR_MISMATCH', -7); +define('MDB2_ERROR_INVALID', -8); +define('MDB2_ERROR_NOT_CAPABLE', -9); +define('MDB2_ERROR_TRUNCATED', -10); +define('MDB2_ERROR_INVALID_NUMBER', -11); +define('MDB2_ERROR_INVALID_DATE', -12); +define('MDB2_ERROR_DIVZERO', -13); +define('MDB2_ERROR_NODBSELECTED', -14); +define('MDB2_ERROR_CANNOT_CREATE', -15); +define('MDB2_ERROR_CANNOT_DELETE', -16); +define('MDB2_ERROR_CANNOT_DROP', -17); +define('MDB2_ERROR_NOSUCHTABLE', -18); +define('MDB2_ERROR_NOSUCHFIELD', -19); +define('MDB2_ERROR_NEED_MORE_DATA', -20); +define('MDB2_ERROR_NOT_LOCKED', -21); +define('MDB2_ERROR_VALUE_COUNT_ON_ROW', -22); +define('MDB2_ERROR_INVALID_DSN', -23); +define('MDB2_ERROR_CONNECT_FAILED', -24); +define('MDB2_ERROR_EXTENSION_NOT_FOUND',-25); +define('MDB2_ERROR_NOSUCHDB', -26); +define('MDB2_ERROR_ACCESS_VIOLATION', -27); +define('MDB2_ERROR_CANNOT_REPLACE', -28); +define('MDB2_ERROR_CONSTRAINT_NOT_NULL',-29); +define('MDB2_ERROR_DEADLOCK', -30); +define('MDB2_ERROR_CANNOT_ALTER', -31); +define('MDB2_ERROR_MANAGER', -32); +define('MDB2_ERROR_MANAGER_PARSE', -33); +define('MDB2_ERROR_LOADMODULE', -34); +define('MDB2_ERROR_INSUFFICIENT_DATA', -35); +define('MDB2_ERROR_NO_PERMISSION', -36); + +// }}} +// {{{ Verbose constants +/** + * These are just helper constants to more verbosely express parameters to prepare() + */ + +define('MDB2_PREPARE_MANIP', false); +define('MDB2_PREPARE_RESULT', null); + +// }}} +// {{{ Fetchmode constants + +/** + * This is a special constant that tells MDB2 the user hasn't specified + * any particular get mode, so the default should be used. + */ +define('MDB2_FETCHMODE_DEFAULT', 0); + +/** + * Column data indexed by numbers, ordered from 0 and up + */ +define('MDB2_FETCHMODE_ORDERED', 1); + +/** + * Column data indexed by column names + */ +define('MDB2_FETCHMODE_ASSOC', 2); + +/** + * Column data as object properties + */ +define('MDB2_FETCHMODE_OBJECT', 3); + +/** + * For multi-dimensional results: normally the first level of arrays + * is the row number, and the second level indexed by column number or name. + * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays + * is the column name, and the second level the row number. + */ +define('MDB2_FETCHMODE_FLIPPED', 4); + +// }}} +// {{{ Portability mode constants + +/** + * Portability: turn off all portability features. + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_NONE', 0); + +/** + * Portability: convert names of tables and fields to case defined in the + * "field_case" option when using the query*(), fetch*() and tableInfo() methods. + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_FIX_CASE', 1); + +/** + * Portability: right trim the data output by query*() and fetch*(). + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_RTRIM', 2); + +/** + * Portability: force reporting the number of rows deleted. + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_DELETE_COUNT', 4); + +/** + * Portability: not needed in MDB2 (just left here for compatibility to DB) + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_NUMROWS', 8); + +/** + * Portability: makes certain error messages in certain drivers compatible + * with those from other DBMS's. + * + * + mysql, mysqli: change unique/primary key constraints + * MDB2_ERROR_ALREADY_EXISTS -> MDB2_ERROR_CONSTRAINT + * + * + odbc(access): MS's ODBC driver reports 'no such field' as code + * 07001, which means 'too few parameters.' When this option is on + * that code gets mapped to MDB2_ERROR_NOSUCHFIELD. + * + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_ERRORS', 16); + +/** + * Portability: convert empty values to null strings in data output by + * query*() and fetch*(). + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32); + +/** + * Portability: removes database/table qualifiers from associative indexes + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64); + +/** + * Portability: turn on all portability features. + * @see MDB2_Driver_Common::setOption() + */ +define('MDB2_PORTABILITY_ALL', 127); + +// }}} +// {{{ Globals for class instance tracking + +/** + * These are global variables that are used to track the various class instances + */ + +$GLOBALS['_MDB2_databases'] = array(); +$GLOBALS['_MDB2_dsninfo_default'] = array( + 'phptype' => false, + 'dbsyntax' => false, + 'username' => false, + 'password' => false, + 'protocol' => false, + 'hostspec' => false, + 'port' => false, + 'socket' => false, + 'database' => false, + 'mode' => false, +); + +// }}} +// {{{ class MDB2 + +/** + * The main 'MDB2' class is simply a container class with some static + * methods for creating DB objects as well as some utility functions + * common to all parts of DB. + * + * The object model of MDB2 is as follows (indentation means inheritance): + * + * MDB2 The main MDB2 class. This is simply a utility class + * with some 'static' methods for creating MDB2 objects as + * well as common utility functions for other MDB2 classes. + * + * MDB2_Driver_Common The base for each MDB2 implementation. Provides default + * | implementations (in OO lingo virtual methods) for + * | the actual DB implementations as well as a bunch of + * | query utility functions. + * | + * +-MDB2_Driver_mysql The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common. + * When calling MDB2::factory or MDB2::connect for MySQL + * connections, the object returned is an instance of this + * class. + * +-MDB2_Driver_pgsql The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common. + * When calling MDB2::factory or MDB2::connect for PostGreSQL + * connections, the object returned is an instance of this + * class. + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2 +{ + // {{{ function setOptions(&$db, $options) + + /** + * set option array in an exiting database object + * + * @param MDB2_Driver_Common MDB2 object + * @param array An associative array of option names and their values. + * + * @return mixed MDB2_OK or a PEAR Error object + * + * @access public + */ + function setOptions(&$db, $options) + { + if (is_array($options)) { + foreach ($options as $option => $value) { + $test = $db->setOption($option, $value); + if (PEAR::isError($test)) { + return $test; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ function classExists($classname) + + /** + * Checks if a class exists without triggering __autoload + * + * @param string classname + * + * @return bool true success and false on error + * @static + * @access public + */ + function classExists($classname) + { + if (version_compare(phpversion(), "5.0", ">=")) { + return class_exists($classname, false); + } + return class_exists($classname); + } + + // }}} + // {{{ function loadClass($class_name, $debug) + + /** + * Loads a PEAR class. + * + * @param string classname to load + * @param bool if errors should be suppressed + * + * @return mixed true success or PEAR_Error on failure + * + * @access public + */ + function loadClass($class_name, $debug) + { + if (!MDB2::classExists($class_name)) { + $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php'; + if ($debug) { + $include = include_once($file_name); + } else { + $include = @include_once($file_name); + } + if (!$include) { + if (!MDB2::fileExists($file_name)) { + $msg = "unable to find package '$class_name' file '$file_name'"; + } else { + $msg = "unable to load class '$class_name' from file '$file_name'"; + } + $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg); + return $err; + } + } + return MDB2_OK; + } + + // }}} + // {{{ function &factory($dsn, $options = false) + + /** + * Create a new MDB2 object for the specified database type + * + * IMPORTANT: In order for MDB2 to work properly it is necessary that + * you make sure that you work with a reference of the original + * object instead of a copy (this is a PHP4 quirk). + * + * For example: + * $db =& MDB2::factory($dsn); + * ^^ + * And not: + * $db = MDB2::factory($dsn); + * + * @param mixed 'data source name', see the MDB2::parseDSN + * method for a description of the dsn format. + * Can also be specified as an array of the + * format returned by MDB2::parseDSN. + * @param array An associative array of option names and + * their values. + * + * @return mixed a newly created MDB2 object, or false on error + * + * @access public + */ + function &factory($dsn, $options = false) + { + $dsninfo = MDB2::parseDSN($dsn); + if (empty($dsninfo['phptype'])) { + $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, + null, null, 'no RDBMS driver specified'); + return $err; + } + $class_name = 'MDB2_Driver_'.$dsninfo['phptype']; + + $debug = (!empty($options['debug'])); + $err = MDB2::loadClass($class_name, $debug); + if (PEAR::isError($err)) { + return $err; + } + + $db =& new $class_name(); + $db->setDSN($dsninfo); + $err = MDB2::setOptions($db, $options); + if (PEAR::isError($err)) { + return $err; + } + + return $db; + } + + // }}} + // {{{ function &connect($dsn, $options = false) + + /** + * Create a new MDB2 connection object and connect to the specified + * database + * + * IMPORTANT: In order for MDB2 to work properly it is necessary that + * you make sure that you work with a reference of the original + * object instead of a copy (this is a PHP4 quirk). + * + * For example: + * $db =& MDB2::connect($dsn); + * ^^ + * And not: + * $db = MDB2::connect($dsn); + * ^^ + * + * @param mixed 'data source name', see the MDB2::parseDSN + * method for a description of the dsn format. + * Can also be specified as an array of the + * format returned by MDB2::parseDSN. + * @param array An associative array of option names and + * their values. + * + * @return mixed a newly created MDB2 connection object, or a MDB2 + * error object on error + * + * @access public + * @see MDB2::parseDSN + */ + function &connect($dsn, $options = false) + { + $db =& MDB2::factory($dsn, $options); + if (PEAR::isError($db)) { + return $db; + } + + $err = $db->connect(); + if (PEAR::isError($err)) { + $dsn = $db->getDSN('string', 'xxx'); + $db->disconnect(); + $err->addUserInfo($dsn); + return $err; + } + + return $db; + } + + // }}} + // {{{ function &singleton($dsn = null, $options = false) + + /** + * Returns a MDB2 connection with the requested DSN. + * A new MDB2 connection object is only created if no object with the + * requested DSN exists yet. + * + * IMPORTANT: In order for MDB2 to work properly it is necessary that + * you make sure that you work with a reference of the original + * object instead of a copy (this is a PHP4 quirk). + * + * For example: + * $db =& MDB2::singleton($dsn); + * ^^ + * And not: + * $db = MDB2::singleton($dsn); + * ^^ + * + * @param mixed 'data source name', see the MDB2::parseDSN + * method for a description of the dsn format. + * Can also be specified as an array of the + * format returned by MDB2::parseDSN. + * @param array An associative array of option names and + * their values. + * + * @return mixed a newly created MDB2 connection object, or a MDB2 + * error object on error + * + * @access public + * @see MDB2::parseDSN + */ + function &singleton($dsn = null, $options = false) + { + if ($dsn) { + $dsninfo = MDB2::parseDSN($dsn); + $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo); + $keys = array_keys($GLOBALS['_MDB2_databases']); + for ($i=0, $j=count($keys); $i<$j; ++$i) { + if (isset($GLOBALS['_MDB2_databases'][$keys[$i]])) { + $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array'); + if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0) { + MDB2::setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options); + return $GLOBALS['_MDB2_databases'][$keys[$i]]; + } + } + } + } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) { + $db =& $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])]; + return $db; + } + $db =& MDB2::factory($dsn, $options); + return $db; + } + + // }}} + // {{{ function areEquals() + + /** + * It looks like there's a memory leak in array_diff() in PHP 5.1.x, + * so use this method instead. + * @see http://pear.php.net/bugs/bug.php?id=11790 + * + * @param array $arr1 + * @param array $arr2 + * @return boolean + */ + function areEquals($arr1, $arr2) + { + if (count($arr1) != count($arr2)) { + return false; + } + foreach (array_keys($arr1) as $k) { + if (!array_key_exists($k, $arr2) || $arr1[$k] != $arr2[$k]) { + return false; + } + } + return true; + } + + // }}} + // {{{ function loadFile($file) + + /** + * load a file (like 'Date') + * + * @param string name of the file in the MDB2 directory (without '.php') + * + * @return string name of the file that was included + * + * @access public + */ + function loadFile($file) + { + $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php'; + if (!MDB2::fileExists($file_name)) { + return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'unable to find: '.$file_name); + } + if (!include_once($file_name)) { + return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'unable to load driver class: '.$file_name); + } + return $file_name; + } + + // }}} + // {{{ function apiVersion() + + /** + * Return the MDB2 API version + * + * @return string the MDB2 API version number + * + * @access public + */ + function apiVersion() + { + return '2.5.0b1'; + } + + // }}} + // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null) + + /** + * This method is used to communicate an error and invoke error + * callbacks etc. Basically a wrapper for PEAR::raiseError + * without the message string. + * + * @param mixed int error code + * + * @param int error mode, see PEAR_Error docs + * + * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * + * @param string Extra debug information. Defaults to the last + * query and native error code. + * + * @return PEAR_Error instance of a PEAR Error object + * + * @access private + * @see PEAR_Error + */ + function &raiseError($code = null, + $mode = null, + $options = null, + $userinfo = null, + $dummy1 = null, + $dummy2 = null, + $dummy3 = false) + { + $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true); + return $err; + } + + // }}} + // {{{ function isError($data, $code = null) + + /** + * Tell whether a value is a MDB2 error. + * + * @param mixed the value to test + * @param int if is an error object, return true + * only if $code is a string and + * $db->getMessage() == $code or + * $code is an integer and $db->getCode() == $code + * + * @return bool true if parameter is an error + * + * @access public + */ + function isError($data, $code = null) + { + if (is_a($data, 'MDB2_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() === $code; + } else { + $code = (array)$code; + return in_array($data->getCode(), $code); + } + } + return false; + } + + // }}} + // {{{ function isConnection($value) + + /** + * Tell whether a value is a MDB2 connection + * + * @param mixed value to test + * + * @return bool whether $value is a MDB2 connection + * + * @access public + */ + function isConnection($value) + { + return is_a($value, 'MDB2_Driver_Common'); + } + + // }}} + // {{{ function isResult($value) + + /** + * Tell whether a value is a MDB2 result + * + * @param mixed value to test + * + * @return bool whether $value is a MDB2 result + * + * @access public + */ + function isResult($value) + { + return is_a($value, 'MDB2_Result'); + } + + // }}} + // {{{ function isResultCommon($value) + + /** + * Tell whether a value is a MDB2 result implementing the common interface + * + * @param mixed value to test + * + * @return bool whether $value is a MDB2 result implementing the common interface + * + * @access public + */ + function isResultCommon($value) + { + return is_a($value, 'MDB2_Result_Common'); + } + + // }}} + // {{{ function isStatement($value) + + /** + * Tell whether a value is a MDB2 statement interface + * + * @param mixed value to test + * + * @return bool whether $value is a MDB2 statement interface + * + * @access public + */ + function isStatement($value) + { + return is_a($value, 'MDB2_Statement_Common'); + } + + // }}} + // {{{ function errorMessage($value = null) + + /** + * Return a textual error message for a MDB2 error code + * + * @param int|array integer error code, + null to get the current error code-message map, + or an array with a new error code-message map + * + * @return string error message, or false if the error code was + * not recognized + * + * @access public + */ + function errorMessage($value = null) + { + static $errorMessages; + + if (is_array($value)) { + $errorMessages = $value; + return MDB2_OK; + } + + if (!isset($errorMessages)) { + $errorMessages = array( + MDB2_OK => 'no error', + MDB2_ERROR => 'unknown error', + MDB2_ERROR_ALREADY_EXISTS => 'already exists', + MDB2_ERROR_CANNOT_CREATE => 'can not create', + MDB2_ERROR_CANNOT_ALTER => 'can not alter', + MDB2_ERROR_CANNOT_REPLACE => 'can not replace', + MDB2_ERROR_CANNOT_DELETE => 'can not delete', + MDB2_ERROR_CANNOT_DROP => 'can not drop', + MDB2_ERROR_CONSTRAINT => 'constraint violation', + MDB2_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', + MDB2_ERROR_DIVZERO => 'division by zero', + MDB2_ERROR_INVALID => 'invalid', + MDB2_ERROR_INVALID_DATE => 'invalid date or time', + MDB2_ERROR_INVALID_NUMBER => 'invalid number', + MDB2_ERROR_MISMATCH => 'mismatch', + MDB2_ERROR_NODBSELECTED => 'no database selected', + MDB2_ERROR_NOSUCHFIELD => 'no such field', + MDB2_ERROR_NOSUCHTABLE => 'no such table', + MDB2_ERROR_NOT_CAPABLE => 'MDB2 backend not capable', + MDB2_ERROR_NOT_FOUND => 'not found', + MDB2_ERROR_NOT_LOCKED => 'not locked', + MDB2_ERROR_SYNTAX => 'syntax error', + MDB2_ERROR_UNSUPPORTED => 'not supported', + MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', + MDB2_ERROR_INVALID_DSN => 'invalid DSN', + MDB2_ERROR_CONNECT_FAILED => 'connect failed', + MDB2_ERROR_NEED_MORE_DATA => 'insufficient data supplied', + MDB2_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', + MDB2_ERROR_NOSUCHDB => 'no such database', + MDB2_ERROR_ACCESS_VIOLATION => 'insufficient permissions', + MDB2_ERROR_LOADMODULE => 'error while including on demand module', + MDB2_ERROR_TRUNCATED => 'truncated', + MDB2_ERROR_DEADLOCK => 'deadlock detected', + MDB2_ERROR_NO_PERMISSION => 'no permission', + ); + } + + if (is_null($value)) { + return $errorMessages; + } + + if (PEAR::isError($value)) { + $value = $value->getCode(); + } + + return isset($errorMessages[$value]) ? + $errorMessages[$value] : $errorMessages[MDB2_ERROR]; + } + + // }}} + // {{{ function parseDSN($dsn) + + /** + * Parse a data source name. + * + * Additional keys can be added by appending a URI query string to the + * end of the DSN. + * + * The format of the supplied DSN is in its fullest form: + * + * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true + * + * + * Most variations are allowed: + * + * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644 + * phptype://username:password@hostspec/database_name + * phptype://username:password@hostspec + * phptype://username@hostspec + * phptype://hostspec/database + * phptype://hostspec + * phptype(dbsyntax) + * phptype + * + * + * @param string Data Source Name to be parsed + * + * @return array an associative array with the following keys: + * + phptype: Database backend used in PHP (mysql, odbc etc.) + * + dbsyntax: Database used with regards to SQL syntax etc. + * + protocol: Communication protocol to use (tcp, unix etc.) + * + hostspec: Host specification (hostname[:port]) + * + database: Database to use on the DBMS server + * + username: User name for login + * + password: Password for login + * + * @access public + * @author Tomas V.V.Cox + */ + function parseDSN($dsn) + { + $parsed = $GLOBALS['_MDB2_dsninfo_default']; + + if (is_array($dsn)) { + $dsn = array_merge($parsed, $dsn); + if (!$dsn['dbsyntax']) { + $dsn['dbsyntax'] = $dsn['phptype']; + } + return $dsn; + } + + // Find phptype and dbsyntax + if (($pos = strpos($dsn, '://')) !== false) { + $str = substr($dsn, 0, $pos); + $dsn = substr($dsn, $pos + 3); + } else { + $str = $dsn; + $dsn = null; + } + + // Get phptype and dbsyntax + // $str => phptype(dbsyntax) + if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { + $parsed['phptype'] = $arr[1]; + $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; + } else { + $parsed['phptype'] = $str; + $parsed['dbsyntax'] = $str; + } + + if (!count($dsn)) { + return $parsed; + } + + // Get (if found): username and password + // $dsn => username:password@protocol+hostspec/database + if (($at = strrpos($dsn,'@')) !== false) { + $str = substr($dsn, 0, $at); + $dsn = substr($dsn, $at + 1); + if (($pos = strpos($str, ':')) !== false) { + $parsed['username'] = rawurldecode(substr($str, 0, $pos)); + $parsed['password'] = rawurldecode(substr($str, $pos + 1)); + } else { + $parsed['username'] = rawurldecode($str); + } + } + + // Find protocol and hostspec + + // $dsn => proto(proto_opts)/database + if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { + $proto = $match[1]; + $proto_opts = $match[2] ? $match[2] : false; + $dsn = $match[3]; + + // $dsn => protocol+hostspec/database (old format) + } else { + if (strpos($dsn, '+') !== false) { + list($proto, $dsn) = explode('+', $dsn, 2); + } + if ( strpos($dsn, '//') === 0 + && strpos($dsn, '/', 2) !== false + && $parsed['phptype'] == 'oci8' + ) { + //oracle's "Easy Connect" syntax: + //"username/password@[//]host[:port][/service_name]" + //e.g. "scott/tiger@//mymachine:1521/oracle" + $proto_opts = $dsn; + $dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1); + } elseif (strpos($dsn, '/') !== false) { + list($proto_opts, $dsn) = explode('/', $dsn, 2); + } else { + $proto_opts = $dsn; + $dsn = null; + } + } + + // process the different protocol options + $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; + $proto_opts = rawurldecode($proto_opts); + if (strpos($proto_opts, ':') !== false) { + list($proto_opts, $parsed['port']) = explode(':', $proto_opts); + } + if ($parsed['protocol'] == 'tcp') { + $parsed['hostspec'] = $proto_opts; + } elseif ($parsed['protocol'] == 'unix') { + $parsed['socket'] = $proto_opts; + } + + // Get dabase if any + // $dsn => database + if ($dsn) { + // /database + if (($pos = strpos($dsn, '?')) === false) { + $parsed['database'] = $dsn; + // /database?param1=value1¶m2=value2 + } else { + $parsed['database'] = substr($dsn, 0, $pos); + $dsn = substr($dsn, $pos + 1); + if (strpos($dsn, '&') !== false) { + $opts = explode('&', $dsn); + } else { // database?param1=value1 + $opts = array($dsn); + } + foreach ($opts as $opt) { + list($key, $value) = explode('=', $opt); + if (!isset($parsed[$key])) { + // don't allow params overwrite + $parsed[$key] = rawurldecode($value); + } + } + } + } + + return $parsed; + } + + // }}} + // {{{ function fileExists($file) + + /** + * Checks if a file exists in the include path + * + * @param string filename + * + * @return bool true success and false on error + * + * @access public + */ + function fileExists($file) + { + // safe_mode does notwork with is_readable() + if (!@ini_get('safe_mode')) { + $dirs = explode(PATH_SEPARATOR, ini_get('include_path')); + foreach ($dirs as $dir) { + if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) { + return true; + } + } + } else { + $fp = @fopen($file, 'r', true); + if (is_resource($fp)) { + @fclose($fp); + return true; + } + } + return false; + } + // }}} +} + +// }}} +// {{{ class MDB2_Error extends PEAR_Error + +/** + * MDB2_Error implements a class for reporting portable database error + * messages. + * + * @package MDB2 + * @category Database + * @author Stig Bakken + */ +class MDB2_Error extends PEAR_Error +{ + // {{{ constructor: function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) + + /** + * MDB2_Error constructor. + * + * @param mixed MDB2 error code, or string with error message. + * @param int what 'error mode' to operate in + * @param int what error level to use for $mode & PEAR_ERROR_TRIGGER + * @param mixed additional debug info, such as the last query + */ + function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, + $level = E_USER_NOTICE, $debuginfo = null, $dummy = null) + { + if (is_null($code)) { + $code = MDB2_ERROR; + } + $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code, + $mode, $level, $debuginfo); + } + + // }}} +} + +// }}} +// {{{ class MDB2_Driver_Common extends PEAR + +/** + * MDB2_Driver_Common: Base class that is extended by each MDB2 driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Common extends PEAR +{ + // {{{ Variables (Properties) + + /** + * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array + * @var int + * @access public + */ + var $db_index = 0; + + /** + * DSN used for the next query + * @var array + * @access protected + */ + var $dsn = array(); + + /** + * DSN that was used to create the current connection + * @var array + * @access protected + */ + var $connected_dsn = array(); + + /** + * connection resource + * @var mixed + * @access protected + */ + var $connection = 0; + + /** + * if the current opened connection is a persistent connection + * @var bool + * @access protected + */ + var $opened_persistent; + + /** + * the name of the database for the next query + * @var string + * @access protected + */ + var $database_name = ''; + + /** + * the name of the database currently selected + * @var string + * @access protected + */ + var $connected_database_name = ''; + + /** + * server version information + * @var string + * @access protected + */ + var $connected_server_info = ''; + + /** + * list of all supported features of the given driver + * @var array + * @access public + */ + var $supported = array( + 'sequences' => false, + 'indexes' => false, + 'affected_rows' => false, + 'summary_functions' => false, + 'order_by_text' => false, + 'transactions' => false, + 'savepoints' => false, + 'current_id' => false, + 'limit_queries' => false, + 'LOBs' => false, + 'replace' => false, + 'sub_selects' => false, + 'triggers' => false, + 'auto_increment' => false, + 'primary_key' => false, + 'result_introspection' => false, + 'prepared_statements' => false, + 'identifier_quoting' => false, + 'pattern_escaping' => false, + 'new_link' => false, + ); + + /** + * Array of supported options that can be passed to the MDB2 instance. + * + * The options can be set during object creation, using + * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can + * also be set after the object is created, using MDB2::setOptions() or + * MDB2_Driver_Common::setOption(). + * The list of available option includes: + *
    + *
  • $options['ssl'] -> boolean: determines if ssl should be used for connections
  • + *
  • $options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names
  • + *
  • $options['disable_query'] -> boolean: determines if queries should be executed
  • + *
  • $options['result_class'] -> string: class used for result sets
  • + *
  • $options['buffered_result_class'] -> string: class used for buffered result sets
  • + *
  • $options['result_wrap_class'] -> string: class used to wrap result sets into
  • + *
  • $options['result_buffering'] -> boolean should results be buffered or not?
  • + *
  • $options['fetch_class'] -> string: class to use when fetch mode object is used
  • + *
  • $options['persistent'] -> boolean: persistent connection?
  • + *
  • $options['debug'] -> integer: numeric debug level
  • + *
  • $options['debug_handler'] -> string: function/method that captures debug messages
  • + *
  • $options['debug_expanded_output'] -> bool: BC option to determine if more context information should be send to the debug handler
  • + *
  • $options['default_text_field_length'] -> integer: default text field length to use
  • + *
  • $options['lob_buffer_length'] -> integer: LOB buffer length
  • + *
  • $options['log_line_break'] -> string: line-break format
  • + *
  • $options['idxname_format'] -> string: pattern for index name
  • + *
  • $options['seqname_format'] -> string: pattern for sequence name
  • + *
  • $options['savepoint_format'] -> string: pattern for auto generated savepoint names
  • + *
  • $options['statement_format'] -> string: pattern for prepared statement names
  • + *
  • $options['seqcol_name'] -> string: sequence column name
  • + *
  • $options['quote_identifier'] -> boolean: if identifier quoting should be done when check_option is used
  • + *
  • $options['use_transactions'] -> boolean: if transaction use should be enabled
  • + *
  • $options['decimal_places'] -> integer: number of decimal places to handle
  • + *
  • $options['portability'] -> integer: portability constant
  • + *
  • $options['modules'] -> array: short to long module name mapping for __call()
  • + *
  • $options['emulate_prepared'] -> boolean: force prepared statements to be emulated
  • + *
  • $options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes
  • + *
  • $options['datatype_map_callback'] -> array: callback function/method that should be called
  • + *
  • $options['bindname_format'] -> string: regular expression pattern for named parameters + *
  • $options['max_identifiers_length'] -> integer: max identifier length
  • + *
+ * + * @var array + * @access public + * @see MDB2::connect() + * @see MDB2::factory() + * @see MDB2::singleton() + * @see MDB2_Driver_Common::setOption() + */ + var $options = array( + 'ssl' => false, + 'field_case' => CASE_LOWER, + 'disable_query' => false, + 'result_class' => 'MDB2_Result_%s', + 'buffered_result_class' => 'MDB2_BufferedResult_%s', + 'result_wrap_class' => false, + 'result_buffering' => true, + 'fetch_class' => 'stdClass', + 'persistent' => false, + 'debug' => 0, + 'debug_handler' => 'MDB2_defaultDebugOutput', + 'debug_expanded_output' => false, + 'default_text_field_length' => 4096, + 'lob_buffer_length' => 8192, + 'log_line_break' => "\n", + 'idxname_format' => '%s_idx', + 'seqname_format' => '%s_seq', + 'savepoint_format' => 'MDB2_SAVEPOINT_%s', + 'statement_format' => 'MDB2_STATEMENT_%1$s_%2$s', + 'seqcol_name' => 'sequence', + 'quote_identifier' => false, + 'use_transactions' => true, + 'decimal_places' => 2, + 'portability' => MDB2_PORTABILITY_ALL, + 'modules' => array( + 'ex' => 'Extended', + 'dt' => 'Datatype', + 'mg' => 'Manager', + 'rv' => 'Reverse', + 'na' => 'Native', + 'fc' => 'Function', + ), + 'emulate_prepared' => false, + 'datatype_map' => array(), + 'datatype_map_callback' => array(), + 'nativetype_map_callback' => array(), + 'lob_allow_url_include' => false, + 'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)', + 'max_identifiers_length' => 30, + ); + + /** + * string array + * @var string + * @access protected + */ + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => false, 'escape_pattern' => false); + + /** + * identifier quoting + * @var array + * @access protected + */ + var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"'); + + /** + * sql comments + * @var array + * @access protected + */ + var $sql_comments = array( + array('start' => '--', 'end' => "\n", 'escape' => false), + array('start' => '/*', 'end' => '*/', 'escape' => false), + ); + + /** + * comparision wildcards + * @var array + * @access protected + */ + var $wildcards = array('%', '_'); + + /** + * column alias keyword + * @var string + * @access protected + */ + var $as_keyword = ' AS '; + + /** + * warnings + * @var array + * @access protected + */ + var $warnings = array(); + + /** + * string with the debugging information + * @var string + * @access public + */ + var $debug_output = ''; + + /** + * determine if there is an open transaction + * @var bool + * @access protected + */ + var $in_transaction = false; + + /** + * the smart transaction nesting depth + * @var int + * @access protected + */ + var $nested_transaction_counter = null; + + /** + * the first error that occured inside a nested transaction + * @var MDB2_Error|bool + * @access protected + */ + var $has_transaction_error = false; + + /** + * result offset used in the next query + * @var int + * @access protected + */ + var $offset = 0; + + /** + * result limit used in the next query + * @var int + * @access protected + */ + var $limit = 0; + + /** + * Database backend used in PHP (mysql, odbc etc.) + * @var string + * @access public + */ + var $phptype; + + /** + * Database used with regards to SQL syntax etc. + * @var string + * @access public + */ + var $dbsyntax; + + /** + * the last query sent to the driver + * @var string + * @access public + */ + var $last_query; + + /** + * the default fetchmode used + * @var int + * @access protected + */ + var $fetchmode = MDB2_FETCHMODE_ORDERED; + + /** + * array of module instances + * @var array + * @access protected + */ + var $modules = array(); + + /** + * determines of the PHP4 destructor emulation has been enabled yet + * @var array + * @access protected + */ + var $destructor_registered = true; + + // }}} + // {{{ constructor: function __construct() + + /** + * Constructor + */ + function __construct() + { + end($GLOBALS['_MDB2_databases']); + $db_index = key($GLOBALS['_MDB2_databases']) + 1; + $GLOBALS['_MDB2_databases'][$db_index] = &$this; + $this->db_index = $db_index; + } + + // }}} + // {{{ function MDB2_Driver_Common() + + /** + * PHP 4 Constructor + */ + function MDB2_Driver_Common() + { + $this->destructor_registered = false; + $this->__construct(); + } + + // }}} + // {{{ destructor: function __destruct() + + /** + * Destructor + */ + function __destruct() + { + $this->disconnect(false); + } + + // }}} + // {{{ function free() + + /** + * Free the internal references so that the instance can be destroyed + * + * @return bool true on success, false if result is invalid + * + * @access public + */ + function free() + { + unset($GLOBALS['_MDB2_databases'][$this->db_index]); + unset($this->db_index); + return MDB2_OK; + } + + // }}} + // {{{ function __toString() + + /** + * String conversation + * + * @return string representation of the object + * + * @access public + */ + function __toString() + { + $info = get_class($this); + $info.= ': (phptype = '.$this->phptype.', dbsyntax = '.$this->dbsyntax.')'; + if ($this->connection) { + $info.= ' [connected]'; + } + return $info; + } + + // }}} + // {{{ function errorInfo($error = null) + + /** + * This method is used to collect information about an error + * + * @param mixed error code or resource + * + * @return array with MDB2 errorcode, native error code, native message + * + * @access public + */ + function errorInfo($error = null) + { + return array($error, null, null); + } + + // }}} + // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null) + + /** + * This method is used to communicate an error and invoke error + * callbacks etc. Basically a wrapper for PEAR::raiseError + * without the message string. + * + * @param mixed integer error code, or a PEAR error object (all other + * parameters are ignored if this parameter is an object + * @param int error mode, see PEAR_Error docs + * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * @param string Extra debug information. Defaults to the last + * query and native error code. + * @param string name of the method that triggered the error + * + * @return PEAR_Error instance of a PEAR Error object + * + * @access public + * @see PEAR_Error + */ + function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $method = null) + { + $userinfo = "[Error message: $userinfo]\n"; + // The error is yet a MDB2 error object + if (PEAR::isError($code)) { + // because we use the static PEAR::raiseError, our global + // handler should be used if it is set + if (is_null($mode) && !empty($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + } + if (is_null($userinfo)) { + $userinfo = $code->getUserinfo(); + } + $code = $code->getCode(); + } elseif ($code == MDB2_ERROR_NOT_FOUND) { + // extension not loaded: don't call $this->errorInfo() or the script + // will die + } elseif (isset($this->connection)) { + if (!empty($this->last_query)) { + $userinfo.= "[Last executed query: {$this->last_query}]\n"; + } + $native_errno = $native_msg = null; + list($code, $native_errno, $native_msg) = $this->errorInfo($code); + if (!is_null($native_errno) && $native_errno !== '') { + $userinfo.= "[Native code: $native_errno]\n"; + } + if (!is_null($native_msg) && $native_msg !== '') { + $userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n"; + } + if (!is_null($method)) { + $userinfo = $method.': '.$userinfo; + } + } + + $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true); + if ($err->getMode() !== PEAR_ERROR_RETURN + && isset($this->nested_transaction_counter) && !$this->has_transaction_error) { + $this->has_transaction_error =& $err; + } + return $err; + } + + // }}} + // {{{ function resetWarnings() + + /** + * reset the warning array + * + * @return void + * + * @access public + */ + function resetWarnings() + { + $this->warnings = array(); + } + + // }}} + // {{{ function getWarnings() + + /** + * Get all warnings in reverse order. + * This means that the last warning is the first element in the array + * + * @return array with warnings + * + * @access public + * @see resetWarnings() + */ + function getWarnings() + { + return array_reverse($this->warnings); + } + + // }}} + // {{{ function setFetchMode($fetchmode, $object_class = 'stdClass') + + /** + * Sets which fetch mode should be used by default on queries + * on this connection + * + * @param int MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC + * or MDB2_FETCHMODE_OBJECT + * @param string the class name of the object to be returned + * by the fetch methods when the + * MDB2_FETCHMODE_OBJECT mode is selected. + * If no class is specified by default a cast + * to object from the assoc array row will be + * done. There is also the possibility to use + * and extend the 'MDB2_row' class. + * + * @return mixed MDB2_OK or MDB2 Error Object + * + * @access public + * @see MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC, MDB2_FETCHMODE_OBJECT + */ + function setFetchMode($fetchmode, $object_class = 'stdClass') + { + switch ($fetchmode) { + case MDB2_FETCHMODE_OBJECT: + $this->options['fetch_class'] = $object_class; + case MDB2_FETCHMODE_ORDERED: + case MDB2_FETCHMODE_ASSOC: + $this->fetchmode = $fetchmode; + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'invalid fetchmode mode', __FUNCTION__); + } + + return MDB2_OK; + } + + // }}} + // {{{ function setOption($option, $value) + + /** + * set the option for the db class + * + * @param string option name + * @param mixed value for the option + * + * @return mixed MDB2_OK or MDB2 Error Object + * + * @access public + */ + function setOption($option, $value) + { + if (array_key_exists($option, $this->options)) { + $this->options[$option] = $value; + return MDB2_OK; + } + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + "unknown option $option", __FUNCTION__); + } + + // }}} + // {{{ function getOption($option) + + /** + * Returns the value of an option + * + * @param string option name + * + * @return mixed the option value or error object + * + * @access public + */ + function getOption($option) + { + if (array_key_exists($option, $this->options)) { + return $this->options[$option]; + } + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + "unknown option $option", __FUNCTION__); + } + + // }}} + // {{{ function debug($message, $scope = '', $is_manip = null) + + /** + * set a debug message + * + * @param string message that should be appended to the debug variable + * @param string usually the method name that triggered the debug call: + * for example 'query', 'prepare', 'execute', 'parameters', + * 'beginTransaction', 'commit', 'rollback' + * @param array contains context information about the debug() call + * common keys are: is_manip, time, result etc. + * + * @return void + * + * @access public + */ + function debug($message, $scope = '', $context = array()) + { + if ($this->options['debug'] && $this->options['debug_handler']) { + if (!$this->options['debug_expanded_output']) { + if (!empty($context['when']) && $context['when'] !== 'pre') { + return null; + } + $context = empty($context['is_manip']) ? false : $context['is_manip']; + } + return call_user_func_array($this->options['debug_handler'], array(&$this, $scope, $message, $context)); + } + return null; + } + + // }}} + // {{{ function getDebugOutput() + + /** + * output debug info + * + * @return string content of the debug_output class variable + * + * @access public + */ + function getDebugOutput() + { + return $this->debug_output; + } + + // }}} + // {{{ function escape($text) + + /** + * Quotes a string so it can be safely used in a query. It will quote + * the text so it can safely be used within a query. + * + * @param string the input string to quote + * @param bool escape wildcards + * + * @return string quoted string + * + * @access public + */ + function escape($text, $escape_wildcards = false) + { + if ($escape_wildcards) { + $text = $this->escapePattern($text); + } + + $text = str_replace($this->string_quoting['end'], $this->string_quoting['escape'] . $this->string_quoting['end'], $text); + return $text; + } + + // }}} + // {{{ function escapePattern($text) + + /** + * Quotes pattern (% and _) characters in a string) + * + * @param string the input string to quote + * + * @return string quoted string + * + * @access public + */ + function escapePattern($text) + { + if ($this->string_quoting['escape_pattern']) { + $text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text); + foreach ($this->wildcards as $wildcard) { + $text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text); + } + } + return $text; + } + + // }}} + // {{{ function quoteIdentifier($str, $check_option = false) + + /** + * Quote a string so it can be safely used as a table or column name + * + * Delimiting style depends on which database driver is being used. + * + * NOTE: just because you CAN use delimited identifiers doesn't mean + * you SHOULD use them. In general, they end up causing way more + * problems than they solve. + * + * NOTE: if you have table names containing periods, don't use this method + * (@see bug #11906) + * + * Portability is broken by using the following characters inside + * delimited identifiers: + * + backtick (`) -- due to MySQL + * + double quote (") -- due to Oracle + * + brackets ([ or ]) -- due to Access + * + * Delimited identifiers are known to generally work correctly under + * the following drivers: + * + mssql + * + mysql + * + mysqli + * + oci8 + * + pgsql + * + sqlite + * + * InterBase doesn't seem to be able to use delimited identifiers + * via PHP 4. They work fine under PHP 5. + * + * @param string identifier name to be quoted + * @param bool check the 'quote_identifier' option + * + * @return string quoted identifier string + * + * @access public + */ + function quoteIdentifier($str, $check_option = false) + { + if ($check_option && !$this->options['quote_identifier']) { + return $str; + } + $str = str_replace($this->identifier_quoting['end'], $this->identifier_quoting['escape'] . $this->identifier_quoting['end'], $str); + $parts = explode('.', $str); + foreach (array_keys($parts) as $k) { + $parts[$k] = $this->identifier_quoting['start'] . $parts[$k] . $this->identifier_quoting['end']; + } + return implode('.', $parts); + } + + // }}} + // {{{ function getAsKeyword() + + /** + * Gets the string to alias column + * + * @return string to use when aliasing a column + */ + function getAsKeyword() + { + return $this->as_keyword; + } + + // }}} + // {{{ function getConnection() + + /** + * Returns a native connection + * + * @return mixed a valid MDB2 connection object, + * or a MDB2 error object on error + * + * @access public + */ + function getConnection() + { + $result = $this->connect(); + if (PEAR::isError($result)) { + return $result; + } + return $this->connection; + } + + // }}} + // {{{ function _fixResultArrayValues(&$row, $mode) + + /** + * Do all necessary conversions on result arrays to fix DBMS quirks + * + * @param array the array to be fixed (passed by reference) + * @param array bit-wise addition of the required portability modes + * + * @return void + * + * @access protected + */ + function _fixResultArrayValues(&$row, $mode) + { + switch ($mode) { + case MDB2_PORTABILITY_EMPTY_TO_NULL: + foreach ($row as $key => $value) { + if ($value === '') { + $row[$key] = null; + } + } + break; + case MDB2_PORTABILITY_RTRIM: + foreach ($row as $key => $value) { + if (is_string($value)) { + $row[$key] = rtrim($value); + } + } + break; + case MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES: + $tmp_row = array(); + foreach ($row as $key => $value) { + $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value; + } + $row = $tmp_row; + break; + case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_EMPTY_TO_NULL): + foreach ($row as $key => $value) { + if ($value === '') { + $row[$key] = null; + } elseif (is_string($value)) { + $row[$key] = rtrim($value); + } + } + break; + case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES): + $tmp_row = array(); + foreach ($row as $key => $value) { + if (is_string($value)) { + $value = rtrim($value); + } + $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value; + } + $row = $tmp_row; + break; + case (MDB2_PORTABILITY_EMPTY_TO_NULL + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES): + $tmp_row = array(); + foreach ($row as $key => $value) { + if ($value === '') { + $value = null; + } + $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value; + } + $row = $tmp_row; + break; + case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_EMPTY_TO_NULL + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES): + $tmp_row = array(); + foreach ($row as $key => $value) { + if ($value === '') { + $value = null; + } elseif (is_string($value)) { + $value = rtrim($value); + } + $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value; + } + $row = $tmp_row; + break; + } + } + + // }}} + // {{{ function &loadModule($module, $property = null, $phptype_specific = null) + + /** + * loads a module + * + * @param string name of the module that should be loaded + * (only used for error messages) + * @param string name of the property into which the class will be loaded + * @param bool if the class to load for the module is specific to the + * phptype + * + * @return object on success a reference to the given module is returned + * and on failure a PEAR error + * + * @access public + */ + function &loadModule($module, $property = null, $phptype_specific = null) + { + if (!$property) { + $property = strtolower($module); + } + + if (!isset($this->{$property})) { + $version = $phptype_specific; + if ($phptype_specific !== false) { + $version = true; + $class_name = 'MDB2_Driver_'.$module.'_'.$this->phptype; + $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php'; + } + if ($phptype_specific === false + || (!MDB2::classExists($class_name) && !MDB2::fileExists($file_name)) + ) { + $version = false; + $class_name = 'MDB2_'.$module; + $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php'; + } + + $err = MDB2::loadClass($class_name, $this->getOption('debug')); + if (PEAR::isError($err)) { + return $err; + } + + // load module in a specific version + if ($version) { + if (method_exists($class_name, 'getClassName')) { + $class_name_new = call_user_func(array($class_name, 'getClassName'), $this->db_index); + if ($class_name != $class_name_new) { + $class_name = $class_name_new; + $err = MDB2::loadClass($class_name, $this->getOption('debug')); + if (PEAR::isError($err)) { + return $err; + } + } + } + } + + if (!MDB2::classExists($class_name)) { + $err =& $this->raiseError(MDB2_ERROR_LOADMODULE, null, null, + "unable to load module '$module' into property '$property'", __FUNCTION__); + return $err; + } + $this->{$property} = new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; + if ($version) { + // this will be used in the connect method to determine if the module + // needs to be loaded with a different version if the server + // version changed in between connects + $this->loaded_version_modules[] = $property; + } + } + + return $this->{$property}; + } + + // }}} + // {{{ function __call($method, $params) + + /** + * Calls a module method using the __call magic method + * + * @param string Method name. + * @param array Arguments. + * + * @return mixed Returned value. + */ + function __call($method, $params) + { + $module = null; + if (preg_match('/^([a-z]+)([A-Z])(.*)$/', $method, $match) + && isset($this->options['modules'][$match[1]]) + ) { + $module = $this->options['modules'][$match[1]]; + $method = strtolower($match[2]).$match[3]; + if (!isset($this->modules[$module]) || !is_object($this->modules[$module])) { + $result =& $this->loadModule($module); + if (PEAR::isError($result)) { + return $result; + } + } + } else { + foreach ($this->modules as $key => $foo) { + if (is_object($this->modules[$key]) + && method_exists($this->modules[$key], $method) + ) { + $module = $key; + break; + } + } + } + if (!is_null($module)) { + return call_user_func_array(array(&$this->modules[$module], $method), $params); + } + trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $method), E_USER_ERROR); + } + + // }}} + // {{{ function beginTransaction($savepoint = null) + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'transactions are not supported', __FUNCTION__); + } + + // }}} + // {{{ function commit($savepoint = null) + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'commiting transactions is not supported', __FUNCTION__); + } + + // }}} + // {{{ function rollback($savepoint = null) + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'rolling back transactions is not supported', __FUNCTION__); + } + + // }}} + // {{{ function inTransaction($ignore_nested = false) + + /** + * If a transaction is currently open. + * + * @param bool if the nested transaction count should be ignored + * @return int|bool - an integer with the nesting depth is returned if a + * nested transaction is open + * - true is returned for a normal open transaction + * - false is returned if no transaction is open + * + * @access public + */ + function inTransaction($ignore_nested = false) + { + if (!$ignore_nested && isset($this->nested_transaction_counter)) { + return $this->nested_transaction_counter; + } + return $this->in_transaction; + } + + // }}} + // {{{ function setTransactionIsolation($isolation) + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @param array some transaction options: + * 'wait' => 'WAIT' | 'NO WAIT' + * 'rw' => 'READ WRITE' | 'READ ONLY' + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation, $options = array()) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level setting is not supported', __FUNCTION__); + } + + // }}} + // {{{ function beginNestedTransaction($savepoint = false) + + /** + * Start a nested transaction. + * + * @return mixed MDB2_OK on success/savepoint name, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function beginNestedTransaction() + { + if ($this->in_transaction) { + ++$this->nested_transaction_counter; + $savepoint = sprintf($this->options['savepoint_format'], $this->nested_transaction_counter); + if ($this->supports('savepoints') && $savepoint) { + return $this->beginTransaction($savepoint); + } + return MDB2_OK; + } + $this->has_transaction_error = false; + $result = $this->beginTransaction(); + $this->nested_transaction_counter = 1; + return $result; + } + + // }}} + // {{{ function completeNestedTransaction($force_rollback = false, $release = false) + + /** + * Finish a nested transaction by rolling back if an error occured or + * committing otherwise. + * + * @param bool if the transaction should be rolled back regardless + * even if no error was set within the nested transaction + * @return mixed MDB_OK on commit/counter decrementing, false on rollback + * and a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function completeNestedTransaction($force_rollback = false) + { + if ($this->nested_transaction_counter > 1) { + $savepoint = sprintf($this->options['savepoint_format'], $this->nested_transaction_counter); + if ($this->supports('savepoints') && $savepoint) { + if ($force_rollback || $this->has_transaction_error) { + $result = $this->rollback($savepoint); + if (!PEAR::isError($result)) { + $result = false; + $this->has_transaction_error = false; + } + } else { + $result = $this->commit($savepoint); + } + } else { + $result = MDB2_OK; + } + --$this->nested_transaction_counter; + return $result; + } + + $this->nested_transaction_counter = null; + $result = MDB2_OK; + + // transaction has not yet been rolled back + if ($this->in_transaction) { + if ($force_rollback || $this->has_transaction_error) { + $result = $this->rollback(); + if (!PEAR::isError($result)) { + $result = false; + } + } else { + $result = $this->commit(); + } + } + $this->has_transaction_error = false; + return $result; + } + + // }}} + // {{{ function failNestedTransaction($error = null, $immediately = false) + + /** + * Force setting nested transaction to failed. + * + * @param mixed value to return in getNestededTransactionError() + * @param bool if the transaction should be rolled back immediately + * @return bool MDB2_OK + * + * @access public + * @since 2.1.1 + */ + function failNestedTransaction($error = null, $immediately = false) + { + if (is_null($error)) { + $error = $this->has_transaction_error ? $this->has_transaction_error : true; + } elseif (!$error) { + $error = true; + } + $this->has_transaction_error = $error; + if (!$immediately) { + return MDB2_OK; + } + return $this->rollback(); + } + + // }}} + // {{{ function getNestedTransactionError() + + /** + * The first error that occured since the transaction start. + * + * @return MDB2_Error|bool MDB2 error object if an error occured or false. + * + * @access public + * @since 2.1.1 + */ + function getNestedTransactionError() + { + return $this->has_transaction_error; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return true on success, MDB2 Error Object on failure + */ + function connect() + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ setCharset($charset, $connection = null) + + /** + * Set the charset on the current connection + * + * @param string charset + * @param resource connection handle + * + * @return true on success, MDB2 Error Object on failure + */ + function setCharset($charset, $connection = null) + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function disconnect($force = true) + + /** + * Log out and disconnect from the database. + * + * @param bool if the disconnect should be forced even if the + * connection is opened persistently + * + * @return mixed true on success, false if not connected and error + * object on error + * + * @access public + */ + function disconnect($force = true) + { + $this->connection = 0; + $this->connected_dsn = array(); + $this->connected_database_name = ''; + $this->opened_persistent = null; + $this->connected_server_info = ''; + $this->in_transaction = null; + $this->nested_transaction_counter = null; + return MDB2_OK; + } + + // }}} + // {{{ function setDatabase($name) + + /** + * Select a different database + * + * @param string name of the database that should be selected + * + * @return string name of the database previously connected to + * + * @access public + */ + function setDatabase($name) + { + $previous_database_name = (isset($this->database_name)) ? $this->database_name : ''; + $this->database_name = $name; + if (!empty($this->connected_database_name) && ($this->connected_database_name != $this->database_name)) { + $this->disconnect(false); + } + return $previous_database_name; + } + + // }}} + // {{{ function getDatabase() + + /** + * Get the current database + * + * @return string name of the database + * + * @access public + */ + function getDatabase() + { + return $this->database_name; + } + + // }}} + // {{{ function setDSN($dsn) + + /** + * set the DSN + * + * @param mixed DSN string or array + * + * @return MDB2_OK + * + * @access public + */ + function setDSN($dsn) + { + $dsn_default = $GLOBALS['_MDB2_dsninfo_default']; + $dsn = MDB2::parseDSN($dsn); + if (array_key_exists('database', $dsn)) { + $this->database_name = $dsn['database']; + unset($dsn['database']); + } + $this->dsn = array_merge($dsn_default, $dsn); + return $this->disconnect(false); + } + + // }}} + // {{{ function getDSN($type = 'string', $hidepw = false) + + /** + * return the DSN as a string + * + * @param string format to return ("array", "string") + * @param string string to hide the password with + * + * @return mixed DSN in the chosen type + * + * @access public + */ + function getDSN($type = 'string', $hidepw = false) + { + $dsn = array_merge($GLOBALS['_MDB2_dsninfo_default'], $this->dsn); + $dsn['phptype'] = $this->phptype; + $dsn['database'] = $this->database_name; + if ($hidepw) { + $dsn['password'] = $hidepw; + } + switch ($type) { + // expand to include all possible options + case 'string': + $dsn = $dsn['phptype']. + ($dsn['dbsyntax'] ? ('('.$dsn['dbsyntax'].')') : ''). + '://'.$dsn['username'].':'. + $dsn['password'].'@'.$dsn['hostspec']. + ($dsn['port'] ? (':'.$dsn['port']) : ''). + '/'.$dsn['database']; + break; + case 'array': + default: + break; + } + return $dsn; + } + + // }}} + // {{{ function &standaloneQuery($query, $types = null, $is_manip = false) + + /** + * execute a query as database administrator + * + * @param string the SQL query + * @param mixed array that contains the types of the columns in + * the result set + * @param bool if the query is a manipulation query + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $result =& $this->_doQuery($query, $is_manip, $connection, false); + if (PEAR::isError($result)) { + return $result; + } + + if ($is_manip) { + $affected_rows = $this->_affectedRows($connection, $result); + return $affected_rows; + } + $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset); + return $result; + } + + // }}} + // {{{ function _modifyQuery($query, $is_manip, $limit, $offset) + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string query to modify + * @param bool if it is a DML query + * @param int limit the number of rows + * @param int start reading from given offset + * + * @return string modified query + * + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + return $query; + } + + // }}} + // {{{ function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + + /** + * Execute a query + * @param string query + * @param bool if the query is a manipulation query + * @param resource connection handle + * @param string database name + * + * @return result or error object + * + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $err =& $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $err; + } + + // }}} + // {{{ function _affectedRows($connection, $result = null) + + /** + * Returns the number of rows affected + * + * @param resource result handle + * @param resource connection handle + * + * @return mixed MDB2 Error Object or the number of rows affected + * + * @access private + */ + function _affectedRows($connection, $result = null) + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function &exec($query) + + /** + * Execute a manipulation query to the database and return the number of affected rows + * + * @param string the SQL query + * + * @return mixed number of affected rows on success, a MDB2 error on failure + * + * @access public + */ + function &exec($query) + { + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, true, $limit, $offset); + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $result =& $this->_doQuery($query, true, $connection, $this->database_name); + if (PEAR::isError($result)) { + return $result; + } + + $affectedRows = $this->_affectedRows($connection, $result); + return $affectedRows; + } + + // }}} + // {{{ function &query($query, $types = null, $result_class = true, $result_wrap_class = false) + + /** + * Send a query to the database and return any results + * + * @param string the SQL query + * @param mixed array that contains the types of the columns in + * the result set + * @param mixed string which specifies which result class to use + * @param mixed string which specifies which class to wrap results in + * + * @return mixed an MDB2_Result handle on success, a MDB2 error on failure + * + * @access public + */ + function &query($query, $types = null, $result_class = true, $result_wrap_class = false) + { + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, false, $limit, $offset); + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $result =& $this->_doQuery($query, false, $connection, $this->database_name); + if (PEAR::isError($result)) { + return $result; + } + + $result =& $this->_wrapResult($result, $types, $result_class, $result_wrap_class, $limit, $offset); + return $result; + } + + // }}} + // {{{ function &_wrapResult($result, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null) + + /** + * wrap a result set into the correct class + * + * @param resource result handle + * @param mixed array that contains the types of the columns in + * the result set + * @param mixed string which specifies which result class to use + * @param mixed string which specifies which class to wrap results in + * @param string number of rows to select + * @param string first row to select + * + * @return mixed an MDB2_Result, a MDB2 error on failure + * + * @access protected + */ + function &_wrapResult($result, $types = array(), $result_class = true, + $result_wrap_class = false, $limit = null, $offset = null) + { + if ($types === true) { + if ($this->supports('result_introspection')) { + $this->loadModule('Reverse', null, true); + $tableInfo = $this->reverse->tableInfo($result); + if (PEAR::isError($tableInfo)) { + return $tableInfo; + } + $types = array(); + foreach ($tableInfo as $field) { + $types[] = $field['mdb2type']; + } + } else { + $types = null; + } + } + + if ($result_class === true) { + $result_class = $this->options['result_buffering'] + ? $this->options['buffered_result_class'] : $this->options['result_class']; + } + + if ($result_class) { + $class_name = sprintf($result_class, $this->phptype); + if (!MDB2::classExists($class_name)) { + $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'result class does not exist '.$class_name, __FUNCTION__); + return $err; + } + $result =& new $class_name($this, $result, $limit, $offset); + if (!MDB2::isResultCommon($result)) { + $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'result class is not extended from MDB2_Result_Common', __FUNCTION__); + return $err; + } + if (!empty($types)) { + $err = $result->setResultTypes($types); + if (PEAR::isError($err)) { + $result->free(); + return $err; + } + } + } + if ($result_wrap_class === true) { + $result_wrap_class = $this->options['result_wrap_class']; + } + if ($result_wrap_class) { + if (!MDB2::classExists($result_wrap_class)) { + $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'result wrap class does not exist '.$result_wrap_class, __FUNCTION__); + return $err; + } + $result = new $result_wrap_class($result, $this->fetchmode); + } + return $result; + } + + // }}} + // {{{ function getServerVersion($native = false) + + /** + * return version information about the server + * + * @param bool determines if the raw version string should be returned + * + * @return mixed array with version information or row string + * + * @access public + */ + function getServerVersion($native = false) + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function setLimit($limit, $offset = null) + + /** + * set the range of the next query + * + * @param string number of rows to select + * @param string first row to select + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function setLimit($limit, $offset = null) + { + if (!$this->supports('limit_queries')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'limit is not supported by this driver', __FUNCTION__); + } + $limit = (int)$limit; + if ($limit < 0) { + return $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'it was not specified a valid selected range row limit', __FUNCTION__); + } + $this->limit = $limit; + if (!is_null($offset)) { + $offset = (int)$offset; + if ($offset < 0) { + return $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'it was not specified a valid first selected range row', __FUNCTION__); + } + $this->offset = $offset; + } + return MDB2_OK; + } + + // }}} + // {{{ function subSelect($query, $type = false) + + /** + * simple subselect emulation: leaves the query untouched for all RDBMS + * that support subselects + * + * @param string the SQL query for the subselect that may only + * return a column + * @param string determines type of the field + * + * @return string the query + * + * @access public + */ + function subSelect($query, $type = false) + { + if ($this->supports('sub_selects') === true) { + return $query; + } + + if (!$this->supports('sub_selects')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + $col = $this->queryCol($query, $type); + if (PEAR::isError($col)) { + return $col; + } + if (!is_array($col) || count($col) == 0) { + return 'NULL'; + } + if ($type) { + $this->loadModule('Datatype', null, true); + return $this->datatype->implodeArray($col, $type); + } + return implode(', ', $col); + } + + // }}} + // {{{ function replace($table, $fields) + + /** + * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT + * query, except that if there is already a row in the table with the same + * key field values, the REPLACE query just updates its values instead of + * inserting a new row. + * + * The REPLACE type of query does not make part of the SQL standards. Since + * practically only MySQL and SQLite implement it natively, this type of + * query isemulated through this method for other DBMS using standard types + * of queries inside a transaction to assure the atomicity of the operation. + * + * @param string name of the table on which the REPLACE query will + * be executed. + * @param array associative array that describes the fields and the + * values that will be inserted or updated in the specified table. The + * indexes of the array are the names of all the fields of the table. + * The values of the array are also associative arrays that describe + * the values and other properties of the table fields. + * + * Here follows a list of field properties that need to be specified: + * + * value + * Value to be assigned to the specified field. This value may be + * of specified in database independent type format as this + * function can perform the necessary datatype conversions. + * + * Default: this property is required unless the Null property is + * set to 1. + * + * type + * Name of the type of the field. Currently, all types MDB2 + * are supported except for clob and blob. + * + * Default: no type conversion + * + * null + * bool property that indicates that the value for this field + * should be set to null. + * + * The default value for fields missing in INSERT queries may be + * specified the definition of a table. Often, the default value + * is already null, but since the REPLACE may be emulated using + * an UPDATE query, make sure that all fields of the table are + * listed in this function argument array. + * + * Default: 0 + * + * key + * bool property that indicates that this field should be + * handled as a primary key or at least as part of the compound + * unique index of the table that will determine the row that will + * updated if it exists or inserted a new row otherwise. + * + * This function will fail if no key field is specified or if the + * value of a key field is set to null because fields that are + * part of unique index they may not be null. + * + * Default: 0 + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function replace($table, $fields) + { + if (!$this->supports('replace')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'replace query is not supported', __FUNCTION__); + } + $count = count($fields); + $condition = $values = array(); + for ($colnum = 0, reset($fields); $colnum < $count; next($fields), $colnum++) { + $name = key($fields); + if (isset($fields[$name]['null']) && $fields[$name]['null']) { + $value = 'NULL'; + } else { + $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null; + $value = $this->quote($fields[$name]['value'], $type); + } + $values[$name] = $value; + if (isset($fields[$name]['key']) && $fields[$name]['key']) { + if ($value === 'NULL') { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'key value '.$name.' may not be NULL', __FUNCTION__); + } + $condition[] = $this->quoteIdentifier($name, true) . '=' . $value; + } + } + if (empty($condition)) { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'not specified which fields are keys', __FUNCTION__); + } + + $result = null; + $in_transaction = $this->in_transaction; + if (!$in_transaction && PEAR::isError($result = $this->beginTransaction())) { + return $result; + } + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $condition = ' WHERE '.implode(' AND ', $condition); + $query = 'DELETE FROM ' . $this->quoteIdentifier($table, true) . $condition; + $result =& $this->_doQuery($query, true, $connection); + if (!PEAR::isError($result)) { + $affected_rows = $this->_affectedRows($connection, $result); + $insert = ''; + foreach ($values as $key => $value) { + $insert .= ($insert?', ':'') . $this->quoteIdentifier($key, true); + } + $values = implode(', ', $values); + $query = 'INSERT INTO '. $this->quoteIdentifier($table, true) . "($insert) VALUES ($values)"; + $result =& $this->_doQuery($query, true, $connection); + if (!PEAR::isError($result)) { + $affected_rows += $this->_affectedRows($connection, $result);; + } + } + + if (!$in_transaction) { + if (PEAR::isError($result)) { + $this->rollback(); + } else { + $result = $this->commit(); + } + } + + if (PEAR::isError($result)) { + return $result; + } + + return $affected_rows; + } + + // }}} + // {{{ function &prepare($query, $types = null, $result_types = null, $lobs = array()) + + /** + * Prepares a query for multiple execution with execute(). + * With some database backends, this is emulated. + * prepare() requires a generic query as string like + * 'INSERT INTO numbers VALUES(?,?)' or + * 'INSERT INTO numbers VALUES(:foo,:bar)'. + * The ? and :name and are placeholders which can be set using + * bindParam() and the query can be sent off using the execute() method. + * The allowed format for :name can be set with the 'bindname_format' option. + * + * @param string the query to prepare + * @param mixed array that contains the types of the placeholders + * @param mixed array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * @param mixed key (field) value (parameter) pair for all lob placeholders + * + * @return mixed resource handle for the prepared query on success, + * a MDB2 error on failure + * + * @access public + * @see bindParam, execute + */ + function &prepare($query, $types = null, $result_types = null, $lobs = array()) + { + $is_manip = ($result_types === MDB2_PREPARE_MANIP); + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $placeholder_type_guess = $placeholder_type = null; + $question = '?'; + $colon = ':'; + $positions = array(); + $position = 0; + $ignores = $this->sql_comments; + $ignores[] = $this->string_quoting; + $ignores[] = $this->identifier_quoting; + while ($position < strlen($query)) { + $q_position = strpos($query, $question, $position); + $c_position = strpos($query, $colon, $position); + if ($q_position && $c_position) { + $p_position = min($q_position, $c_position); + } elseif ($q_position) { + $p_position = $q_position; + } elseif ($c_position) { + $p_position = $c_position; + } else { + break; + } + if (is_null($placeholder_type)) { + $placeholder_type_guess = $query[$p_position]; + } + + $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position); + if (PEAR::isError($new_pos)) { + return $new_pos; + } + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + if ($query[$position] == $placeholder_type_guess) { + if (is_null($placeholder_type)) { + $placeholder_type = $query[$p_position]; + $question = $colon = $placeholder_type; + if (!empty($types) && is_array($types)) { + if ($placeholder_type == ':') { + if (is_int(key($types))) { + $types_tmp = $types; + $types = array(); + $count = -1; + } + } else { + $types = array_values($types); + } + } + } + if ($placeholder_type == ':') { + $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; + $parameter = preg_replace($regexp, '\\1', $query); + if ($parameter === '') { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'named parameter name must match "bindname_format" option', __FUNCTION__); + return $err; + } + $positions[$p_position] = $parameter; + $query = substr_replace($query, '?', $position, strlen($parameter)+1); + // use parameter name in type array + if (isset($count) && isset($types_tmp[++$count])) { + $types[$parameter] = $types_tmp[$count]; + } + } else { + $positions[$p_position] = count($positions); + } + $position = $p_position + 1; + } else { + $position = $p_position; + } + } + $class_name = 'MDB2_Statement_'.$this->phptype; + $statement = null; + $obj = new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)); + return $obj; + } + + // }}} + // {{{ function _skipDelimitedStrings($query, $position, $p_position) + + /** + * Utility method, used by prepare() to avoid replacing placeholders within delimited strings. + * Check if the placeholder is contained within a delimited string. + * If so, skip it and advance the position, otherwise return the current position, + * which is valid + * + * @param string $query + * @param integer $position current string cursor position + * @param integer $p_position placeholder position + * + * @return mixed integer $new_position on success + * MDB2_Error on failure + * + * @access protected + */ + function _skipDelimitedStrings($query, $position, $p_position) + { + $ignores = $this->sql_comments; + $ignores[] = $this->string_quoting; + $ignores[] = $this->identifier_quoting; + + foreach ($ignores as $ignore) { + if (!empty($ignore['start'])) { + if (is_int($start_quote = strpos($query, $ignore['start'], $position)) && $start_quote < $p_position) { + $end_quote = $start_quote; + do { + if (!is_int($end_quote = strpos($query, $ignore['end'], $end_quote + 1))) { + if ($ignore['end'] === "\n") { + $end_quote = strlen($query) - 1; + } else { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'query with an unterminated text string specified', __FUNCTION__); + return $err; + } + } + } while ($ignore['escape'] && $query[($end_quote - 1)] == $ignore['escape']); + $position = $end_quote + 1; + return $position; + } + } + } + return $position; + } + + // }}} + // {{{ function quote($value, $type = null, $quote = true) + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string text string value that is intended to be converted. + * @param string type to which the value should be converted to + * @param bool quote + * @param bool escape wildcards + * + * @return string text string that represents the given argument value in + * a DBMS specific format. + * + * @access public + */ + function quote($value, $type = null, $quote = true, $escape_wildcards = false) + { + $result = $this->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + return $this->datatype->quote($value, $type, $quote, $escape_wildcards); + } + + // }}} + // {{{ function getDeclaration($type, $name, $field) + + /** + * Obtain DBMS specific SQL code portion needed to declare + * of the given type + * + * @param string type to which the value should be converted to + * @param string name the field to be declared. + * @param string definition of the field + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * + * @access public + */ + function getDeclaration($type, $name, $field) + { + $result = $this->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + return $this->datatype->getDeclaration($type, $name, $field); + } + + // }}} + // {{{ function compareDefinition($current, $previous) + + /** + * Obtain an array of changes that may need to applied + * + * @param array new definition + * @param array old definition + * + * @return array containing all changes that will need to be applied + * + * @access public + */ + function compareDefinition($current, $previous) + { + $result = $this->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + return $this->datatype->compareDefinition($current, $previous); + } + + // }}} + // {{{ function supports($feature) + + /** + * Tell whether a DB implementation or its backend extension + * supports a given feature. + * + * @param string name of the feature (see the MDB2 class doc) + * + * @return bool|string if this DB implementation supports a given feature + * false means no, true means native, + * 'emulated' means emulated + * + * @access public + */ + function supports($feature) + { + if (array_key_exists($feature, $this->supported)) { + return $this->supported[$feature]; + } + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + "unknown support feature $feature", __FUNCTION__); + } + + // }}} + // {{{ function getSequenceName($sqn) + + /** + * adds sequence name formatting to a sequence name + * + * @param string name of the sequence + * + * @return string formatted sequence name + * + * @access public + */ + function getSequenceName($sqn) + { + return sprintf($this->options['seqname_format'], + preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn)); + } + + // }}} + // {{{ function getIndexName($idx) + + /** + * adds index name formatting to a index name + * + * @param string name of the index + * + * @return string formatted index name + * + * @access public + */ + function getIndexName($idx) + { + return sprintf($this->options['idxname_format'], + preg_replace('/[^a-z0-9_\$]/i', '_', $idx)); + } + + // }}} + // {{{ function nextID($seq_name, $ondemand = true) + + /** + * Returns the next free id of a sequence + * + * @param string name of the sequence + * @param bool when true missing sequences are automatic created + * + * @return mixed MDB2 Error Object or id + * + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function lastInsertID($table = null, $field = null) + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string name of the table into which a new row was inserted + * @param string name of the field into which a new row was inserted + * + * @return mixed MDB2 Error Object or id + * + * @access public + */ + function lastInsertID($table = null, $field = null) + { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function currID($seq_name) + + /** + * Returns the current id of a sequence + * + * @param string name of the sequence + * + * @return mixed MDB2 Error Object or id + * + * @access public + */ + function currID($seq_name) + { + $this->warnings[] = 'database does not support getting current + sequence value, the sequence value was incremented'; + return $this->nextID($seq_name); + } + + // }}} + // {{{ function queryOne($query, $type = null, $colnum = 0) + + /** + * Execute the specified query, fetch the value from the first column of + * the first row of the result set and then frees + * the result set. + * + * @param string the SELECT query statement to be executed. + * @param string optional argument that specifies the expected + * datatype of the result set field, so that an eventual conversion + * may be performed. The default datatype is text, meaning that no + * conversion is performed + * @param int the column number to fetch + * + * @return mixed MDB2_OK or field value on success, a MDB2 error on failure + * + * @access public + */ + function queryOne($query, $type = null, $colnum = 0) + { + $result = $this->query($query, $type); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $one = $result->fetchOne($colnum); + $result->free(); + return $one; + } + + // }}} + // {{{ function queryRow($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT) + + /** + * Execute the specified query, fetch the values from the first + * row of the result set into an array and then frees + * the result set. + * + * @param string the SELECT query statement to be executed. + * @param array optional array argument that specifies a list of + * expected datatypes of the result set columns, so that the eventual + * conversions may be performed. The default list of datatypes is + * empty, meaning that no conversion is performed. + * @param int how the array data should be indexed + * + * @return mixed MDB2_OK or data array on success, a MDB2 error on failure + * + * @access public + */ + function queryRow($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT) + { + $result = $this->query($query, $types); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $row = $result->fetchRow($fetchmode); + $result->free(); + return $row; + } + + // }}} + // {{{ function queryCol($query, $type = null, $colnum = 0) + + /** + * Execute the specified query, fetch the value from the first column of + * each row of the result set into an array and then frees the result set. + * + * @param string the SELECT query statement to be executed. + * @param string optional argument that specifies the expected + * datatype of the result set field, so that an eventual conversion + * may be performed. The default datatype is text, meaning that no + * conversion is performed + * @param int the row number to fetch + * + * @return mixed MDB2_OK or data array on success, a MDB2 error on failure + * + * @access public + */ + function queryCol($query, $type = null, $colnum = 0) + { + $result = $this->query($query, $type); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $col = $result->fetchCol($colnum); + $result->free(); + return $col; + } + + // }}} + // {{{ function queryAll($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, $force_array = false, $group = false) + + /** + * Execute the specified query, fetch all the rows of the result set into + * a two dimensional array and then frees the result set. + * + * @param string the SELECT query statement to be executed. + * @param array optional array argument that specifies a list of + * expected datatypes of the result set columns, so that the eventual + * conversions may be performed. The default list of datatypes is + * empty, meaning that no conversion is performed. + * @param int how the array data should be indexed + * @param bool if set to true, the $all will have the first + * column as its first dimension + * @param bool used only when the query returns exactly + * two columns. If true, the values of the returned array will be + * one-element arrays instead of scalars. + * @param bool if true, the values of the returned array is + * wrapped in another array. If the same key value (in the first + * column) repeats itself, the values will be appended to this array + * instead of overwriting the existing values. + * + * @return mixed MDB2_OK or data array on success, a MDB2 error on failure + * + * @access public + */ + function queryAll($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT, + $rekey = false, $force_array = false, $group = false) + { + $result = $this->query($query, $types); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $all = $result->fetchAll($fetchmode, $rekey, $force_array, $group); + $result->free(); + return $all; + } + + // }}} +} + +// }}} +// {{{ class MDB2_Result + +/** + * The dummy class that all user space result classes should extend from + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Result +{ +} + +// }}} +// {{{ class MDB2_Result_Common extends MDB2_Result + +/** + * The common result class for MDB2 result objects + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Result_Common extends MDB2_Result +{ + // {{{ Variables (Properties) + + var $db; + var $result; + var $rownum = -1; + var $types = array(); + var $values = array(); + var $offset; + var $offset_count = 0; + var $limit; + var $column_names; + + // }}} + // {{{ constructor: function __construct(&$db, &$result, $limit = 0, $offset = 0) + + /** + * Constructor + */ + function __construct(&$db, &$result, $limit = 0, $offset = 0) + { + $this->db =& $db; + $this->result =& $result; + $this->offset = $offset; + $this->limit = max(0, $limit - 1); + } + + // }}} + // {{{ function MDB2_Result_Common(&$db, &$result, $limit = 0, $offset = 0) + + /** + * PHP 4 Constructor + */ + function MDB2_Result_Common(&$db, &$result, $limit = 0, $offset = 0) + { + $this->__construct($db, $result, $limit, $offset); + } + + // }}} + // {{{ function setResultTypes($types) + + /** + * Define the list of types to be associated with the columns of a given + * result set. + * + * This function may be called before invoking fetchRow(), fetchOne(), + * fetchCol() and fetchAll() so that the necessary data type + * conversions are performed on the data to be retrieved by them. If this + * function is not called, the type of all result set columns is assumed + * to be text, thus leading to not perform any conversions. + * + * @param array variable that lists the + * data types to be expected in the result set columns. If this array + * contains less types than the number of columns that are returned + * in the result set, the remaining columns are assumed to be of the + * type text. Currently, the types clob and blob are not fully + * supported. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function setResultTypes($types) + { + $load = $this->db->loadModule('Datatype', null, true); + if (PEAR::isError($load)) { + return $load; + } + $types = $this->db->datatype->checkResultTypes($types); + if (PEAR::isError($types)) { + return $types; + } + $this->types = $types; + return MDB2_OK; + } + + // }}} + // {{{ function seek($rownum = 0) + + /** + * Seek to a specific row in a result set + * + * @param int number of the row where the data can be found + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function seek($rownum = 0) + { + $target_rownum = $rownum - 1; + if ($this->rownum > $target_rownum) { + return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'seeking to previous rows not implemented', __FUNCTION__); + } + while ($this->rownum < $target_rownum) { + $this->fetchRow(); + } + return MDB2_OK; + } + + // }}} + // {{{ function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + + /** + * Fetch and return a row of data + * + * @param int how the array data should be indexed + * @param int number of the row where the data can be found + * + * @return int data array on success, a MDB2 error on failure + * + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + $err =& $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $err; + } + + // }}} + // {{{ function fetchOne($colnum = 0) + + /** + * fetch single column from the next row from a result set + * + * @param int the column number to fetch + * @param int number of the row where the data can be found + * + * @return string data on success, a MDB2 error on failure + * + * @access public + */ + function fetchOne($colnum = 0, $rownum = null) + { + $fetchmode = is_numeric($colnum) ? MDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC; + $row = $this->fetchRow($fetchmode, $rownum); + if (!is_array($row) || PEAR::isError($row)) { + return $row; + } + if (!array_key_exists($colnum, $row)) { + return $this->db->raiseError(MDB2_ERROR_TRUNCATED, null, null, + 'column is not defined in the result set: '.$colnum, __FUNCTION__); + } + return $row[$colnum]; + } + + // }}} + // {{{ function fetchCol($colnum = 0) + + /** + * Fetch and return a column from the current row pointer position + * + * @param int the column number to fetch + * + * @return mixed data array on success, a MDB2 error on failure + * + * @access public + */ + function fetchCol($colnum = 0) + { + $column = array(); + $fetchmode = is_numeric($colnum) ? MDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC; + $row = $this->fetchRow($fetchmode); + if (is_array($row)) { + if (!array_key_exists($colnum, $row)) { + return $this->db->raiseError(MDB2_ERROR_TRUNCATED, null, null, + 'column is not defined in the result set: '.$colnum, __FUNCTION__); + } + do { + $column[] = $row[$colnum]; + } while (is_array($row = $this->fetchRow($fetchmode))); + } + if (PEAR::isError($row)) { + return $row; + } + return $column; + } + + // }}} + // {{{ function fetchAll($fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, $force_array = false, $group = false) + + /** + * Fetch and return all rows from the current row pointer position + * + * @param int $fetchmode the fetch mode to use: + * + MDB2_FETCHMODE_ORDERED + * + MDB2_FETCHMODE_ASSOC + * + MDB2_FETCHMODE_ORDERED | MDB2_FETCHMODE_FLIPPED + * + MDB2_FETCHMODE_ASSOC | MDB2_FETCHMODE_FLIPPED + * @param bool if set to true, the $all will have the first + * column as its first dimension + * @param bool used only when the query returns exactly + * two columns. If true, the values of the returned array will be + * one-element arrays instead of scalars. + * @param bool if true, the values of the returned array is + * wrapped in another array. If the same key value (in the first + * column) repeats itself, the values will be appended to this array + * instead of overwriting the existing values. + * + * @return mixed data array on success, a MDB2 error on failure + * + * @access public + * @see getAssoc() + */ + function fetchAll($fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, + $force_array = false, $group = false) + { + $all = array(); + $row = $this->fetchRow($fetchmode); + if (PEAR::isError($row)) { + return $row; + } elseif (!$row) { + return $all; + } + + $shift_array = $rekey ? false : null; + if (!is_null($shift_array)) { + if (is_object($row)) { + $colnum = count(get_object_vars($row)); + } else { + $colnum = count($row); + } + if ($colnum < 2) { + return $this->db->raiseError(MDB2_ERROR_TRUNCATED, null, null, + 'rekey feature requires atleast 2 column', __FUNCTION__); + } + $shift_array = (!$force_array && $colnum == 2); + } + + if ($rekey) { + do { + if (is_object($row)) { + $arr = get_object_vars($row); + $key = reset($arr); + unset($row->{$key}); + } else { + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $key = reset($row); + unset($row[key($row)]); + } else { + $key = array_shift($row); + } + if ($shift_array) { + $row = array_shift($row); + } + } + if ($group) { + $all[$key][] = $row; + } else { + $all[$key] = $row; + } + } while (($row = $this->fetchRow($fetchmode))); + } elseif ($fetchmode & MDB2_FETCHMODE_FLIPPED) { + do { + foreach ($row as $key => $val) { + $all[$key][] = $val; + } + } while (($row = $this->fetchRow($fetchmode))); + } else { + do { + $all[] = $row; + } while (($row = $this->fetchRow($fetchmode))); + } + + return $all; + } + + // }}} + // {{{ function rowCount() + /** + * Returns the actual row number that was last fetched (count from 0) + * @return int + * + * @access public + */ + function rowCount() + { + return $this->rownum + 1; + } + + // }}} + // {{{ function numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * + * @access public + */ + function numRows() + { + return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function nextResult() + + /** + * Move the internal result pointer to the next available result + * + * @return true on success, false if there is no more result set or an error object on failure + * + * @access public + */ + function nextResult() + { + return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result or + * from the cache. + * + * @param bool If set to true the values are the column names, + * otherwise the names of the columns are the keys. + * @return mixed Array variable that holds the names of columns or an + * MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * + * @access public + */ + function getColumnNames($flip = false) + { + if (!isset($this->column_names)) { + $result = $this->_getColumnNames(); + if (PEAR::isError($result)) { + return $result; + } + $this->column_names = $result; + } + if ($flip) { + return array_flip($this->column_names); + } + return $this->column_names; + } + + // }}} + // {{{ function _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * + * @access private + */ + function _getColumnNames() + { + return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + * + * @access public + */ + function numCols() + { + return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ function getResource() + + /** + * return the resource associated with the result object + * + * @return resource + * + * @access public + */ + function getResource() + { + return $this->result; + } + + // }}} + // {{{ function bindColumn($column, &$value, $type = null) + + /** + * Set bind variable to a column. + * + * @param int column number or name + * @param mixed variable reference + * @param string specifies the type of the field + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function bindColumn($column, &$value, $type = null) + { + if (!is_numeric($column)) { + $column_names = $this->getColumnNames(); + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($this->db->options['field_case'] == CASE_LOWER) { + $column = strtolower($column); + } else { + $column = strtoupper($column); + } + } + $column = $column_names[$column]; + } + $this->values[$column] =& $value; + if (!is_null($type)) { + $this->types[$column] = $type; + } + return MDB2_OK; + } + + // }}} + // {{{ function _assignBindColumns($row) + + /** + * Bind a variable to a value in the result row. + * + * @param array row data + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access private + */ + function _assignBindColumns($row) + { + $row = array_values($row); + foreach ($row as $column => $value) { + if (array_key_exists($column, $this->values)) { + $this->values[$column] = $value; + } + } + return MDB2_OK; + } + + // }}} + // {{{ function free() + + /** + * Free the internal resources associated with result. + * + * @return bool true on success, false if result is invalid + * + * @access public + */ + function free() + { + $this->result = false; + return MDB2_OK; + } + + // }}} +} + +// }}} +// {{{ class MDB2_Row + +/** + * The simple class that accepts row data as an array + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Row +{ + // {{{ constructor: function __construct(&$row) + + /** + * constructor + * + * @param resource row data as array + */ + function __construct(&$row) + { + foreach ($row as $key => $value) { + $this->$key = &$row[$key]; + } + } + + // }}} + // {{{ function MDB2_Row(&$row) + + /** + * PHP 4 Constructor + * + * @param resource row data as array + */ + function MDB2_Row(&$row) + { + $this->__construct($row); + } + + // }}} +} + +// }}} +// {{{ class MDB2_Statement_Common + +/** + * The common statement class for MDB2 statement objects + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Statement_Common +{ + // {{{ Variables (Properties) + + var $db; + var $statement; + var $query; + var $result_types; + var $types; + var $values = array(); + var $limit; + var $offset; + var $is_manip; + + // }}} + // {{{ constructor: function __construct(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) + + /** + * Constructor + */ + function __construct(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) + { + $this->db =& $db; + $this->statement =& $statement; + $this->positions = $positions; + $this->query = $query; + $this->types = (array)$types; + $this->result_types = (array)$result_types; + $this->limit = $limit; + $this->is_manip = $is_manip; + $this->offset = $offset; + } + + // }}} + // {{{ function MDB2_Statement_Common(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) + + /** + * PHP 4 Constructor + */ + function MDB2_Statement_Common(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null) + { + $this->__construct($db, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + } + + // }}} + // {{{ function bindValue($parameter, &$value, $type = null) + + /** + * Set the value of a parameter of a prepared query. + * + * @param int the order number of the parameter in the query + * statement. The order number of the first parameter is 1. + * @param mixed value that is meant to be assigned to specified + * parameter. The type of the value depends on the $type argument. + * @param string specifies the type of the field + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function bindValue($parameter, $value, $type = null) + { + if (!is_numeric($parameter)) { + $parameter = preg_replace('/^:(.*)$/', '\\1', $parameter); + } + if (!in_array($parameter, $this->positions)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $this->values[$parameter] = $value; + if (!is_null($type)) { + $this->types[$parameter] = $type; + } + return MDB2_OK; + } + + // }}} + // {{{ function bindValueArray($values, $types = null) + + /** + * Set the values of multiple a parameter of a prepared query in bulk. + * + * @param array specifies all necessary information + * for bindValue() the array elements must use keys corresponding to + * the number of the position of the parameter. + * @param array specifies the types of the fields + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @see bindParam() + */ + function bindValueArray($values, $types = null) + { + $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null); + $parameters = array_keys($values); + foreach ($parameters as $key => $parameter) { + $this->db->pushErrorHandling(PEAR_ERROR_RETURN); + $this->db->expectError(MDB2_ERROR_NOT_FOUND); + $err = $this->bindValue($parameter, $values[$parameter], $types[$key]); + $this->db->popExpect(); + $this->db->popErrorHandling(); + if (PEAR::isError($err)) { + if ($err->getCode() == MDB2_ERROR_NOT_FOUND) { + //ignore (extra value for missing placeholder) + continue; + } + return $err; + } + } + return MDB2_OK; + } + + // }}} + // {{{ function bindParam($parameter, &$value, $type = null) + + /** + * Bind a variable to a parameter of a prepared query. + * + * @param int the order number of the parameter in the query + * statement. The order number of the first parameter is 1. + * @param mixed variable that is meant to be bound to specified + * parameter. The type of the value depends on the $type argument. + * @param string specifies the type of the field + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function bindParam($parameter, &$value, $type = null) + { + if (!is_numeric($parameter)) { + $parameter = preg_replace('/^:(.*)$/', '\\1', $parameter); + } + if (!in_array($parameter, $this->positions)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $this->values[$parameter] =& $value; + if (!is_null($type)) { + $this->types[$parameter] = $type; + } + return MDB2_OK; + } + + // }}} + // {{{ function bindParamArray(&$values, $types = null) + + /** + * Bind the variables of multiple a parameter of a prepared query in bulk. + * + * @param array specifies all necessary information + * for bindParam() the array elements must use keys corresponding to + * the number of the position of the parameter. + * @param array specifies the types of the fields + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @see bindParam() + */ + function bindParamArray(&$values, $types = null) + { + $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null); + $parameters = array_keys($values); + foreach ($parameters as $key => $parameter) { + $err = $this->bindParam($parameter, $values[$parameter], $types[$key]); + if (PEAR::isError($err)) { + return $err; + } + } + return MDB2_OK; + } + + // }}} + // {{{ function &execute($values = null, $result_class = true, $result_wrap_class = false) + + /** + * Execute a prepared query statement. + * + * @param array specifies all necessary information + * for bindParam() the array elements must use keys corresponding to + * the number of the position of the parameter. + * @param mixed specifies which result class to use + * @param mixed specifies which class to wrap results in + * + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function &execute($values = null, $result_class = true, $result_wrap_class = false) + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + + $values = (array)$values; + if (!empty($values)) { + $err = $this->bindValueArray($values); + if (PEAR::isError($err)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Binding Values failed with message: ' . $err->getMessage(), __FUNCTION__); + } + } + $result =& $this->_execute($result_class, $result_wrap_class); + return $result; + } + + // }}} + // {{{ function &_execute($result_class = true, $result_wrap_class = false) + + /** + * Execute a prepared query statement helper method. + * + * @param mixed specifies which result class to use + * @param mixed specifies which class to wrap results in + * + * @return mixed MDB2_Result or integer on success, a MDB2 error on failure + * + * @access private + */ + function &_execute($result_class = true, $result_wrap_class = false) + { + $this->last_query = $this->query; + $query = ''; + $last_position = 0; + foreach ($this->positions as $current_position => $parameter) { + if (!array_key_exists($parameter, $this->values)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $value = $this->values[$parameter]; + $query.= substr($this->query, $last_position, $current_position - $last_position); + if (!isset($value)) { + $value_quoted = 'NULL'; + } else { + $type = !empty($this->types[$parameter]) ? $this->types[$parameter] : null; + $value_quoted = $this->db->quote($value, $type); + if (PEAR::isError($value_quoted)) { + return $value_quoted; + } + } + $query.= $value_quoted; + $last_position = $current_position + 1; + } + $query.= substr($this->query, $last_position); + + $this->db->offset = $this->offset; + $this->db->limit = $this->limit; + if ($this->is_manip) { + $result = $this->db->exec($query); + } else { + $result =& $this->db->query($query, $this->result_types, $result_class, $result_wrap_class); + } + return $result; + } + + // }}} + // {{{ function free() + + /** + * Release resources allocated for the specified prepared query. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function free() + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + + $this->statement = null; + $this->positions = null; + $this->query = null; + $this->types = null; + $this->result_types = null; + $this->limit = null; + $this->is_manip = null; + $this->offset = null; + $this->values = null; + + return MDB2_OK; + } + + // }}} +} + +// }}} +// {{{ class MDB2_Module_Common + +/** + * The common modules class for MDB2 module objects + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Module_Common +{ + // {{{ Variables (Properties) + + /** + * contains the key to the global MDB2 instance array of the associated + * MDB2 instance + * + * @var int + * @access protected + */ + var $db_index; + + // }}} + // {{{ constructor: function __construct($db_index) + + /** + * Constructor + */ + function __construct($db_index) + { + $this->db_index = $db_index; + } + + // }}} + // {{{ function MDB2_Module_Common($db_index) + + /** + * PHP 4 Constructor + */ + function MDB2_Module_Common($db_index) + { + $this->__construct($db_index); + } + + // }}} + // {{{ function &getDBInstance() + + /** + * Get the instance of MDB2 associated with the module instance + * + * @return object MDB2 instance or a MDB2 error on failure + * + * @access public + */ + function &getDBInstance() + { + if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + $result =& $GLOBALS['_MDB2_databases'][$this->db_index]; + } else { + $result =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'could not find MDB2 instance'); + } + return $result; + } + + // }}} +} + +// }}} +// {{{ function MDB2_closeOpenTransactions() + +/** + * Close any open transactions form persistent connections + * + * @return void + * + * @access public + */ + +function MDB2_closeOpenTransactions() +{ + reset($GLOBALS['_MDB2_databases']); + while (next($GLOBALS['_MDB2_databases'])) { + $key = key($GLOBALS['_MDB2_databases']); + if ($GLOBALS['_MDB2_databases'][$key]->opened_persistent + && $GLOBALS['_MDB2_databases'][$key]->in_transaction + ) { + $GLOBALS['_MDB2_databases'][$key]->rollback(); + } + } +} + +// }}} +// {{{ function MDB2_defaultDebugOutput(&$db, $scope, $message, $is_manip = null) + +/** + * default debug output handler + * + * @param object reference to an MDB2 database object + * @param string usually the method name that triggered the debug call: + * for example 'query', 'prepare', 'execute', 'parameters', + * 'beginTransaction', 'commit', 'rollback' + * @param string message that should be appended to the debug variable + * @param array contains context information about the debug() call + * common keys are: is_manip, time, result etc. + * + * @return void|string optionally return a modified message, this allows + * rewriting a query before being issued or prepared + * + * @access public + */ +function MDB2_defaultDebugOutput(&$db, $scope, $message, $context = array()) +{ + $db->debug_output.= $scope.'('.$db->db_index.'): '; + $db->debug_output.= $message.$db->getOption('log_line_break'); + return $message; +} + +// }}} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Date.php b/lib/Pear/MDB2/Date.php new file mode 100644 index 0000000..ce84654 --- /dev/null +++ b/lib/Pear/MDB2/Date.php @@ -0,0 +1,183 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Date.php,v 1.10 2006/03/01 12:15:32 lsmith Exp $ +// + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + */ + +/** + * Several methods to convert the MDB2 native timestamp format (ISO based) + * to and from data structures that are convenient to worth with in side of php. + * For more complex date arithmetic please take a look at the Date package in PEAR + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Date +{ + // {{{ mdbNow() + + /** + * return the current datetime + * + * @return string current datetime in the MDB2 format + * @access public + */ + function mdbNow() + { + return date('Y-m-d H:i:s'); + } + // }}} + + // {{{ mdbToday() + + /** + * return the current date + * + * @return string current date in the MDB2 format + * @access public + */ + function mdbToday() + { + return date('Y-m-d'); + } + // }}} + + // {{{ mdbTime() + + /** + * return the current time + * + * @return string current time in the MDB2 format + * @access public + */ + function mdbTime() + { + return date('H:i:s'); + } + // }}} + + // {{{ date2Mdbstamp() + + /** + * convert a date into a MDB2 timestamp + * + * @param int hour of the date + * @param int minute of the date + * @param int second of the date + * @param int month of the date + * @param int day of the date + * @param int year of the date + * + * @return string a valid MDB2 timestamp + * @access public + */ + function date2Mdbstamp($hour = null, $minute = null, $second = null, + $month = null, $day = null, $year = null) + { + return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1)); + } + // }}} + + // {{{ unix2Mdbstamp() + + /** + * convert a unix timestamp into a MDB2 timestamp + * + * @param int a valid unix timestamp + * + * @return string a valid MDB2 timestamp + * @access public + */ + function unix2Mdbstamp($unix_timestamp) + { + return date('Y-m-d H:i:s', $unix_timestamp); + } + // }}} + + // {{{ mdbstamp2Unix() + + /** + * convert a MDB2 timestamp into a unix timestamp + * + * @param int a valid MDB2 timestamp + * @return string unix timestamp with the time stored in the MDB2 format + * + * @access public + */ + function mdbstamp2Unix($mdb_timestamp) + { + $arr = MDB2_Date::mdbstamp2Date($mdb_timestamp); + + return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1); + } + // }}} + + // {{{ mdbstamp2Date() + + /** + * convert a MDB2 timestamp into an array containing all + * values necessary to pass to php's date() function + * + * @param int a valid MDB2 timestamp + * + * @return array with the time split + * @access public + */ + function mdbstamp2Date($mdb_timestamp) + { + list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) = + sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u"); + return $arr; + } + // }}} +} + +?> diff --git a/lib/Pear/MDB2/Driver/Datatype/Common.php b/lib/Pear/MDB2/Driver/Datatype/Common.php new file mode 100644 index 0000000..2134e64 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/Common.php @@ -0,0 +1,1824 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.137 2008/02/17 18:53:40 afz Exp $ + +require_once 'MDB2/LOB.php'; + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + */ + +/** + * MDB2_Driver_Common: Base class that is extended by each MDB2 driver + * + * To load this module in the MDB2 object: + * $mdb->loadModule('Datatype'); + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Datatype_Common extends MDB2_Module_Common +{ + var $valid_default_values = array( + 'text' => '', + 'boolean' => true, + 'integer' => 0, + 'decimal' => 0.0, + 'float' => 0.0, + 'timestamp' => '1970-01-01 00:00:00', + 'time' => '00:00:00', + 'date' => '1970-01-01', + 'clob' => '', + 'blob' => '', + ); + + /** + * contains all LOB objects created with this MDB2 instance + * @var array + * @access protected + */ + var $lobs = array(); + + // }}} + // {{{ getValidTypes() + + /** + * Get the list of valid types + * + * This function returns an array of valid types as keys with the values + * being possible default values for all native datatypes and mapped types + * for custom datatypes. + * + * @return mixed array on success, a MDB2 error on failure + * @access public + */ + function getValidTypes() + { + $types = $this->valid_default_values; + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (!empty($db->options['datatype_map'])) { + foreach ($db->options['datatype_map'] as $type => $mapped_type) { + if (array_key_exists($mapped_type, $types)) { + $types[$type] = $types[$mapped_type]; + } elseif (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type, 'mapped_type' => $mapped_type); + $default = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + $types[$type] = $default; + } + } + } + return $types; + } + + // }}} + // {{{ checkResultTypes() + + /** + * Define the list of types to be associated with the columns of a given + * result set. + * + * This function may be called before invoking fetchRow(), fetchOne() + * fetchCole() and fetchAll() so that the necessary data type + * conversions are performed on the data to be retrieved by them. If this + * function is not called, the type of all result set columns is assumed + * to be text, thus leading to not perform any conversions. + * + * @param array $types array variable that lists the + * data types to be expected in the result set columns. If this array + * contains less types than the number of columns that are returned + * in the result set, the remaining columns are assumed to be of the + * type text. Currently, the types clob and blob are not fully + * supported. + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function checkResultTypes($types) + { + $types = is_array($types) ? $types : array($types); + foreach ($types as $key => $type) { + if (!isset($this->valid_default_values[$type])) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (empty($db->options['datatype_map'][$type])) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + $type.' for '.$key.' is not a supported column type', __FUNCTION__); + } + } + } + return $types; + } + + // }}} + // {{{ _baseConvertResult() + + /** + * General type conversion method + * + * @param mixed $value reference to a value to be converted + * @param string $type specifies which type to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return object an MDB2 error on failure + * @access protected + */ + function _baseConvertResult($value, $type, $rtrim = true) + { + switch ($type) { + case 'text': + if ($rtrim) { + $value = rtrim($value); + } + return $value; + case 'integer': + return intval($value); + case 'boolean': + return !empty($value); + case 'decimal': + return $value; + case 'float': + return doubleval($value); + case 'date': + return $value; + case 'time': + return $value; + case 'timestamp': + return $value; + case 'clob': + case 'blob': + $this->lobs[] = array( + 'buffer' => null, + 'position' => 0, + 'lob_index' => null, + 'endOfLOB' => false, + 'resource' => $value, + 'value' => null, + 'loaded' => false, + ); + end($this->lobs); + $lob_index = key($this->lobs); + $this->lobs[$lob_index]['lob_index'] = $lob_index; + return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index, 'r+'); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_INVALID, null, null, + 'attempt to convert result value to an unknown type :' . $type, __FUNCTION__); + } + + // }}} + // {{{ convertResult() + + /** + * Convert a value to a RDBMS indipendent MDB2 type + * + * @param mixed $value value to be converted + * @param string $type specifies which type to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return mixed converted value + * @access public + */ + function convertResult($value, $type, $rtrim = true) + { + if (is_null($value)) { + return null; + } + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (!empty($db->options['datatype_map'][$type])) { + $type = $db->options['datatype_map'][$type]; + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type, 'value' => $value, 'rtrim' => $rtrim); + return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + } + } + return $this->_baseConvertResult($value, $type, $rtrim); + } + + // }}} + // {{{ convertResultRow() + + /** + * Convert a result row + * + * @param array $types + * @param array $row specifies the types to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return mixed MDB2_OK on success, an MDB2 error on failure + * @access public + */ + function convertResultRow($types, $row, $rtrim = true) + { + $types = $this->_sortResultFieldTypes(array_keys($row), $types); + foreach ($row as $key => $value) { + if (empty($types[$key])) { + continue; + } + $value = $this->convertResult($row[$key], $types[$key], $rtrim); + if (PEAR::isError($value)) { + return $value; + } + $row[$key] = $value; + } + return $row; + } + + // }}} + // {{{ _sortResultFieldTypes() + + /** + * convert a result row + * + * @param array $types + * @param array $row specifies the types to convert to + * @param bool $rtrim if to rtrim text values or not + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function _sortResultFieldTypes($columns, $types) + { + $n_cols = count($columns); + $n_types = count($types); + if ($n_cols > $n_types) { + for ($i= $n_cols - $n_types; $i >= 0; $i--) { + $types[] = null; + } + } + $sorted_types = array(); + foreach ($columns as $col) { + $sorted_types[$col] = null; + } + foreach ($types as $name => $type) { + if (array_key_exists($name, $sorted_types)) { + $sorted_types[$name] = $type; + unset($types[$name]); + } + } + // if there are left types in the array, fill the null values of the + // sorted array with them, in order. + if (count($types)) { + reset($types); + foreach (array_keys($sorted_types) as $k) { + if (is_null($sorted_types[$k])) { + $sorted_types[$k] = current($types); + next($types); + } + } + } + return $sorted_types; + } + + // }}} + // {{{ getDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare + * of the given type + * + * @param string $type type to which the value should be converted to + * @param string $name name the field to be declared. + * @param string $field definition of the field + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getDeclaration($type, $name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($db->options['datatype_map'][$type])) { + $type = $db->options['datatype_map'][$type]; + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type, 'name' => $name, 'field' => $field); + return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + } + $field['type'] = $type; + } + + if (!method_exists($this, "_get{$type}Declaration")) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'type not defined: '.$type, __FUNCTION__); + } + return $this->{"_get{$type}Declaration"}($name, $field); + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length']; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + return 'TEXT'; + case 'blob': + return 'TEXT'; + case 'integer': + return 'INT'; + case 'boolean': + return 'INT'; + case 'date': + return 'CHAR ('.strlen('YYYY-MM-DD').')'; + case 'time': + return 'CHAR ('.strlen('HH:MM:SS').')'; + case 'timestamp': + return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')'; + case 'float': + return 'TEXT'; + case 'decimal': + return 'TEXT'; + } + return ''; + } + + // }}} + // {{{ _getDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a generic type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * charset + * Text value with the default CHARACTER SET for this field. + * collation + * Text value with the default COLLATION for this field. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field, or a MDB2_Error on failure + * @access protected + */ + function _getDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $declaration_options = $db->datatype->_getDeclarationOptions($field); + if (PEAR::isError($declaration_options)) { + return $declaration_options; + } + return $name.' '.$this->getTypeDeclaration($field).$declaration_options; + } + + // }}} + // {{{ _getDeclarationOptions() + + /** + * Obtain DBMS specific SQL code portion needed to declare a generic type + * field to be used in statement like CREATE TABLE, without the field name + * and type values (ie. just the character set, default value, if the + * field is permitted to be NULL or not, and the collation options). + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Text value to be used as default for this field. + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * charset + * Text value with the default CHARACTER SET for this field. + * collation + * Text value with the default COLLATION for this field. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field's options. + * @access protected + */ + function _getDeclarationOptions($field) + { + $charset = empty($field['charset']) ? '' : + ' '.$this->_getCharsetFieldDeclaration($field['charset']); + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $default = ''; + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $valid_default_values = $this->getValidTypes(); + $field['default'] = $valid_default_values[$field['type']]; + if ($field['default'] === ''&& ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)) { + $field['default'] = ' '; + } + } + if (!is_null($field['default'])) { + $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']); + } + } + + $collation = empty($field['collation']) ? '' : + ' '.$this->_getCollationFieldDeclaration($field['collation']); + + return $charset.$default.$notnull.$collation; + } + + // }}} + // {{{ _getCharsetFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + function _getCharsetFieldDeclaration($charset) + { + return ''; + } + + // }}} + // {{{ _getCollationFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + function _getCollationFieldDeclaration($collation) + { + return ''; + } + + // }}} + // {{{ _getIntegerDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field should be + * declared as unsigned integer if possible. + * + * default + * Integer value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getIntegerDeclaration($name, $field) + { + if (!empty($field['unsigned'])) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; + } + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getTextDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getTextDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getCLOBDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an character + * large object type field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the large + * object field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function _getCLOBDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$notnull; + } + + // }}} + // {{{ _getBLOBDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an binary large + * object type field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the large + * object field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getBLOBDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$notnull; + } + + // }}} + // {{{ _getBooleanDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a boolean type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Boolean value to be used as default for this field. + * + * notnullL + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getBooleanDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getDateDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a date type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Date value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getDateDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getTimestampDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a timestamp + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Timestamp value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getTimestampDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getTimeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a time + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Time value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getTimeDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getFloatDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a float type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Float value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getFloatDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ _getDecimalDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare a decimal type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Decimal value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getDecimalDeclaration($name, $field) + { + return $this->_getDeclaration($name, $field); + } + + // }}} + // {{{ compareDefinition() + + /** + * Obtain an array of changes that may need to applied + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access public + */ + function compareDefinition($current, $previous) + { + $type = !empty($current['type']) ? $current['type'] : null; + + if (!method_exists($this, "_compare{$type}Definition")) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('current' => $current, 'previous' => $previous); + $change = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + return $change; + } + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'type "'.$current['type'].'" is not yet supported', __FUNCTION__); + } + + if (empty($previous['type']) || $previous['type'] != $type) { + return $current; + } + + $change = $this->{"_compare{$type}Definition"}($current, $previous); + + if ($previous['type'] != $type) { + $change['type'] = true; + } + + $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false; + $notnull = !empty($current['notnull']) ? $current['notnull'] : false; + if ($previous_notnull != $notnull) { + $change['notnull'] = true; + } + + $previous_default = array_key_exists('default', $previous) ? $previous['default'] : + ($previous_notnull ? '' : null); + $default = array_key_exists('default', $current) ? $current['default'] : + ($notnull ? '' : null); + if ($previous_default !== $default) { + $change['default'] = true; + } + + return $change; + } + + // }}} + // {{{ _compareIntegerDefinition() + + /** + * Obtain an array of changes that may need to applied to an integer field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareIntegerDefinition($current, $previous) + { + $change = array(); + $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false; + $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false; + if ($previous_unsigned != $unsigned) { + $change['unsigned'] = true; + } + $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false; + $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false; + if ($previous_autoincrement != $autoincrement) { + $change['autoincrement'] = true; + } + return $change; + } + + // }}} + // {{{ _compareTextDefinition() + + /** + * Obtain an array of changes that may need to applied to an text field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareTextDefinition($current, $previous) + { + $change = array(); + $previous_length = !empty($previous['length']) ? $previous['length'] : 0; + $length = !empty($current['length']) ? $current['length'] : 0; + if ($previous_length != $length) { + $change['length'] = true; + } + $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0; + $fixed = !empty($current['fixed']) ? $current['fixed'] : 0; + if ($previous_fixed != $fixed) { + $change['fixed'] = true; + } + return $change; + } + + // }}} + // {{{ _compareCLOBDefinition() + + /** + * Obtain an array of changes that may need to applied to an CLOB field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareCLOBDefinition($current, $previous) + { + return $this->_compareTextDefinition($current, $previous); + } + + // }}} + // {{{ _compareBLOBDefinition() + + /** + * Obtain an array of changes that may need to applied to an BLOB field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareBLOBDefinition($current, $previous) + { + return $this->_compareTextDefinition($current, $previous); + } + + // }}} + // {{{ _compareDateDefinition() + + /** + * Obtain an array of changes that may need to applied to an date field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareDateDefinition($current, $previous) + { + return array(); + } + + // }}} + // {{{ _compareTimeDefinition() + + /** + * Obtain an array of changes that may need to applied to an time field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareTimeDefinition($current, $previous) + { + return array(); + } + + // }}} + // {{{ _compareTimestampDefinition() + + /** + * Obtain an array of changes that may need to applied to an timestamp field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareTimestampDefinition($current, $previous) + { + return array(); + } + + // }}} + // {{{ _compareBooleanDefinition() + + /** + * Obtain an array of changes that may need to applied to an boolean field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareBooleanDefinition($current, $previous) + { + return array(); + } + + // }}} + // {{{ _compareFloatDefinition() + + /** + * Obtain an array of changes that may need to applied to an float field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareFloatDefinition($current, $previous) + { + return array(); + } + + // }}} + // {{{ _compareDecimalDefinition() + + /** + * Obtain an array of changes that may need to applied to an decimal field + * + * @param array $current new definition + * @param array $previous old definition + * @return array containing all changes that will need to be applied + * @access protected + */ + function _compareDecimalDefinition($current, $previous) + { + return array(); + } + + // }}} + // {{{ quote() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param string $type type to which the value should be converted to + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access public + */ + function quote($value, $type = null, $quote = true, $escape_wildcards = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (is_null($value) + || ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL) + ) { + if (!$quote) { + return null; + } + return 'NULL'; + } + + if (is_null($type)) { + switch (gettype($value)) { + case 'integer': + $type = 'integer'; + break; + case 'double': + // todo: default to decimal as float is quite unusual + // $type = 'float'; + $type = 'decimal'; + break; + case 'boolean': + $type = 'boolean'; + break; + case 'array': + $value = serialize($value); + case 'object': + $type = 'text'; + break; + default: + if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) { + $type = 'timestamp'; + } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) { + $type = 'time'; + } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { + $type = 'date'; + } else { + $type = 'text'; + } + break; + } + } elseif (!empty($db->options['datatype_map'][$type])) { + $type = $db->options['datatype_map'][$type]; + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards); + return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + } + } + + if (!method_exists($this, "_quote{$type}")) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'type not defined: '.$type, __FUNCTION__); + } + $value = $this->{"_quote{$type}"}($value, $quote, $escape_wildcards); + if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern'] + && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern'] + ) { + $value.= $this->patternEscapeString(); + } + return $value; + } + + // }}} + // {{{ _quoteInteger() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteInteger($value, $quote, $escape_wildcards) + { + return (int)$value; + } + + // }}} + // {{{ _quoteText() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that already contains any DBMS specific + * escaped character sequences. + * @access protected + */ + function _quoteText($value, $quote, $escape_wildcards) + { + if (!$quote) { + return $value; + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $value = $db->escape($value, $escape_wildcards); + if (PEAR::isError($value)) { + return $value; + } + return "'".$value."'"; + } + + // }}} + // {{{ _readFile() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _readFile($value) + { + $close = false; + if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { + $close = true; + if ($match[1] == 'file://') { + $value = $match[2]; + } + $value = @fopen($value, 'r'); + } + + if (is_resource($value)) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $fp = $value; + $value = ''; + while (!@feof($fp)) { + $value.= @fread($fp, $db->options['lob_buffer_length']); + } + if ($close) { + @fclose($fp); + } + } + + return $value; + } + + // }}} + // {{{ _quoteLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteLOB($value, $quote, $escape_wildcards) + { + $value = $this->_readFile($value); + if (PEAR::isError($value)) { + return $value; + } + return $this->_quoteText($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteCLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteCLOB($value, $quote, $escape_wildcards) + { + return $this->_quoteLOB($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteBLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteBLOB($value, $quote, $escape_wildcards) + { + return $this->_quoteLOB($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteBoolean() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteBoolean($value, $quote, $escape_wildcards) + { + return ($value ? 1 : 0); + } + + // }}} + // {{{ _quoteDate() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteDate($value, $quote, $escape_wildcards) + { + if ($value === 'CURRENT_DATE') { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) { + return $db->function->now('date'); + } + return 'CURRENT_DATE'; + } + return $this->_quoteText($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteTimestamp() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteTimestamp($value, $quote, $escape_wildcards) + { + if ($value === 'CURRENT_TIMESTAMP') { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) { + return $db->function->now('timestamp'); + } + return 'CURRENT_TIMESTAMP'; + } + return $this->_quoteText($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteTime() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteTime($value, $quote, $escape_wildcards) + { + if ($value === 'CURRENT_TIME') { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) { + return $db->function->now('time'); + } + return 'CURRENT_TIME'; + } + return $this->_quoteText($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteFloat() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteFloat($value, $quote, $escape_wildcards) + { + if (preg_match('/^(.*)e([-+])(\d+)$/i', $value, $matches)) { + $decimal = $this->_quoteDecimal($matches[1], $quote, $escape_wildcards); + $sign = $matches[2]; + $exponent = str_pad($matches[3], 2, '0', STR_PAD_LEFT); + $value = $decimal.'E'.$sign.$exponent; + } else { + $value = $this->_quoteDecimal($value, $quote, $escape_wildcards); + } + return $value; + } + + // }}} + // {{{ _quoteDecimal() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteDecimal($value, $quote, $escape_wildcards) + { + $value = (string)$value; + $value = preg_replace('/[^\d\.,\-+eE]/', '', $value); + if (preg_match('/[^\.\d]/', $value)) { + if (strpos($value, ',')) { + // 1000,00 + if (!strpos($value, '.')) { + // convert the last "," to a "." + $value = strrev(str_replace(',', '.', strrev($value))); + // 1.000,00 + } elseif (strpos($value, '.') && strpos($value, '.') < strpos($value, ',')) { + $value = str_replace('.', '', $value); + // convert the last "," to a "." + $value = strrev(str_replace(',', '.', strrev($value))); + // 1,000.00 + } else { + $value = str_replace(',', '', $value); + } + } + } + return $value; + } + + // }}} + // {{{ writeLOBToFile() + + /** + * retrieve LOB from the database + * + * @param resource $lob stream handle + * @param string $file name of the file into which the LOb should be fetched + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function writeLOBToFile($lob, $file) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) { + if ($match[1] == 'file://') { + $file = $match[2]; + } + } + + $fp = @fopen($file, 'wb'); + while (!@feof($lob)) { + $result = @fread($lob, $db->options['lob_buffer_length']); + $read = strlen($result); + if (@fwrite($fp, $result, $read) != $read) { + @fclose($fp); + return $db->raiseError(MDB2_ERROR, null, null, + 'could not write to the output file', __FUNCTION__); + } + } + @fclose($fp); + return MDB2_OK; + } + + // }}} + // {{{ _retrieveLOB() + + /** + * retrieve LOB from the database + * + * @param array $lob array + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function _retrieveLOB(&$lob) + { + if (is_null($lob['value'])) { + $lob['value'] = $lob['resource']; + } + $lob['loaded'] = true; + return MDB2_OK; + } + + // }}} + // {{{ readLOB() + + /** + * Read data from large object input stream. + * + * @param resource $lob stream handle + * @param string $data reference to a variable that will hold data + * to be read from the large object input stream + * @param integer $length value that indicates the largest ammount ofdata + * to be read from the large object input stream. + * @return mixed the effective number of bytes read from the large object + * input stream on sucess or an MDB2 error object. + * @access public + * @see endOfLOB() + */ + function _readLOB($lob, $length) + { + return substr($lob['value'], $lob['position'], $length); + } + + // }}} + // {{{ _endOfLOB() + + /** + * Determine whether it was reached the end of the large object and + * therefore there is no more data to be read for the its input stream. + * + * @param array $lob array + * @return mixed true or false on success, a MDB2 error on failure + * @access protected + */ + function _endOfLOB($lob) + { + return $lob['endOfLOB']; + } + + // }}} + // {{{ destroyLOB() + + /** + * Free any resources allocated during the lifetime of the large object + * handler object. + * + * @param resource $lob stream handle + * @access public + */ + function destroyLOB($lob) + { + $lob_data = stream_get_meta_data($lob); + $lob_index = $lob_data['wrapper_data']->lob_index; + fclose($lob); + if (isset($this->lobs[$lob_index])) { + $this->_destroyLOB($this->lobs[$lob_index]); + unset($this->lobs[$lob_index]); + } + return MDB2_OK; + } + + // }}} + // {{{ _destroyLOB() + + /** + * Free any resources allocated during the lifetime of the large object + * handler object. + * + * @param array $lob array + * @access private + */ + function _destroyLOB(&$lob) + { + return MDB2_OK; + } + + // }}} + // {{{ implodeArray() + + /** + * apply a type to all values of an array and return as a comma seperated string + * useful for generating IN statements + * + * @access public + * + * @param array $array data array + * @param string $type determines type of the field + * + * @return string comma seperated values + */ + function implodeArray($array, $type = false) + { + if (!is_array($array) || empty($array)) { + return 'NULL'; + } + if ($type) { + foreach ($array as $value) { + $return[] = $this->quote($value, $type); + } + } else { + $return = $array; + } + return implode(', ', $return); + } + + // }}} + // {{{ matchPattern() + + /** + * build a pattern matching string + * + * @access public + * + * @param array $pattern even keys are strings, odd are patterns (% and _) + * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) + * @param string $field optional field name that is being matched against + * (might be required when emulating ILIKE) + * + * @return string SQL pattern + */ + function matchPattern($pattern, $operator = null, $field = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $match = ''; + if (!is_null($operator)) { + $operator = strtoupper($operator); + switch ($operator) { + // case insensitive + case 'ILIKE': + if (is_null($field)) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'case insensitive LIKE matching requires passing the field name', __FUNCTION__); + } + $db->loadModule('Function', null, true); + $match = $db->function->lower($field).' LIKE '; + break; + // case sensitive + case 'LIKE': + $match = is_null($field) ? 'LIKE ' : $field.' LIKE '; + break; + default: + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'not a supported operator type:'. $operator, __FUNCTION__); + } + } + $match.= "'"; + foreach ($pattern as $key => $value) { + if ($key % 2) { + $match.= $value; + } else { + if ($operator === 'ILIKE') { + $value = strtolower($value); + } + $escaped = $db->escape($value); + if (PEAR::isError($escaped)) { + return $escaped; + } + $match.= $db->escapePattern($escaped); + } + } + $match.= "'"; + $match.= $this->patternEscapeString(); + return $match; + } + + // }}} + // {{{ patternEscapeString() + + /** + * build string to define pattern escape character + * + * @access public + * + * @return string define pattern escape character + */ + function patternEscapeString() + { + return ''; + } + + // }}} + // {{{ mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function mapNativeDatatype($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + // If the user has specified an option to map the native field + // type to a custom MDB2 datatype... + $db_type = strtok($field['type'], '(), '); + if (!empty($db->options['nativetype_map_callback'][$db_type])) { + return call_user_func_array($db->options['nativetype_map_callback'][$db_type], array($db, $field)); + } + + // Otherwise perform the built-in (i.e. normal) MDB2 native type to + // MDB2 datatype conversion + return $this->_mapNativeDatatype($field); + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ mapPrepareDatatype() + + /** + * Maps an mdb2 datatype to mysqli prepare type + * + * @param string $type + * @return string + * @access public + */ + function mapPrepareDatatype($type) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($db->options['datatype_map'][$type])) { + $type = $db->options['datatype_map'][$type]; + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type); + return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + } + } + + return $type; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/ibase.php b/lib/Pear/MDB2/Driver/Datatype/ibase.php new file mode 100644 index 0000000..e564e63 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/ibase.php @@ -0,0 +1,426 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: ibase.php,v 1.89 2007/03/28 16:58:54 quipo Exp $ + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 Firebird/Interbase driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + * @author Lorenzo Alberton + */ +class MDB2_Driver_Datatype_ibase extends MDB2_Driver_Datatype_Common +{ + // {{{ _baseConvertResult() + + /** + * General type conversion method + * + * @param mixed $value refernce to a value to be converted + * @param string $type specifies which type to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return object a MDB2 error on failure + * @access protected + */ + function _baseConvertResult($value, $type, $rtrim = true) + { + if (is_null($value)) { + return null; + } + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($type) { + case 'timestamp': + return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS')); + } + return parent::_baseConvertResult($value, $type, $rtrim); + } + + // }}} + // {{{ _getCharsetFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + function _getCharsetFieldDeclaration($charset) + { + return 'CHARACTER SET '.$charset; + } + + // }}} + // {{{ _getCollationFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + function _getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + $length = !empty($field['length']) + ? $field['length'] : $db->options['default_text_field_length']; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? 'CHAR('.$length.')' : 'VARCHAR('.$length.')'; + case 'clob': + return 'BLOB SUB_TYPE 1'; + case 'blob': + return 'BLOB SUB_TYPE 0'; + case 'integer': + return 'INT'; + case 'boolean': + return 'SMALLINT'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'TIMESTAMP'; + case 'float': + return 'DOUBLE PRECISION'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'DECIMAL('.$length.','.$scale.')'; + } + return ''; + } + + // }}} + // {{{ _quoteLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteLOB($value, $quote, $escape_wildcards) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $connection = $db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $close = true; + if (is_resource($value)) { + $close = false; + } elseif (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { + if ($match[1] == 'file://') { + $value = $match[2]; + } + $value = @fopen($value, 'r'); + } else { + $fp = @tmpfile(); + @fwrite($fp, $value); + @rewind($fp); + $value = $fp; + } + $blob_id = @ibase_blob_import($connection, $value); + + if ($close) { + @fclose($value); + } + return $blob_id; + } + + // }}} + // {{{ _retrieveLOB() + + /** + * retrieve LOB from the database + * + * @param array $lob array + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function _retrieveLOB(&$lob) + { + if (empty($lob['handle'])) { + $lob['handle'] = @ibase_blob_open($lob['resource']); + if (!$lob['handle']) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(null, null, null, + 'Could not open fetched large object field', __FUNCTION__); + } + } + $lob['loaded'] = true; + return MDB2_OK; + } + + // }}} + // {{{ _readLOB() + + /** + * Read data from large object input stream. + * + * @param array $lob array + * @param blob $data reference to a variable that will hold data to be + * read from the large object input stream + * @param int $length integer value that indicates the largest ammount of + * data to be read from the large object input stream. + * @return mixed length on success, a MDB2 error on failure + * @access protected + */ + function _readLOB(&$lob, $length) + { + $data = @ibase_blob_get($lob['handle'], $length); + if (!is_string($data)) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(null, null, null, + 'Unable to read LOB', __FUNCTION__); + } + return $data; + } + + // }}} + // {{{ _destroyLOB() + + /** + * Free any resources allocated during the lifetime of the large object + * handler object. + * + * @param array $lob array + * @access protected + */ + function _destroyLOB(&$lob) + { + if (isset($lob['handle'])) { + @ibase_blob_close($lob['handle']); + unset($lob['handle']); + } + } + + // }}} + // {{{ patternEscapeString() + + /** + * build string to define escape pattern string + * + * @access public + * + * @return string define escape pattern + */ + function patternEscapeString() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return " ESCAPE '". $db->string_quoting['escape_pattern'] ."'"; + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $length = $field['length']; + if ((int)$length <= 0) { + $length = null; + } + $type = array(); + $unsigned = $fixed = null; + $db_type = strtolower($field['type']); + $field['field_sub_type'] = !empty($field['field_sub_type']) + ? strtolower($field['field_sub_type']) : null; + switch ($db_type) { + case 'smallint': + case 'integer': + case 'int64': + //these may be 'numeric' or 'decimal' + if (isset($field['field_sub_type'])) { + $field['type'] = $field['field_sub_type']; + return $this->mapNativeDatatype($field); + } + case 'bigint': + case 'quad': + $type[] = 'integer'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'varchar': + $fixed = false; + case 'char': + case 'cstring': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'double precision': + case 'd_float': + $type[] = 'float'; + break; + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + $length = $field['precision'].','.$field['scale']; + break; + case 'blob': + $type[] = ($field['field_sub_type'] == 'text') ? 'clob' : 'blob'; + $length = null; + break; + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/mssql.php b/lib/Pear/MDB2/Driver/Datatype/mssql.php new file mode 100644 index 0000000..fff343c --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/mssql.php @@ -0,0 +1,436 @@ + | +// | Daniel Convissor | +// +----------------------------------------------------------------------+ +// +// $Id: mssql.php,v 1.65 2008/02/19 14:54:17 afz Exp $ +// + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 MS SQL driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common +{ + // {{{ _baseConvertResult() + + /** + * general type conversion method + * + * @param mixed $value refernce to a value to be converted + * @param string $type specifies which type to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return object a MDB2 error on failure + * @access protected + */ + function _baseConvertResult($value, $type, $rtrim = true) + { + if (is_null($value)) { + return null; + } + switch ($type) { + case 'boolean': + return $value == '1'; + case 'date': + if (strlen($value) > 10) { + $value = substr($value,0,10); + } + return $value; + case 'time': + if (strlen($value) > 8) { + $value = substr($value,11,8); + } + return $value; + } + return parent::_baseConvertResult($value, $type, $rtrim); + } + + // }}} + // {{{ _getCollationFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + function _getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + $length = !empty($field['length']) + ? $field['length'] : false; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 8000) { + return 'VARCHAR('.$length.')'; + } + } + return 'TEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 8000) { + return "VARBINARY($length)"; + } + } + return 'IMAGE'; + case 'integer': + return 'INT'; + case 'boolean': + return 'BIT'; + case 'date': + return 'CHAR ('.strlen('YYYY-MM-DD').')'; + case 'time': + return 'CHAR ('.strlen('HH:MM:SS').')'; + case 'timestamp': + return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')'; + case 'float': + return 'FLOAT'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'DECIMAL('.$length.','.$scale.')'; + } + return ''; + } + + // }}} + // {{{ _getIntegerDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getIntegerDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; + $default = $autoinc = ''; + if (!empty($field['autoincrement'])) { + $autoinc = ' IDENTITY PRIMARY KEY'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = 0; + } + if (is_null($field['default'])) { + $default = ' DEFAULT (null)'; + } else { + $default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')'; + } + } + + if (!empty($field['unsigned'])) { + $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; + } + + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc; + } + + // }}} + // {{{ _getCLOBDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an character + * large object type field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the large + * object field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function _getCLOBDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$notnull; + } + + // }}} + // {{{ _getBLOBDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an binary large + * object type field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the large + * object field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getBLOBDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$notnull; + } + + // }}} + // {{{ _quoteBLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteBLOB($value, $quote, $escape_wildcards) + { + if (!$quote) { + return $value; + } + $value = '0x'.bin2hex($this->_readFile($value)); + return $value; + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + // todo: handle length of various int variations + $db_type = preg_replace('/\d/', '', strtolower($field['type'])); + $length = $field['length']; + $type = array(); + // todo: unsigned handling seems to be missing + $unsigned = $fixed = null; + switch ($db_type) { + case 'bit': + $type[0] = 'boolean'; + break; + case 'tinyint': + $type[0] = 'integer'; + $length = 1; + break; + case 'smallint': + $type[0] = 'integer'; + $length = 2; + break; + case 'int': + $type[0] = 'integer'; + $length = 4; + break; + case 'bigint': + $type[0] = 'integer'; + $length = 8; + break; + case 'datetime': + $type[0] = 'timestamp'; + break; + case 'float': + case 'real': + case 'numeric': + $type[0] = 'float'; + break; + case 'decimal': + case 'money': + $type[0] = 'decimal'; + $length = $field['numeric_precision'].','.$field['numeric_scale']; + break; + case 'text': + case 'ntext': + case 'varchar': + case 'nvarchar': + $fixed = false; + case 'char': + case 'nchar': + $type[0] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + $type = array_reverse($type); + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'image': + case 'varbinary': + $type[] = 'blob'; + $length = null; + break; + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } + // }}} +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/mysql.php b/lib/Pear/MDB2/Driver/Datatype/mysql.php new file mode 100644 index 0000000..f54dd0a --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/mysql.php @@ -0,0 +1,553 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.65 2008/02/22 19:23:49 quipo Exp $ +// + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 MySQL driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common +{ + // {{{ _getCharsetFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + function _getCharsetFieldDeclaration($charset) + { + return 'CHARACTER SET '.$charset; + } + + // }}} + // {{{ _getCollationFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + function _getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + if (empty($field['length']) && array_key_exists('default', $field)) { + $field['length'] = $db->varchar_max_length; + } + $length = !empty($field['length']) ? $field['length'] : false; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } elseif ($length <= 65532) { + return 'TEXT'; + } elseif ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + return 'LONGTEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYBLOB'; + } elseif ($length <= 65532) { + return 'BLOB'; + } elseif ($length <= 16777215) { + return 'MEDIUMBLOB'; + } + } + return 'LONGBLOB'; + case 'integer': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 1) { + return 'TINYINT'; + } elseif ($length == 2) { + return 'SMALLINT'; + } elseif ($length == 3) { + return 'MEDIUMINT'; + } elseif ($length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'boolean': + return 'TINYINT(1)'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'DATETIME'; + case 'float': + return 'DOUBLE'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'DECIMAL('.$length.','.$scale.')'; + } + return ''; + } + + // }}} + // {{{ _getIntegerDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getIntegerDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $default = $autoinc = ''; + if (!empty($field['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT PRIMARY KEY'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; + } + + // }}} + // {{{ _getFloatDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an float type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned float if + * possible. + * + * default + * float value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getFloatDeclaration($name, $field) + { + // Since AUTO_INCREMENT can be used for integer or floating-point types, + // reuse the INTEGER declaration + // @see http://bugs.mysql.com/bug.php?id=31032 + return $this->_getIntegerDeclaration($name, $field); + } + + // }}} + // {{{ _getDecimalDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an decimal type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Decimal value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getDecimalDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $default = ''; + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); + } elseif (empty($field['notnull'])) { + $default = ' DEFAULT NULL'; + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull; + } + + // }}} + // {{{ matchPattern() + + /** + * build a pattern matching string + * + * @access public + * + * @param array $pattern even keys are strings, odd are patterns (% and _) + * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) + * @param string $field optional field name that is being matched against + * (might be required when emulating ILIKE) + * + * @return string SQL pattern + */ + function matchPattern($pattern, $operator = null, $field = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $match = ''; + if (!is_null($operator)) { + $field = is_null($field) ? '' : $field.' '; + $operator = strtoupper($operator); + switch ($operator) { + // case insensitive + case 'ILIKE': + $match = $field.'LIKE '; + break; + // case sensitive + case 'LIKE': + $match = $field.'LIKE BINARY '; + break; + default: + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'not a supported operator type:'. $operator, __FUNCTION__); + } + } + $match.= "'"; + foreach ($pattern as $key => $value) { + if ($key % 2) { + $match.= $value; + } else { + $match.= $db->escapePattern($db->escape($value)); + } + } + $match.= "'"; + $match.= $this->patternEscapeString(); + return $match; + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $db_type = strtolower($field['type']); + $db_type = strtok($db_type, '(), '); + if ($db_type == 'national') { + $db_type = strtok('(), '); + } + if (!empty($field['length'])) { + $length = strtok($field['length'], ', '); + $decimal = strtok(', '); + } else { + $length = strtok('(), '); + $decimal = strtok('(), '); + } + $type = array(); + $unsigned = $fixed = null; + switch ($db_type) { + case 'tinyint': + $type[] = 'integer'; + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 1; + break; + case 'smallint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 2; + break; + case 'mediumint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 3; + break; + case 'int': + case 'integer': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 4; + break; + case 'bigint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 8; + break; + case 'tinytext': + case 'mediumtext': + case 'longtext': + case 'text': + case 'varchar': + $fixed = false; + case 'string': + case 'char': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + if ($decimal == 'binary') { + $type[] = 'blob'; + } + $type = array_reverse($type); + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'enum': + $type[] = 'text'; + preg_match_all('/\'.+\'/U', $field['type'], $matches); + $length = 0; + $fixed = false; + if (is_array($matches)) { + foreach ($matches[0] as $value) { + $length = max($length, strlen($value)-2); + } + if ($length == '1' && count($matches[0]) == 2) { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + } + $type[] = 'integer'; + case 'set': + $fixed = false; + $type[] = 'text'; + $type[] = 'integer'; + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + break; + case 'unknown': + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + if ($decimal !== false) { + $length = $length.','.$decimal; + } + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + $type[] = 'blob'; + $length = null; + break; + case 'binary': + case 'varbinary': + $type[] = 'blob'; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } + + // }}} +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/mysqli.php b/lib/Pear/MDB2/Driver/Datatype/mysqli.php new file mode 100644 index 0000000..deba919 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/mysqli.php @@ -0,0 +1,590 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysqli.php,v 1.63 2008/02/22 19:23:49 quipo Exp $ +// + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 MySQLi driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Datatype_mysqli extends MDB2_Driver_Datatype_Common +{ + // {{{ _getCharsetFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + function _getCharsetFieldDeclaration($charset) + { + return 'CHARACTER SET '.$charset; + } + + // }}} + // {{{ _getCollationFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + function _getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + if (empty($field['length']) && array_key_exists('default', $field)) { + $field['length'] = $db->varchar_max_length; + } + $length = !empty($field['length']) ? $field['length'] : false; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } elseif ($length <= 65532) { + return 'TEXT'; + } elseif ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + return 'LONGTEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYBLOB'; + } elseif ($length <= 65532) { + return 'BLOB'; + } elseif ($length <= 16777215) { + return 'MEDIUMBLOB'; + } + } + return 'LONGBLOB'; + case 'integer': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 1) { + return 'TINYINT'; + } elseif ($length == 2) { + return 'SMALLINT'; + } elseif ($length == 3) { + return 'MEDIUMINT'; + } elseif ($length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'boolean': + return 'TINYINT(1)'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'DATETIME'; + case 'float': + return 'DOUBLE'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'DECIMAL('.$length.','.$scale.')'; + } + return ''; + } + + // }}} + // {{{ _getIntegerDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getIntegerDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $default = $autoinc = ''; + if (!empty($field['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT PRIMARY KEY'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; + } + + // }}} + // {{{ _getFloatDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an float type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned float if + * possible. + * + * default + * float value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getFloatDeclaration($name, $field) + { + // Since AUTO_INCREMENT can be used for integer or floating-point types, + // reuse the INTEGER declaration + // @see http://bugs.mysql.com/bug.php?id=31032 + return $this->_getIntegerDeclaration($name, $field); + } + + // }}} + // {{{ _getDecimalDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an decimal type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Decimal value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getDecimalDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $default = ''; + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); + } elseif (empty($field['notnull'])) { + $default = ' DEFAULT NULL'; + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull; + } + + // }}} + // {{{ matchPattern() + + /** + * build a pattern matching string + * + * @access public + * + * @param array $pattern even keys are strings, odd are patterns (% and _) + * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) + * @param string $field optional field name that is being matched against + * (might be required when emulating ILIKE) + * + * @return string SQL pattern + */ + function matchPattern($pattern, $operator = null, $field = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $match = ''; + if (!is_null($operator)) { + $field = is_null($field) ? '' : $field.' '; + $operator = strtoupper($operator); + switch ($operator) { + // case insensitive + case 'ILIKE': + $match = $field.'LIKE '; + break; + // case sensitive + case 'LIKE': + $match = $field.'LIKE BINARY '; + break; + default: + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'not a supported operator type:'. $operator, __FUNCTION__); + } + } + $match.= "'"; + foreach ($pattern as $key => $value) { + if ($key % 2) { + $match.= $value; + } else { + $match.= $db->escapePattern($db->escape($value)); + } + } + $match.= "'"; + $match.= $this->patternEscapeString(); + return $match; + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $db_type = strtolower($field['type']); + $db_type = strtok($db_type, '(), '); + if ($db_type == 'national') { + $db_type = strtok('(), '); + } + if (!empty($field['length'])) { + $length = strtok($field['length'], ', '); + $decimal = strtok(', '); + } else { + $length = strtok('(), '); + $decimal = strtok('(), '); + } + $type = array(); + $unsigned = $fixed = null; + switch ($db_type) { + case 'tinyint': + $type[] = 'integer'; + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 1; + break; + case 'smallint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 2; + break; + case 'mediumint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 3; + break; + case 'int': + case 'integer': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 4; + break; + case 'bigint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 8; + break; + case 'tinytext': + case 'mediumtext': + case 'longtext': + case 'text': + case 'varchar': + $fixed = false; + case 'string': + case 'char': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + if ($decimal == 'binary') { + $type[] = 'blob'; + } + $type = array_reverse($type); + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'enum': + $type[] = 'text'; + preg_match_all('/\'.+\'/U', $field['type'], $matches); + $length = 0; + $fixed = false; + if (is_array($matches)) { + foreach ($matches[0] as $value) { + $length = max($length, strlen($value)-2); + } + if ($length == '1' && count($matches[0]) == 2) { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + } + $type[] = 'integer'; + case 'set': + $fixed = false; + $type[] = 'text'; + $type[] = 'integer'; + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + break; + case 'unknown': + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + if ($decimal !== false) { + $length = $length.','.$decimal; + } + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + $type[] = 'blob'; + $length = null; + break; + case 'binary': + case 'varbinary': + $type[] = 'blob'; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } + + // }}} + // {{{ mapPrepareDatatype() + + /** + * Maps an MDB2 datatype to native prepare type + * + * @param string $type + * @return string + * @access public + */ + function mapPrepareDatatype($type) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($db->options['datatype_map'][$type])) { + $type = $db->options['datatype_map'][$type]; + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type); + return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + } + } + + switch ($type) { + case 'integer': + return 'i'; + case 'float': + return 'd'; + case 'blob': + return 'b'; + default: + break; + } + return 's'; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/oci8.php b/lib/Pear/MDB2/Driver/Datatype/oci8.php new file mode 100644 index 0000000..91509de --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/oci8.php @@ -0,0 +1,482 @@ + | +// +----------------------------------------------------------------------+ + +// $Id: oci8.php,v 1.72 2007/03/28 16:58:54 quipo Exp $ + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 OCI8 driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Datatype_oci8 extends MDB2_Driver_Datatype_Common +{ + // {{{ _baseConvertResult() + + /** + * general type conversion method + * + * @param mixed $value refernce to a value to be converted + * @param string $type specifies which type to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return object a MDB2 error on failure + * @access protected + */ + function _baseConvertResult($value, $type, $rtrim = true) + { + if (is_null($value)) { + return null; + } + switch ($type) { + case 'date': + return substr($value, 0, strlen('YYYY-MM-DD')); + case 'time': + return substr($value, strlen('YYYY-MM-DD '), strlen('HH:MI:SS')); + } + return parent::_baseConvertResult($value, $type, $rtrim); + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + $length = !empty($field['length']) + ? $field['length'] : $db->options['default_text_field_length']; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')'; + case 'clob': + return 'CLOB'; + case 'blob': + return 'BLOB'; + case 'integer': + if (!empty($field['length'])) { + switch((int)$field['length']) { + case 1: $digit = 3; break; + case 2: $digit = 5; break; + case 3: $digit = 8; break; + case 4: $digit = 10; break; + case 5: $digit = 13; break; + case 6: $digit = 15; break; + case 7: $digit = 17; break; + case 8: $digit = 20; break; + default: $digit = 10; + } + return 'NUMBER('.$digit.')'; + } + return 'INT'; + case 'boolean': + return 'NUMBER(1)'; + case 'date': + case 'time': + case 'timestamp': + return 'DATE'; + case 'float': + return 'NUMBER'; + case 'decimal': + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'NUMBER(*,'.$scale.')'; + } + } + + // }}} + // {{{ _quoteCLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteCLOB($value, $quote, $escape_wildcards) + { + return 'EMPTY_CLOB()'; + } + + // }}} + // {{{ _quoteBLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteBLOB($value, $quote, $escape_wildcards) + { + return 'EMPTY_BLOB()'; + } + + // }}} + // {{{ _quoteDate() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteDate($value, $quote, $escape_wildcards) + { + return $this->_quoteText("$value 00:00:00", $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteTimestamp() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteTimestamp($value, $quote, $escape_wildcards) + { + return $this->_quoteText($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteTime() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteTime($value, $quote, $escape_wildcards) + { + return $this->_quoteText("0001-01-01 $value", $quote, $escape_wildcards); + } + + // }}} + // {{{ writeLOBToFile() + + /** + * retrieve LOB from the database + * + * @param array $lob array + * @param string $file name of the file into which the LOb should be fetched + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function writeLOBToFile($lob, $file) + { + if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) { + if ($match[1] == 'file://') { + $file = $match[2]; + } + } + $lob_data = stream_get_meta_data($lob); + $lob_index = $lob_data['wrapper_data']->lob_index; + $result = $this->lobs[$lob_index]['resource']->writetofile($file); + $this->lobs[$lob_index]['resource']->seek(0); + if (!$result) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(null, null, null, + 'Unable to write LOB to file', __FUNCTION__); + } + return MDB2_OK; + } + + // }}} + // {{{ _retrieveLOB() + + /** + * retrieve LOB from the database + * + * @param array $lob array + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function _retrieveLOB(&$lob) + { + if (!is_object($lob['resource'])) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'attemped to retrieve LOB from non existing or NULL column', __FUNCTION__); + } + + if (!$lob['loaded'] +# && !method_exists($lob['resource'], 'read') + ) { + $lob['value'] = $lob['resource']->load(); + $lob['resource']->seek(0); + } + $lob['loaded'] = true; + return MDB2_OK; + } + + // }}} + // {{{ _readLOB() + + /** + * Read data from large object input stream. + * + * @param array $lob array + * @param blob $data reference to a variable that will hold data to be + * read from the large object input stream + * @param int $length integer value that indicates the largest ammount of + * data to be read from the large object input stream. + * @return mixed length on success, a MDB2 error on failure + * @access protected + */ + function _readLOB($lob, $length) + { + if ($lob['loaded']) { + return parent::_readLOB($lob, $length); + } + + if (!is_object($lob['resource'])) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'attemped to retrieve LOB from non existing or NULL column', __FUNCTION__); + } + + $data = $lob['resource']->read($length); + if (!is_string($data)) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(null, null, null, + 'Unable to read LOB', __FUNCTION__); + } + return $data; + } + + // }}} + // {{{ patternEscapeString() + + /** + * build string to define escape pattern string + * + * @access public + * + * + * @return string define escape pattern + */ + function patternEscapeString() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return " ESCAPE '". $db->string_quoting['escape_pattern'] ."'"; + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $db_type = strtolower($field['type']); + $type = array(); + $length = $unsigned = $fixed = null; + if (!empty($field['length'])) { + $length = $field['length']; + } + switch ($db_type) { + case 'integer': + case 'pls_integer': + case 'binary_integer': + $type[] = 'integer'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'varchar': + case 'varchar2': + case 'nvarchar2': + $fixed = false; + case 'char': + case 'nchar': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'float': + $type[] = 'float'; + break; + case 'number': + if (!empty($field['scale'])) { + $type[] = 'decimal'; + $length = $length.','.$field['scale']; + } else { + $type[] = 'integer'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + } + break; + case 'long': + $type[] = 'text'; + case 'clob': + case 'nclob': + $type[] = 'clob'; + break; + case 'blob': + case 'raw': + case 'long raw': + case 'bfile': + $type[] = 'blob'; + $length = null; + break; + case 'rowid': + case 'urowid': + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/pgsql.php b/lib/Pear/MDB2/Driver/Datatype/pgsql.php new file mode 100644 index 0000000..c31c7d8 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/pgsql.php @@ -0,0 +1,555 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: pgsql.php,v 1.91 2008/03/09 12:28:08 quipo Exp $ + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 PostGreSQL driver + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common +{ + // {{{ _baseConvertResult() + + /** + * General type conversion method + * + * @param mixed $value refernce to a value to be converted + * @param string $type specifies which type to convert to + * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text + * @return object a MDB2 error on failure + * @access protected + */ + function _baseConvertResult($value, $type, $rtrim = true) + { + if (is_null($value)) { + return null; + } + switch ($type) { + case 'boolean': + return $value == 't'; + case 'float': + return doubleval($value); + case 'date': + return $value; + case 'time': + return substr($value, 0, strlen('HH:MM:SS')); + case 'timestamp': + return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS')); + case 'blob': + $value = pg_unescape_bytea($value); + return parent::_baseConvertResult($value, $type, $rtrim); + } + return parent::_baseConvertResult($value, $type, $rtrim); + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + $length = !empty($field['length']) + ? $field['length'] : $db->options['default_text_field_length']; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + return 'TEXT'; + case 'blob': + return 'BYTEA'; + case 'integer': + if (!empty($field['autoincrement'])) { + if (!empty($field['length'])) { + $length = $field['length']; + if ($length > 4) { + return 'BIGSERIAL PRIMARY KEY'; + } + } + return 'SERIAL PRIMARY KEY'; + } + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 2) { + return 'SMALLINT'; + } elseif ($length == 3 || $length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'boolean': + return 'BOOLEAN'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME without time zone'; + case 'timestamp': + return 'TIMESTAMP without time zone'; + case 'float': + return 'FLOAT8'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'NUMERIC('.$length.','.$scale.')'; + } + } + + // }}} + // {{{ _getIntegerDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field should be + * declared as unsigned integer if possible. + * + * default + * Integer value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getIntegerDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($field['unsigned'])) { + $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; + } + if (!empty($field['autoincrement'])) { + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field); + } + $default = ''; + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$default.$notnull; + } + + // }}} + // {{{ _quoteCLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteCLOB($value, $quote, $escape_wildcards) + { + return $this->_quoteText($value, $quote, $escape_wildcards); + } + + // }}} + // {{{ _quoteBLOB() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteBLOB($value, $quote, $escape_wildcards) + { + if (!$quote) { + return $value; + } + if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $connection = $db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $value = @pg_escape_bytea($connection, $value); + } else { + $value = @pg_escape_bytea($value); + } + return "'".$value."'"; + } + + // }}} + // {{{ _quoteBoolean() + + /** + * Convert a text value into a DBMS specific format that is suitable to + * compose query statements. + * + * @param string $value text string value that is intended to be converted. + * @param bool $quote determines if the value should be quoted and escaped + * @param bool $escape_wildcards if to escape escape wildcards + * @return string text string that represents the given argument value in + * a DBMS specific format. + * @access protected + */ + function _quoteBoolean($value, $quote, $escape_wildcards) + { + $value = $value ? 't' : 'f'; + if (!$quote) { + return $value; + } + return "'".$value."'"; + } + + // }}} + // {{{ matchPattern() + + /** + * build a pattern matching string + * + * @access public + * + * @param array $pattern even keys are strings, odd are patterns (% and _) + * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) + * @param string $field optional field name that is being matched against + * (might be required when emulating ILIKE) + * + * @return string SQL pattern + */ + function matchPattern($pattern, $operator = null, $field = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $match = ''; + if (!is_null($operator)) { + $field = is_null($field) ? '' : $field.' '; + $operator = strtoupper($operator); + switch ($operator) { + // case insensitive + case 'ILIKE': + $match = $field.'ILIKE '; + break; + // case sensitive + case 'LIKE': + $match = $field.'LIKE '; + break; + default: + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'not a supported operator type:'. $operator, __FUNCTION__); + } + } + $match.= "'"; + foreach ($pattern as $key => $value) { + if ($key % 2) { + $match.= $value; + } else { + $match.= $db->escapePattern($db->escape($value)); + } + } + $match.= "'"; + $match.= $this->patternEscapeString(); + return $match; + } + + // }}} + // {{{ patternEscapeString() + + /** + * build string to define escape pattern string + * + * @access public + * + * + * @return string define escape pattern + */ + function patternEscapeString() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']); + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $db_type = strtolower($field['type']); + $length = $field['length']; + $type = array(); + $unsigned = $fixed = null; + switch ($db_type) { + case 'smallint': + case 'int2': + $type[] = 'integer'; + $unsigned = false; + $length = 2; + if ($length == '2') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'int': + case 'int4': + case 'integer': + case 'serial': + case 'serial4': + $type[] = 'integer'; + $unsigned = false; + $length = 4; + break; + case 'bigint': + case 'int8': + case 'bigserial': + case 'serial8': + $type[] = 'integer'; + $unsigned = false; + $length = 8; + break; + case 'bool': + case 'boolean': + $type[] = 'boolean'; + $length = null; + break; + case 'text': + case 'varchar': + $fixed = false; + case 'unknown': + case 'char': + case 'bpchar': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + $type = array_reverse($type); + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + case 'timestamptz': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'float4': + case 'float8': + case 'double': + case 'real': + $type[] = 'float'; + break; + case 'decimal': + case 'money': + case 'numeric': + $type[] = 'decimal'; + if (isset($field['scale'])) { + $length = $length.','.$field['scale']; + } + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + case 'bytea': + $type[] = 'blob'; + $length = null; + break; + case 'oid': + $type[] = 'blob'; + $type[] = 'clob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } + + // }}} + // {{{ mapPrepareDatatype() + + /** + * Maps an mdb2 datatype to native prepare type + * + * @param string $type + * @return string + * @access public + */ + function mapPrepareDatatype($type) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($db->options['datatype_map'][$type])) { + $type = $db->options['datatype_map'][$type]; + if (!empty($db->options['datatype_map_callback'][$type])) { + $parameter = array('type' => $type); + return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); + } + } + + switch ($type) { + case 'integer': + return 'int'; + case 'boolean': + return 'bool'; + case 'decimal': + case 'float': + return 'numeric'; + case 'clob': + return 'text'; + case 'blob': + return 'bytea'; + default: + break; + } + return $type; + } + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Datatype/sqlite.php b/lib/Pear/MDB2/Driver/Datatype/sqlite.php new file mode 100644 index 0000000..0310cc7 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Datatype/sqlite.php @@ -0,0 +1,409 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $ +// + +require_once 'MDB2/Driver/Datatype/Common.php'; + +/** + * MDB2 SQLite driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common +{ + // {{{ _getCollationFieldDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + function _getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } + + // }}} + // {{{ getTypeDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access public + */ + function getTypeDeclaration($field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + switch ($field['type']) { + case 'text': + $length = !empty($field['length']) + ? $field['length'] : false; + $fixed = !empty($field['fixed']) ? $field['fixed'] : false; + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } elseif ($length <= 65532) { + return 'TEXT'; + } elseif ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + return 'LONGTEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYBLOB'; + } elseif ($length <= 65532) { + return 'BLOB'; + } elseif ($length <= 16777215) { + return 'MEDIUMBLOB'; + } + } + return 'LONGBLOB'; + case 'integer': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 2) { + return 'SMALLINT'; + } elseif ($length == 3 || $length == 4) { + return 'INTEGER'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INTEGER'; + case 'boolean': + return 'BOOLEAN'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'DATETIME'; + case 'float': + return 'DOUBLE'.($db->options['fixed_float'] ? '('. + ($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : ''); + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; + return 'DECIMAL('.$length.','.$scale.')'; + } + return ''; + } + + // }}} + // {{{ _getIntegerDeclaration() + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + function _getIntegerDeclaration($name, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $default = $autoinc = ''; + if (!empty($field['autoincrement'])) { + $autoinc = ' PRIMARY KEY'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); + } + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; + $name = $db->quoteIdentifier($name, true); + return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; + } + + // }}} + // {{{ matchPattern() + + /** + * build a pattern matching string + * + * @access public + * + * @param array $pattern even keys are strings, odd are patterns (% and _) + * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) + * @param string $field optional field name that is being matched against + * (might be required when emulating ILIKE) + * + * @return string SQL pattern + */ + function matchPattern($pattern, $operator = null, $field = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $match = ''; + if (!is_null($operator)) { + $field = is_null($field) ? '' : $field.' '; + $operator = strtoupper($operator); + switch ($operator) { + // case insensitive + case 'ILIKE': + $match = $field.'LIKE '; + break; + // case sensitive + case 'LIKE': + $match = $field.'LIKE '; + break; + default: + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'not a supported operator type:'. $operator, __FUNCTION__); + } + } + $match.= "'"; + foreach ($pattern as $key => $value) { + if ($key % 2) { + $match.= $value; + } else { + $match.= $db->escapePattern($db->escape($value)); + } + } + $match.= "'"; + $match.= $this->patternEscapeString(); + return $match; + } + + // }}} + // {{{ _mapNativeDatatype() + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @access public + */ + function _mapNativeDatatype($field) + { + $db_type = strtolower($field['type']); + $length = !empty($field['length']) ? $field['length'] : null; + $unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null; + $fixed = null; + $type = array(); + switch ($db_type) { + case 'boolean': + $type[] = 'boolean'; + break; + case 'tinyint': + $type[] = 'integer'; + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 1; + break; + case 'smallint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 2; + break; + case 'mediumint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 3; + break; + case 'int': + case 'integer': + case 'serial': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 4; + break; + case 'bigint': + case 'bigserial': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 8; + break; + case 'clob': + $type[] = 'clob'; + $fixed = false; + break; + case 'tinytext': + case 'mediumtext': + case 'longtext': + case 'text': + case 'varchar': + case 'varchar2': + $fixed = false; + case 'char': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + $type = array_reverse($type); + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + break; + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + $length = $length.','.$field['decimal']; + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + $type[] = 'blob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unknown database attribute type: '.$db_type, __FUNCTION__); + } + + if ((int)$length <= 0) { + $length = null; + } + + return array($type, $length, $unsigned, $fixed); + } + + // }}} +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/Common.php b/lib/Pear/MDB2/Driver/Function/Common.php new file mode 100644 index 0000000..d361b55 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/Common.php @@ -0,0 +1,293 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.21 2008/02/17 18:51:39 quipo Exp $ +// + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + */ + +/** + * Base class for the function modules that is extended by each MDB2 driver + * + * To load this module in the MDB2 object: + * $mdb->loadModule('Function'); + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_Common extends MDB2_Module_Common +{ + // {{{ executeStoredProc() + + /** + * Execute a stored procedure and return any results + * + * @param string $name string that identifies the function to execute + * @param mixed $params array that contains the paramaters to pass the stored proc + * @param mixed $types array that contains the types of the columns in + * the result set + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $error; + } + + // }}} + // {{{ functionTable() + + /** + * return string for internal table used when calling only a function + * + * @return string for internal table used when calling only a function + * @access public + */ + function functionTable() + { + return ''; + } + + // }}} + // {{{ now() + + /** + * Return string to call a variable with the current timestamp inside an SQL statement + * There are three special variables for current date and time: + * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type) + * - CURRENT_DATE (date, DATE type) + * - CURRENT_TIME (time, TIME type) + * + * @param string $type 'timestamp' | 'time' | 'date' + * + * @return string to call a variable with the current timestamp + * @access public + */ + function now($type = 'timestamp') + { + switch ($type) { + case 'time': + return 'CURRENT_TIME'; + case 'date': + return 'CURRENT_DATE'; + case 'timestamp': + default: + return 'CURRENT_TIMESTAMP'; + } + } + + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $error; + } + + // }}} + // {{{ substring() + + /** + * return string to call a function to get a substring inside an SQL statement + * + * @return string to call a function to get a substring + * @access public + */ + function substring($value, $position = 1, $length = null) + { + if (!is_null($length)) { + return "SUBSTRING($value FROM $position FOR $length)"; + } + return "SUBSTRING($value FROM $position)"; + } + + // }}} + // {{{ replace() + + /** + * return string to call a function to get replace inside an SQL statement. + * + * @return string to call a function to get a replace + * @access public + */ + function replace($str, $from_str, $to_str) + { + return "REPLACE($str, $from_str , $to_str)"; + } + + // }}} + // {{{ concat() + + /** + * Returns string to concatenate two or more string parameters + * + * @param string $value1 + * @param string $value2 + * @param string $values... + * + * @return string to concatenate two strings + * @access public + */ + function concat($value1, $value2) + { + $args = func_get_args(); + return "(".implode(' || ', $args).")"; + } + + // }}} + // {{{ random() + + /** + * return string to call a function to get random value inside an SQL statement + * + * @return return string to generate float between 0 and 1 + * @access public + */ + function random() + { + return 'RAND()'; + } + + // }}} + // {{{ lower() + + /** + * return string to call a function to lower the case of an expression + * + * @param string $expression + * + * @return return string to lower case of an expression + * @access public + */ + function lower($expression) + { + return "LOWER($expression)"; + } + + // }}} + // {{{ upper() + + /** + * return string to call a function to upper the case of an expression + * + * @param string $expression + * + * @return return string to upper case of an expression + * @access public + */ + function upper($expression) + { + return "UPPER($expression)"; + } + + // }}} + // {{{ length() + + /** + * return string to call a function to get the length of a string expression + * + * @param string $expression + * + * @return return string to get the string expression length + * @access public + */ + function length($expression) + { + return "LENGTH($expression)"; + } + + // }}} + // {{{ guid() + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + * @access public + */ + function guid() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $error; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/ibase.php b/lib/Pear/MDB2/Driver/Function/ibase.php new file mode 100644 index 0000000..4bae323 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/ibase.php @@ -0,0 +1,108 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: ibase.php,v 1.6 2008/02/12 21:24:02 quipo Exp $ + +require_once 'MDB2/Driver/Function/Common.php'; + +/** + * MDB2 FireBird/InterBase driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_ibase extends MDB2_Driver_Function_Common +{ + // {{{ functionTable() + + /** + * return string for internal table used when calling only a function + * + * @return string for internal table used when calling only a function + * @access public + */ + function functionTable() + { + return ' FROM RDB$DATABASE'; + } + + // }}} + // {{{ length() + + /** + * return string to call a function to get a replacement inside an SQL statement. + * + * @return string to call a function to get a replace + * @access public + */ + function length($expression) + { + return "STRLEN($expression)"; + } + + // }}} + // {{{ replace() + + /** + * return string to call a function to get a replacement inside an SQL statement. + * + * @return string to call a function to get a replace + * @access public + */ + function replace($str, $from_str, $to_str) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $error; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/mssql.php b/lib/Pear/MDB2/Driver/Function/mssql.php new file mode 100644 index 0000000..1038901 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/mssql.php @@ -0,0 +1,193 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mssql.php,v 1.16 2008/02/17 18:54:08 quipo Exp $ +// + +require_once 'MDB2/Driver/Function/Common.php'; + +// {{{ class MDB2_Driver_Function_mssql +/** + * MDB2 MSSQL driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_mssql extends MDB2_Driver_Function_Common +{ + // {{{ executeStoredProc() + + /** + * Execute a stored procedure and return any results + * + * @param string $name string that identifies the function to execute + * @param mixed $params array that contains the paramaters to pass the stored proc + * @param mixed $types array that contains the types of the columns in + * the result set + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'EXECUTE '.$name; + $query .= $params ? ' '.implode(', ', $params) : ''; + return $db->query($query, $types, $result_class, $result_wrap_class); + } + + // }}} + // {{{ now() + + /** + * Return string to call a variable with the current timestamp inside an SQL statement + * There are three special variables for current date and time: + * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type) + * - CURRENT_DATE (date, DATE type) + * - CURRENT_TIME (time, TIME type) + * + * @return string to call a variable with the current timestamp + * @access public + */ + function now($type = 'timestamp') + { + switch ($type) { + case 'time': + case 'date': + case 'timestamp': + default: + return 'GETDATE()'; + } + } + + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + return 'DATEDIFF(second, \'19700101\', '. $expression.') + DATEDIFF(second, GETDATE(), GETUTCDATE())'; + } + + // }}} + // {{{ substring() + + /** + * return string to call a function to get a substring inside an SQL statement + * + * @return string to call a function to get a substring + * @access public + */ + function substring($value, $position = 1, $length = null) + { + if (!is_null($length)) { + return "SUBSTRING($value, $position, $length)"; + } + return "SUBSTRING($value, $position, LEN($value) - $position + 1)"; + } + + // }}} + // {{{ concat() + + /** + * Returns string to concatenate two or more string parameters + * + * @param string $value1 + * @param string $value2 + * @param string $values... + * @return string to concatenate two strings + * @access public + **/ + function concat($value1, $value2) + { + $args = func_get_args(); + return "(".implode(' + ', $args).")"; + } + + // }}} + // {{{ length() + + /** + * return string to call a function to get the length of a string expression + * + * @param string $expression + * @return return string to get the string expression length + * @access public + */ + function length($expression) + { + return "LEN($expression)"; + } + + // }}} + // {{{ guid() + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + * @access public + */ + function guid() + { + return 'NEWID()'; + } + + // }}} +} +// }}} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/mysql.php b/lib/Pear/MDB2/Driver/Function/mysql.php new file mode 100644 index 0000000..d8ae7bb --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/mysql.php @@ -0,0 +1,136 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.12 2008/02/17 18:54:08 quipo Exp $ +// + +require_once 'MDB2/Driver/Function/Common.php'; + +/** + * MDB2 MySQL driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common +{ + // }}} + // {{{ executeStoredProc() + + /** + * Execute a stored procedure and return any results + * + * @param string $name string that identifies the function to execute + * @param mixed $params array that contains the paramaters to pass the stored proc + * @param mixed $types array that contains the types of the columns in + * the result set + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'CALL '.$name; + $query .= $params ? '('.implode(', ', $params).')' : '()'; + return $db->query($query, $types, $result_class, $result_wrap_class); + } + + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + return 'UNIX_TIMESTAMP('. $expression.')'; + } + + // }}} + // {{{ concat() + + /** + * Returns string to concatenate two or more string parameters + * + * @param string $value1 + * @param string $value2 + * @param string $values... + * @return string to concatenate two strings + * @access public + **/ + function concat($value1, $value2) + { + $args = func_get_args(); + return "CONCAT(".implode(', ', $args).")"; + } + + // }}} + // {{{ guid() + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + * @access public + */ + function guid() + { + return 'UUID()'; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/mysqli.php b/lib/Pear/MDB2/Driver/Function/mysqli.php new file mode 100644 index 0000000..c1fe5d6 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/mysqli.php @@ -0,0 +1,144 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysqli.php,v 1.14 2008/02/17 18:54:08 quipo Exp $ +// + +require_once 'MDB2/Driver/Function/Common.php'; + +/** + * MDB2 MySQLi driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_mysqli extends MDB2_Driver_Function_Common +{ + // }}} + // {{{ executeStoredProc() + + /** + * Execute a stored procedure and return any results + * + * @param string $name string that identifies the function to execute + * @param mixed $params array that contains the paramaters to pass the stored proc + * @param mixed $types array that contains the types of the columns in + * the result set + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $multi_query = $db->getOption('multi_query'); + if (!$multi_query) { + $db->setOption('multi_query', true); + } + $query = 'CALL '.$name; + $query .= $params ? '('.implode(', ', $params).')' : '()'; + $result =& $db->query($query, $types, $result_class, $result_wrap_class); + if (!$multi_query) { + $db->setOption('multi_query', false); + } + return $result; + } + + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + return 'UNIX_TIMESTAMP('. $expression.')'; + } + + // }}} + // {{{ concat() + + /** + * Returns string to concatenate two or more string parameters + * + * @param string $value1 + * @param string $value2 + * @param string $values... + * @return string to concatenate two strings + * @access public + **/ + function concat($value1, $value2) + { + $args = func_get_args(); + return "CONCAT(".implode(', ', $args).")"; + } + + // }}} + // {{{ guid() + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + * @access public + */ + function guid() + { + return 'UUID()'; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/oci8.php b/lib/Pear/MDB2/Driver/Function/oci8.php new file mode 100644 index 0000000..c72d17f --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/oci8.php @@ -0,0 +1,187 @@ + | +// +----------------------------------------------------------------------+ + +// $Id: oci8.php,v 1.15 2008/02/17 18:54:08 quipo Exp $ + +require_once 'MDB2/Driver/Function/Common.php'; + +/** + * MDB2 oci8 driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_oci8 extends MDB2_Driver_Function_Common +{ + // {{{ executeStoredProc() + + /** + * Execute a stored procedure and return any results + * + * @param string $name string that identifies the function to execute + * @param mixed $params array that contains the paramaters to pass the stored proc + * @param mixed $types array that contains the types of the columns in + * the result set + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'EXEC '.$name; + $query .= $params ? '('.implode(', ', $params).')' : '()'; + return $db->query($query, $types, $result_class, $result_wrap_class); + } + + // }}} + // {{{ functionTable() + + /** + * return string for internal table used when calling only a function + * + * @return string for internal table used when calling only a function + * @access public + */ + function functionTable() + { + return ' FROM dual'; + } + + // }}} + // {{{ now() + + /** + * Return string to call a variable with the current timestamp inside an SQL statement + * There are three special variables for current date and time: + * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type) + * - CURRENT_DATE (date, DATE type) + * - CURRENT_TIME (time, TIME type) + * + * @return string to call a variable with the current timestamp + * @access public + */ + function now($type = 'timestamp') + { + switch ($type) { + case 'date': + case 'time': + case 'timestamp': + default: + return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')'; + } + } + + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + $utc_offset = 'CAST(SYS_EXTRACT_UTC(SYSTIMESTAMP) AS DATE) - CAST(SYSTIMESTAMP AS DATE)'; + $epoch_date = 'to_date(\'19700101\', \'YYYYMMDD\')'; + return '(CAST('.$expression.' AS DATE) - '.$epoch_date.' + '.$utc_offset.') * 86400 seconds'; + } + + // }}} + // {{{ substring() + + /** + * return string to call a function to get a substring inside an SQL statement + * + * @return string to call a function to get a substring + * @access public + */ + function substring($value, $position = 1, $length = null) + { + if (!is_null($length)) { + return "SUBSTR($value, $position, $length)"; + } + return "SUBSTR($value, $position)"; + } + + // }}} + // {{{ random() + + /** + * return string to call a function to get random value inside an SQL statement + * + * @return return string to generate float between 0 and 1 + * @access public + */ + function random() + { + return 'dbms_random.value'; + } + + // }}}} + // {{{ guid() + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + * @access public + */ + function guid() + { + return 'SYS_GUID()'; + } + + // }}}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/pgsql.php b/lib/Pear/MDB2/Driver/Function/pgsql.php new file mode 100644 index 0000000..8b23ec6 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/pgsql.php @@ -0,0 +1,115 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: pgsql.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ + +require_once 'MDB2/Driver/Function/Common.php'; + +/** + * MDB2 MySQL driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common +{ + // {{{ executeStoredProc() + + /** + * Execute a stored procedure and return any results + * + * @param string $name string that identifies the function to execute + * @param mixed $params array that contains the paramaters to pass the stored proc + * @param mixed $types array that contains the types of the columns in + * the result set + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT * FROM '.$name; + $query .= $params ? '('.implode(', ', $params).')' : '()'; + return $db->query($query, $types, $result_class, $result_wrap_class); + } + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', TIMESTAMP '. $expression.'))'; + } + + // }}} + // {{{ random() + + /** + * return string to call a function to get random value inside an SQL statement + * + * @return return string to generate float between 0 and 1 + * @access public + */ + function random() + { + return 'RANDOM()'; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Function/sqlite.php b/lib/Pear/MDB2/Driver/Function/sqlite.php new file mode 100644 index 0000000..2761059 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Function/sqlite.php @@ -0,0 +1,162 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: sqlite.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ +// + +require_once 'MDB2/Driver/Function/Common.php'; + +/** + * MDB2 SQLite driver for the function modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common +{ + // {{{ constructor + + /** + * Constructor + */ + function __construct($db_index) + { + parent::__construct($db_index); + // create all sorts of UDFs + } + + // {{{ now() + + /** + * Return string to call a variable with the current timestamp inside an SQL statement + * There are three special variables for current date and time. + * + * @return string to call a variable with the current timestamp + * @access public + */ + function now($type = 'timestamp') + { + switch ($type) { + case 'time': + return 'time(\'now\')'; + case 'date': + return 'date(\'now\')'; + case 'timestamp': + default: + return 'datetime(\'now\')'; + } + } + + // }}} + // {{{ unixtimestamp() + + /** + * return string to call a function to get the unix timestamp from a iso timestamp + * + * @param string $expression + * + * @return string to call a variable with the timestamp + * @access public + */ + function unixtimestamp($expression) + { + return 'strftime("%s",'. $expression.', "utc")'; + } + + // }}} + // {{{ substring() + + /** + * return string to call a function to get a substring inside an SQL statement + * + * @return string to call a function to get a substring + * @access public + */ + function substring($value, $position = 1, $length = null) + { + if (!is_null($length)) { + return "substr($value,$position,$length)"; + } + return "substr($value,$position,length($value))"; + } + + // }}} + // {{{ random() + + /** + * return string to call a function to get random value inside an SQL statement + * + * @return return string to generate float between 0 and 1 + * @access public + */ + function random() + { + return '((RANDOM()+2147483648)/4294967296)'; + } + + // }}} + // {{{ replace() + + /** + * return string to call a function to get a replacement inside an SQL statement. + * + * @return string to call a function to get a replace + * @access public + */ + function replace($str, $from_str, $to_str) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + return $error; + } + + // }}} +} +?> diff --git a/lib/Pear/MDB2/Driver/Manager/Common.php b/lib/Pear/MDB2/Driver/Manager/Common.php new file mode 100644 index 0000000..672f577 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/Common.php @@ -0,0 +1,1010 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.71 2008/02/12 23:12:27 quipo Exp $ +// + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + * @author Lorenzo Alberton + */ + +/** + * Base class for the management modules that is extended by each MDB2 driver + * + * To load this module in the MDB2 object: + * $mdb->loadModule('Manager'); + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Manager_Common extends MDB2_Module_Common +{ + // {{{ splitTableSchema() + + /** + * Split the "[owner|schema].table" notation into an array + * @access private + */ + function splitTableSchema($table) + { + $ret = array(); + if (strpos($table, '.') !== false) { + return explode('.', $table); + } + return array(null, $table); + } + + // }}} + // {{{ getFieldDeclarationList() + + /** + * Get declaration of a number of field in bulk + * + * @param array $fields a multidimensional associative array. + * The first dimension determines the field name, while the second + * dimension is keyed with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * default + * Boolean value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return mixed string on success, a MDB2 error on failure + * @access public + */ + function getFieldDeclarationList($fields) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!is_array($fields) || empty($fields)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'missing any fields', __FUNCTION__); + } + foreach ($fields as $field_name => $field) { + $query = $db->getDeclaration($field['type'], $field_name, $field); + if (PEAR::isError($query)) { + return $query; + } + $query_fields[] = $query; + } + return implode(', ', $query_fields); + } + + // }}} + // {{{ _fixSequenceName() + + /** + * Removes any formatting in an sequence name using the 'seqname_format' option + * + * @param string $sqn string that containts name of a potential sequence + * @param bool $check if only formatted sequences should be returned + * @return string name of the sequence with possible formatting removed + * @access protected + */ + function _fixSequenceName($sqn, $check = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i'; + $seq_name = preg_replace($seq_pattern, '\\1', $sqn); + if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) { + return $seq_name; + } + if ($check) { + return false; + } + return $sqn; + } + + // }}} + // {{{ _fixIndexName() + + /** + * Removes any formatting in an index name using the 'idxname_format' option + * + * @param string $idx string that containts name of anl index + * @return string name of the index with eventual formatting removed + * @access protected + */ + function _fixIndexName($idx) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i'; + $idx_name = preg_replace($idx_pattern, '\\1', $idx); + if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) { + return $idx_name; + } + return $idx; + } + + // }}} + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($database, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ alterDatabase() + + /** + * alter an existing database + * + * @param string $name name of the database that should be created + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterDatabase($database, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($database) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ _getCreateTableQuery() + + /** + * Create a basic SQL query for a new table creation + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * @param array $options An associative array of table options + * + * @return mixed string (the SQL query) on success, a MDB2 error on failure + * @see createTable() + */ + function _getCreateTableQuery($name, $fields, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!$name) { + return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null, + 'no valid table name specified', __FUNCTION__); + } + if (empty($fields)) { + return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null, + 'no fields specified for table "'.$name.'"', __FUNCTION__); + } + $query_fields = $this->getFieldDeclarationList($fields); + if (PEAR::isError($query_fields)) { + return $query_fields; + } + if (!empty($options['primary'])) { + $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')'; + } + + $name = $db->quoteIdentifier($name, true); + $result = 'CREATE '; + if (!empty($options['temporary'])) { + $result .= $this->_getTemporaryTableQuery(); + } + $result .= " TABLE $name ($query_fields)"; + return $result; + } + + // }}} + // {{{ _getTemporaryTableQuery() + + /** + * A method to return the required SQL string that fits between CREATE ... TABLE + * to create the table as a temporary table. + * + * Should be overridden in driver classes to return the correct string for the + * specific database type. + * + * The default is to return the string "TEMPORARY" - this will result in a + * SQL error for any database that does not support temporary tables, or that + * requires a different SQL command from "CREATE TEMPORARY TABLE". + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + function _getTemporaryTableQuery() + { + return 'TEMPORARY'; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'temporary' => true|false, + * ); + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + $query = $this->_getCreateTableQuery($name, $fields, $options); + if (PEAR::isError($query)) { + return $query; + } + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + return MDB2_OK; + } + + // }}} + // {{{ dropTable() + + /** + * drop an existing table + * + * @param string $name name of the table that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("DROP TABLE $name"); + } + + // }}} + // {{{ truncateTable() + + /** + * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, + * it falls back to a DELETE FROM TABLE query) + * + * @param string $name name of the table that should be truncated + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function truncateTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("DELETE FROM $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @access public + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implementedd', __FUNCTION__); + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @param string database, the current is default + * NB: not all the drivers can get the view names from + * a database other than the current one + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listTableViews() + + /** + * list the views in the database that reference a given table + * + * @param string table for which all referenced views should be found + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listTableViews($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions in the current database + * + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @param string database, the current is default. + * NB: not all the drivers can get the table names from + * a database other than the current one + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ createIndex() + + /** + * Get the stucture of a field into an array + * + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function supports() to determine whether the DBMS driver can manage indexes. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ascending' + * ), + * 'last_login' => array() + * ) + * ) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createIndex($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "CREATE INDEX $name ON $table"; + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $fields) . ')'; + return $db->exec($query); + } + + // }}} + // {{{ dropIndex() + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropIndex($table, $name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($db->getIndexName($name), true); + return $db->exec("DROP INDEX $name"); + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + return ''; + } + + // }}} + // {{{ createConstraint() + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * The full structure of the array looks like this: + *
+     *          array (
+     *              [primary] => 0
+     *              [unique]  => 0
+     *              [foreign] => 1
+     *              [check]   => 0
+     *              [fields] => array (
+     *                  [field1name] => array() // one entry per each field covered
+     *                  [field2name] => array() // by the index
+     *                  [field3name] => array(
+     *                      [sorting]  => ascending
+     *                      [position] => 3
+     *                  )
+     *              )
+     *              [references] => array(
+     *                  [table] => name
+     *                  [fields] => array(
+     *                      [field1name] => array(  //one entry per each referenced field
+     *                           [position] => 1
+     *                      )
+     *                  )
+     *              )
+     *              [deferrable] => 0
+     *              [initiallydeferred] => 0
+     *              [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [match] => SIMPLE|PARTIAL|FULL
+     *          );
+     *          
+ * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createConstraint($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "ALTER TABLE $table ADD CONSTRAINT $name"; + if (!empty($definition['primary'])) { + $query.= ' PRIMARY KEY'; + } elseif (!empty($definition['unique'])) { + $query.= ' UNIQUE'; + } elseif (!empty($definition['foreign'])) { + $query.= ' FOREIGN KEY'; + } + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $fields) . ')'; + if (!empty($definition['foreign'])) { + $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true); + $referenced_fields = array(); + foreach (array_keys($definition['references']['fields']) as $field) { + $referenced_fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $referenced_fields) . ')'; + $query .= $this->_getAdvancedFKOptions($definition); + } + return $db->exec($query); + } + + // }}} + // {{{ dropConstraint() + + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropConstraint($table, $name, $primary = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + return $db->exec("ALTER TABLE $table DROP CONSTRAINT $name"); + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @param string database, the current is default + * NB: not all the drivers can get the sequence names from + * a database other than the current one + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/ibase.php b/lib/Pear/MDB2/Driver/Manager/ibase.php new file mode 100644 index 0000000..e40e1b5 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/ibase.php @@ -0,0 +1,1121 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: ibase.php,v 1.115 2008/02/22 19:50:01 quipo Exp $ + +require_once 'MDB2/Driver/Manager/Common.php'; + +/** + * MDB2 FireBird/InterBase driver for the management modules + * + * @package MDB2 + * @category Database + * @author Lorenzo Alberton + */ +class MDB2_Driver_Manager_ibase extends MDB2_Driver_Manager_Common +{ + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 'Create database', + 'PHP Interbase API does not support direct queries. You have to '. + 'create the db manually by using isql command or a similar program', __FUNCTION__); + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 'Drop database', + 'PHP Interbase API does not support direct queries. You have '. + 'to drop the db manually by using isql command or a similar program', __FUNCTION__); + } + + // }}} + // {{{ _silentCommit() + + /** + * conditional COMMIT query to make changes permanent, when auto + * @access private + */ + function _silentCommit() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if (!$db->in_transaction) { + @$db->exec('COMMIT'); + } + } + + // }}} + // {{{ _makeAutoincrement() + + /** + * add an autoincrement sequence + trigger + * + * @param string $name name of the PK field + * @param string $table name of the table + * @param string $start start value for the sequence + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _makeAutoincrement($name, $table, $start = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $mix_name = $table . '_' . $name; + if (is_null($start)) { + $db->beginTransaction(); + $query = 'SELECT MAX(' . $db->quoteIdentifier($name, true) . ') FROM ' . $db->quoteIdentifier($table, true); + $start = $this->db->queryOne($query, 'integer'); + if (PEAR::isError($start)) { + return $start; + } + ++$start; + $result = $db->manager->createSequence($mix_name, $start); + $db->commit(); + } else { + $result = $db->manager->createSequence($mix_name, $start); + } + if (PEAR::isError($result)) { + return $db->raiseError(null, null, null, + 'sequence for autoincrement PK could not be created', __FUNCTION__); + } + + $sequence_name = $db->getSequenceName($mix_name); + $trigger_name = $db->quoteIdentifier($mix_name . '_AI_PK', true); + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($name, true); + $trigger_sql = 'CREATE TRIGGER ' . $trigger_name . ' FOR ' . $table . ' + ACTIVE BEFORE INSERT POSITION 0 + AS + BEGIN + IF (NEW.' . $name . ' IS NULL OR NEW.' . $name . ' = 0) THEN + NEW.' . $name . ' = GEN_ID('.$sequence_name.', 1); + END'; + $result = $db->exec($trigger_sql); + if (PEAR::isError($result)) { + return $result; + } + $this->_silentCommit(); + return MDB2_OK; + } + + // }}} + // {{{ _dropAutoincrement() + + /** + * drop an existing autoincrement sequence + trigger + * + * @param string $table name of the table + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _dropAutoincrement($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $result = $db->manager->dropSequence($table); + if (PEAR::isError($result)) { + return $db->raiseError(null, null, null, + 'sequence for autoincrement PK could not be dropped', __FUNCTION__); + } + //remove autoincrement trigger associated with the table + $table = $db->quote(strtoupper($table), 'text'); + $trigger_name = $db->quote(strtoupper($table) . '_AI_PK', 'text'); + $trigger_name_old = $db->quote(strtoupper($table) . '_AUTOINCREMENT_PK', 'text'); + $query = "DELETE FROM RDB\$TRIGGERS + WHERE UPPER(RDB\$RELATION_NAME)=$table + AND (UPPER(RDB\$TRIGGER_NAME)=$trigger_name + OR UPPER(RDB\$TRIGGER_NAME)=$trigger_name_old)"; + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $db->raiseError(null, null, null, + 'trigger for autoincrement PK could not be dropped', __FUNCTION__); + } + return MDB2_OK; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * + * Example + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1, + * 'notnull' => 1, + * 'default' => 0, + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12, + * ), + * 'description' => array( + * 'type' => 'text', + * 'length' => 12, + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'temporary' => true|false, + * ); + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $query = $this->_getCreateTableQuery($name, $fields, $options); + if (PEAR::isError($query)) { + return $query; + } + + $options_strings = array(); + + if (!empty($options['comment'])) { + $options_strings['comment'] = '/* '.$db->quote($options['comment'], 'text'). ' */'; + } + + if (!empty($options_strings)) { + $query.= ' '.implode(' ', $options_strings); + } + + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + $this->_silentCommit(); + foreach ($fields as $field_name => $field) { + if (!empty($field['autoincrement'])) { + //create PK constraint + $pk_definition = array( + 'fields' => array($field_name => array()), + 'primary' => true, + ); + //$pk_name = $name.'_PK'; + $pk_name = null; + $result = $this->createConstraint($name, $pk_name, $pk_definition); + if (PEAR::isError($result)) { + return $result; + } + //create autoincrement sequence + trigger + return $this->_makeAutoincrement($field_name, $name, 1); + } + } + return MDB2_OK; + } + + // }}} + // {{{ checkSupportedChanges() + + /** + * Check if planned changes are supported + * + * @param string $name name of the database that should be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function checkSupportedChanges(&$changes) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'notnull': + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'it is not supported changes to field not null constraint', __FUNCTION__); + case 'default': + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'it is not supported changes to field default value', __FUNCTION__); + case 'length': + /* + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'it is not supported changes to field default length', __FUNCTION__); + */ + case 'unsigned': + case 'type': + case 'declaration': + case 'definition': + break; + default: + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'it is not supported change of type' . $change_name, __FUNCTION__); + } + } + return MDB2_OK; + } + + // }}} + // {{{ _getTemporaryTableQuery() + + /** + * A method to return the required SQL string that fits between CREATE ... TABLE + * to create the table as a temporary table. + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + function _getTemporaryTableQuery() + { + return 'GLOBAL TEMPORARY'; + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['onupdate'])) { + $query .= ' ON UPDATE '.$definition['onupdate']; + } + if (!empty($definition['ondelete'])) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + return $query; + } + + // }}} + // {{{ dropTable() + + /** + * drop an existing table + * + * @param string $name name of the table that should be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropTable($name) + { + $result = $this->_dropAutoincrement($name); + if (PEAR::isError($result)) { + return $result; + } + $result = parent::dropTable($name); + $this->_silentCommit(); + return $result; + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + // not needed in Interbase/Firebird + return MDB2_OK; + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + case 'remove': + case 'rename': + break; + case 'change': + foreach ($changes['change'] as $field) { + if (PEAR::isError($err = $this->checkSupportedChanges($field))) { + return $err; + } + } + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type ' . $change_name . ' not yet supported', __FUNCTION__); + } + } + if ($check) { + return MDB2_OK; + } + $query = ''; + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $query.= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); + } + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $field_name = $db->quoteIdentifier($field_name, true); + $query.= 'DROP ' . $field_name; + } + } + + if (!empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $field_name = $db->quoteIdentifier($field_name, true); + $query.= 'ALTER ' . $field_name . ' TO ' . $db->quoteIdentifier($field['name'], true); + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + // missing support to change DEFAULT and NULLability + foreach ($changes['change'] as $field_name => $field) { + if (PEAR::isError($err = $this->checkSupportedChanges($field))) { + return $err; + } + if ($query) { + $query.= ', '; + } + $db->loadModule('Datatype', null, true); + $field_name = $db->quoteIdentifier($field_name, true); + $query.= 'ALTER ' . $field_name.' TYPE ' . $db->datatype->getTypeDeclaration($field['definition']); + } + } + + if (!strlen($query)) { + return MDB2_OK; + } + + $name = $db->quoteIdentifier($name, true); + $result = $db->exec("ALTER TABLE $name $query"); + $this->_silentCommit(); + return $result; + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $query = 'SELECT RDB$RELATION_NAME + FROM RDB$RELATIONS + WHERE (RDB$SYSTEM_FLAG=0 OR RDB$SYSTEM_FLAG IS NULL) + AND RDB$VIEW_BLR IS NULL + ORDER BY RDB$RELATION_NAME'; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $table = $db->quote(strtoupper($table), 'text'); + $query = "SELECT RDB\$FIELD_NAME + FROM RDB\$RELATION_FIELDS + WHERE UPPER(RDB\$RELATION_NAME)=$table + AND (RDB\$SYSTEM_FLAG=0 OR RDB\$SYSTEM_FLAG IS NULL)"; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + return $db->queryCol('SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES'); + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->queryCol('SELECT DISTINCT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS'); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableViews() + + /** + * list the views in the database that reference a given table + * + * @param string table for which all referenced views should be found + * + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listTableViews($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT DISTINCT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS'; + $table = $db->quote(strtoupper($table), 'text'); + $query .= " WHERE UPPER(RDB\$RELATION_NAME)=$table"; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions (and stored procedures) in the current database + * + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT RDB$FUNCTION_NAME FROM RDB$FUNCTIONS WHERE (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0) + UNION + SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES'; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT RDB$TRIGGER_NAME + FROM RDB$TRIGGERS + WHERE (RDB$SYSTEM_FLAG IS NULL + OR RDB$SYSTEM_FLAG = 0)'; + if (!is_null($table)) { + $table = $db->quote(strtoupper($table), 'text'); + $query .= " AND UPPER(RDB\$RELATION_NAME)=$table"; + } + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ createIndex() + + /** + * Get the stucture of a field into an array + * + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function support() to determine whether the DBMS driver can manage indexes. + + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ascending' + * ), + * 'last_login' => array() + * ) + * ) + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createIndex($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $query = 'CREATE'; + + $query_sort = ''; + foreach ($definition['fields'] as $field) { + if (!strcmp($query_sort, '') && isset($field['sorting'])) { + switch ($field['sorting']) { + case 'ascending': + $query_sort = ' ASC'; + break; + case 'descending': + $query_sort = ' DESC'; + break; + } + } + } + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query .= $query_sort. " INDEX $name ON $table"; + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('.implode(', ', $fields) . ')'; + $result = $db->exec($query); + $this->_silentCommit(); + return $result; + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $table = $db->quote(strtoupper($table), 'text'); + $query = "SELECT RDB\$INDEX_NAME + FROM RDB\$INDICES + WHERE UPPER(RDB\$RELATION_NAME)=$table + AND (RDB\$SYSTEM_FLAG=0 OR RDB\$SYSTEM_FLAG IS NULL) + AND RDB\$UNIQUE_FLAG IS NULL + AND RDB\$FOREIGN_KEY IS NULL"; + $indexes = $db->queryCol($query, 'text'); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $index) { + $index = $this->_fixIndexName($index); + if (!empty($index)) { + $result[$index] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createConstraint() + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array(), + * ) + * ) + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createConstraint($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $table = $db->quoteIdentifier($table, true); + if (!empty($name)) { + $name = $db->quoteIdentifier($db->getIndexName($name), true); + } + $query = "ALTER TABLE $table ADD"; + if (!empty($definition['primary'])) { + if (!empty($name)) { + $query.= ' CONSTRAINT '.$name; + } + $query.= ' PRIMARY KEY'; + } else { + $query.= ' CONSTRAINT '. $name; + if (!empty($definition['unique'])) { + $query.= ' UNIQUE'; + } elseif (!empty($definition['foreign'])) { + $query.= ' FOREIGN KEY'; + } + } + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $fields) . ')'; + if (!empty($definition['foreign'])) { + $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true); + $referenced_fields = array(); + foreach (array_keys($definition['references']['fields']) as $field) { + $referenced_fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $referenced_fields) . ')'; + $query .= $this->_getAdvancedFKOptions($definition); + } + $result = $db->exec($query); + $this->_silentCommit(); + return $result; + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $table = $db->quote(strtoupper($table), 'text'); + $query = "SELECT RDB\$INDEX_NAME + FROM RDB\$INDICES + WHERE UPPER(RDB\$RELATION_NAME)=$table + AND ( + RDB\$UNIQUE_FLAG IS NOT NULL + OR RDB\$FOREIGN_KEY IS NOT NULL + )"; + $constraints = $db->queryCol($query); + if (PEAR::isError($constraints)) { + return $constraints; + } + + $result = array(); + foreach ($constraints as $constraint) { + $constraint = $this->_fixIndexName($constraint); + if (!empty($constraint)) { + $result[$constraint] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->getSequenceName($seq_name); + if (PEAR::isError($result = $db->exec('CREATE GENERATOR '.$sequence_name))) { + return $result; + } + if (PEAR::isError($result = $db->exec('SET GENERATOR '.$sequence_name.' TO '.($start-1)))) { + if (PEAR::isError($err = $db->dropSequence($seq_name))) { + return $db->raiseError($result, null, null, + 'Could not setup sequence start value and then it was not possible to drop it', __FUNCTION__); + } + } + return $result; + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->getSequenceName($seq_name); + $sequence_name = $db->quote($sequence_name, 'text'); + $query = "DELETE FROM RDB\$GENERATORS WHERE UPPER(RDB\$GENERATOR_NAME)=$sequence_name"; + return $db->exec($query); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS WHERE (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)'; + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + $result = array(); + foreach ($table_names as $table_name) { + $result[] = $this->_fixSequenceName($table_name); + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/mssql.php b/lib/Pear/MDB2/Driver/Manager/mssql.php new file mode 100644 index 0000000..fc260f8 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/mssql.php @@ -0,0 +1,1129 @@ + | +// | David Coallier | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: mssql.php,v 1.109 2008/03/05 12:55:57 afz Exp $ +// + +require_once 'MDB2/Driver/Manager/Common.php'; + +// {{{ class MDB2_Driver_Manager_mssql + +/** + * MDB2 MSSQL driver for the management modules + * + * @package MDB2 + * @category Database + * @author Frank M. Kromann + * @author David Coallier + * @author Lorenzo Alberton + */ +class MDB2_Driver_Manager_mssql extends MDB2_Driver_Manager_Common +{ + // {{{ createDatabase() + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = "CREATE DATABASE $name"; + if ($db->options['database_device']) { + $query.= ' ON '.$db->options['database_device']; + $query.= $db->options['database_size'] ? '=' . + $db->options['database_size'] : ''; + } + if (!empty($options['collation'])) { + $query .= ' COLLATE ' . $options['collation']; + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ alterDatabase() + + /** + * alter an existing database + * + * @param string $name name of the database that is intended to be changed + * @param array $options array with name, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = ''; + if (!empty($options['name'])) { + $query .= ' MODIFY NAME = ' .$db->quoteIdentifier($options['name'], true); + } + if (!empty($options['collation'])) { + $query .= ' COLLATE ' . $options['collation']; + } + if (!empty($query)) { + $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true) . $query; + return $db->standaloneQuery($query, null, true); + } + return MDB2_OK; + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->standaloneQuery("DROP DATABASE $name", null, true); + } + + // }}} + // {{{ _getTemporaryTableQuery() + + /** + * Override the parent method. + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + function _getTemporaryTableQuery() + { + return ''; + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['onupdate'])) { + $query .= ' ON UPDATE '.$definition['onupdate']; + } + if (!empty($definition['ondelete'])) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + return $query; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * + * Example + * array( + * + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1, + * 'notnull' => 1, + * 'default' => 0, + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12, + * ), + * 'description' => array( + * 'type' => 'text', + * 'length' => 12, + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'temporary' => true|false, + * ); + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + if (!empty($options['temporary'])) { + $name = '#'.$name; + } + return parent::createTable($name, $fields, $options); + } + + // }}} + // {{{ truncateTable() + + /** + * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, + * it falls back to a DELETE FROM TABLE query) + * + * @param string $name name of the table that should be truncated + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function truncateTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("TRUNCATE TABLE $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * NB: you have to run the NSControl Create utility to enable VACUUM + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $timeout = isset($options['timeout']) ? (int)$options['timeout'] : 300; + + $query = 'NSControl Create'; + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + + return $db->exec('EXEC NSVacuum '.$timeout); + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $name_quoted = $db->quoteIdentifier($name, true); + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'remove': + case 'rename': + case 'add': + case 'change': + case 'name': + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'" not yet supported', __FUNCTION__); + } + } + + if ($check) { + return MDB2_OK; + } + + $idxname_format = $db->getOption('idxname_format'); + $db->setOption('idxname_format', '%s'); + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + $result = $this->_dropConflictingIndices($name, array_keys($changes['remove'])); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + $result = $this->_dropConflictingConstraints($name, array_keys($changes['remove'])); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + + $query = ''; + foreach ($changes['remove'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $field_name = $db->quoteIdentifier($field_name, true); + $query.= 'COLUMN ' . $field_name; + } + + $result = $db->exec("ALTER TABLE $name_quoted DROP $query"); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + } + + if (!empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $field_name => $field) { + $field_name = $db->quoteIdentifier($field_name, true); + $result = $db->exec("sp_rename '$name_quoted.$field_name', '".$field['name']."', 'COLUMN'"); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + } + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + $query = ''; + foreach ($changes['add'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } else { + $query.= 'ADD '; + } + $query.= $db->getDeclaration($field['type'], $field_name, $field); + } + + $result = $db->exec("ALTER TABLE $name_quoted $query"); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + } + + $dropped_indices = array(); + $dropped_constraints = array(); + + if (!empty($changes['change']) && is_array($changes['change'])) { + $dropped = $this->_dropConflictingIndices($name, array_keys($changes['change'])); + if (PEAR::isError($dropped)) { + $db->setOption('idxname_format', $idxname_format); + return $dropped; + } + $dropped_indices = array_merge($dropped_indices, $dropped); + $dropped = $this->_dropConflictingConstraints($name, array_keys($changes['change'])); + if (PEAR::isError($dropped)) { + $db->setOption('idxname_format', $idxname_format); + return $dropped; + } + $dropped_constraints = array_merge($dropped_constraints, $dropped); + + foreach ($changes['change'] as $field_name => $field) { + //MSSQL doesn't allow multiple ALTER COLUMNs in one query + $query = 'ALTER COLUMN '; + + //MSSQL doesn't allow changing the DEFAULT value of a field in altering mode + if (array_key_exists('default', $field['definition'])) { + unset($field['definition']['default']); + } + + $query .= $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']); + $result = $db->exec("ALTER TABLE $name_quoted $query"); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + } + } + + // restore the dropped conflicting indices and constraints + foreach ($dropped_indices as $index_name => $index) { + $result = $this->createIndex($name, $index_name, $index); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + } + foreach ($dropped_constraints as $constraint_name => $constraint) { + $result = $this->createConstraint($name, $constraint_name, $constraint); + if (PEAR::isError($result)) { + $db->setOption('idxname_format', $idxname_format); + return $result; + } + } + + $db->setOption('idxname_format', $idxname_format); + + if (!empty($changes['name'])) { + $new_name = $db->quoteIdentifier($changes['name'], true); + $result = $db->exec("sp_rename '$name_quoted', '$new_name'"); + if (PEAR::isError($result)) { + return $result; + } + } + + return MDB2_OK; + } + + // }}} + // {{{ _dropConflictingIndices() + + /** + * Drop the indices that prevent a successful ALTER TABLE action + * + * @param string $table table name + * @param array $fields array of names of the fields affected by the change + * + * @return array dropped indices definitions + */ + function _dropConflictingIndices($table, $fields) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $dropped = array(); + $index_names = $this->listTableIndexes($table); + if (PEAR::isError($index_names)) { + return $index_names; + } + $db->loadModule('Reverse'); + $indexes = array(); + foreach ($index_names as $index_name) { + $idx_def = $db->reverse->getTableIndexDefinition($table, $index_name); + if (!PEAR::isError($idx_def)) { + $indexes[$index_name] = $idx_def; + } + } + foreach ($fields as $field_name) { + foreach ($indexes as $index_name => $index) { + if (!isset($dropped[$index_name]) && array_key_exists($field_name, $index['fields'])) { + $dropped[$index_name] = $index; + $result = $this->dropIndex($table, $index_name); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + + return $dropped; + } + + // }}} + // {{{ _dropConflictingConstraints() + + /** + * Drop the constraints that prevent a successful ALTER TABLE action + * + * @param string $table table name + * @param array $fields array of names of the fields affected by the change + * + * @return array dropped constraints definitions + */ + function _dropConflictingConstraints($table, $fields) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $dropped = array(); + $constraint_names = $this->listTableConstraints($table); + if (PEAR::isError($constraint_names)) { + return $constraint_names; + } + $db->loadModule('Reverse'); + $constraints = array(); + foreach ($constraint_names as $constraint_name) { + $cons_def = $db->reverse->getTableConstraintDefinition($table, $constraint_name); + if (!PEAR::isError($cons_def)) { + $constraints[$constraint_name] = $cons_def; + } + } + foreach ($fields as $field_name) { + foreach ($constraints as $constraint_name => $constraint) { + if (!isset($dropped[$constraint_name]) && array_key_exists($field_name, $constraint['fields'])) { + $dropped[$constraint_name] = $constraint; + $result = $this->dropConstraint($table, $constraint_name); + if (PEAR::isError($result)) { + return $result; + } + } + } + // also drop implicit DEFAULT constraints + $default = $this->_getTableFieldDefaultConstraint($table, $field_name); + if (!PEAR::isError($default) && !empty($default)) { + $result = $this->dropConstraint($table, $default); + if (PEAR::isError($result)) { + return $result; + } + } + } + + return $dropped; + } + + // }}} + // {{{ _getTableFieldDefaultConstraint() + + /** + * Get the default constraint for a table field + * + * @param string $table name of table that should be used in method + * @param string $field name of field that should be used in method + * + * @return mixed name of default constraint on success, a MDB2 error on failure + * @access private + */ + function _getTableFieldDefaultConstraint($table, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $field = $db->quote($field, 'text'); + $query = "SELECT OBJECT_NAME(syscolumns.cdefault) + FROM syscolumns + WHERE syscolumns.id = object_id('$table') + AND syscolumns.name = $field + AND syscolumns.cdefault <> 0"; + return $db->queryOne($query); + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables() + { + $db =& $this->getDBInstance(); + + if (PEAR::isError($db)) { + return $db; + } + + $query = 'EXEC sp_tables @table_type = "\'TABLE\'"'; + $table_names = $db->queryCol($query, null, 2); + if (PEAR::isError($table_names)) { + return $table_names; + } + $result = array(); + foreach ($table_names as $table_name) { + if (!$this->_fixSequenceName($table_name, true)) { + $result[] = $table_name; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? + 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $columns = $db->queryCol("SELECT c.name + FROM syscolumns c + LEFT JOIN sysobjects o ON c.id = o.id + WHERE o.name = '$table'"); + if (PEAR::isError($columns)) { + return $columns; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $columns); + } + return $columns; + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $key_name = 'INDEX_NAME'; + $pk_name = 'PK_NAME'; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + $pk_name = strtolower($pk_name); + } else { + $key_name = strtoupper($key_name); + $pk_name = strtoupper($pk_name); + } + } + $table = $db->quote($table, 'text'); + $query = "EXEC sp_statistics @table_name=$table"; + $indexes = $db->queryCol($query, 'text', $key_name); + if (PEAR::isError($indexes)) { + return $indexes; + } + $query = "EXEC sp_pkeys @table_name=$table"; + $pk_all = $db->queryCol($query, 'text', $pk_name); + $result = array(); + foreach ($indexes as $index) { + if (!in_array($index, $pk_all) && ($index = $this->_fixIndexName($index))) { + $result[$index] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->queryCol('SELECT name FROM sys.databases'); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->queryCol('SELECT DISTINCT loginame FROM master..sysprocesses'); + if (PEAR::isError($result) || empty($result)) { + return $result; + } + foreach (array_keys($result) as $k) { + $result[$k] = trim($result[$k]); + } + return $result; + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions in the current database + * + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name + FROM sysobjects + WHERE objectproperty(id, N'IsMSShipped') = 0 + AND (objectproperty(id, N'IsTableFunction') = 1 + OR objectproperty(id, N'IsScalarFunction') = 1)"; + /* + SELECT ROUTINE_NAME + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_TYPE = 'FUNCTION' + */ + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * + * @return mixed array of trigger names on success, otherwise, false which + * could be a db error if the db is not instantiated or could + * be the results of the error that occured during the + * querying of the sysobject module. + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quote($table, 'text'); + $query = "SELECT o.name + FROM sysobjects o + WHERE xtype = 'TR' + AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0"; + if (!is_null($table)) { + $query .= " AND object_name(parent_obj) = $table"; + } + + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE && + $db->options['field_case'] == CASE_LOWER) + { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? + 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @param string database, the current is default + * + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name + FROM sysobjects + WHERE xtype = 'V'"; + /* + SELECT * + FROM sysobjects + WHERE objectproperty(id, N'IsMSShipped') = 0 + AND objectproperty(id, N'IsView') = 1 + */ + + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE && + $db->options['field_case'] == CASE_LOWER) + { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? + 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ dropIndex() + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropIndex($table, $name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + return $db->exec("DROP INDEX $table.$name"); + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $table = $db->quoteIdentifier($table, true); + + $query = "SELECT c.constraint_name + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c + WHERE c.constraint_catalog = DB_NAME() + AND c.table_name = '$table'"; + $constraints = $db->queryCol($query); + if (PEAR::isError($constraints)) { + return $constraints; + } + + $result = array(); + foreach ($constraints as $constraint) { + $constraint = $this->_fixIndexName($constraint); + if (!empty($constraint)) { + $result[$constraint] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true); + $query = "CREATE TABLE $sequence_name ($seqcol_name " . + "INT PRIMARY KEY CLUSTERED IDENTITY($start,1) NOT NULL)"; + + $res = $db->exec($query); + if (PEAR::isError($res)) { + return $res; + } + + $query = "SET IDENTITY_INSERT $sequence_name ON ". + "INSERT INTO $sequence_name ($seqcol_name) VALUES ($start)"; + $res = $db->exec($query); + + if (!PEAR::isError($res)) { + return MDB2_OK; + } + + $result = $db->exec("DROP TABLE $sequence_name"); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'could not drop inconsistent sequence table', __FUNCTION__); + } + + return $db->raiseError($res, null, null, + 'could not create sequence table', __FUNCTION__); + } + + // }}} + // {{{ dropSequence() + + /** + * This function drops an existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("DROP TABLE $sequence_name"); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM sysobjects WHERE xtype = 'U'"; + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + $result = array(); + foreach ($table_names as $table_name) { + if ($sqn = $this->_fixSequenceName($table_name, true)) { + $result[] = $sqn; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? + 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} +} + +// }}} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/mysql.php b/lib/Pear/MDB2/Driver/Manager/mysql.php new file mode 100644 index 0000000..a055d8d --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/mysql.php @@ -0,0 +1,1418 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.108 2008/03/11 19:58:12 quipo Exp $ +// + +require_once 'MDB2/Driver/Manager/Common.php'; + +/** + * MDB2 MySQL driver for the management modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common +{ + + // }}} + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = 'CREATE DATABASE ' . $name; + if (!empty($options['charset'])) { + $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); + } + if (!empty($options['collation'])) { + $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ alterDatabase() + + /** + * alter an existing database + * + * @param string $name name of the database that is intended to be changed + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); + if (!empty($options['charset'])) { + $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); + } + if (!empty($options['collation'])) { + $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = "DROP DATABASE $name"; + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['match'])) { + $query .= ' MATCH '.$definition['match']; + } + if (!empty($definition['onupdate'])) { + $query .= ' ON UPDATE '.$definition['onupdate']; + } + if (!empty($definition['ondelete'])) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + return $query; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + // if we have an AUTO_INCREMENT column and a PK on more than one field, + // we have to handle it differently... + $autoincrement = null; + if (empty($options['primary'])) { + $pk_fields = array(); + foreach ($fields as $fieldname => $def) { + if (!empty($def['primary'])) { + $pk_fields[$fieldname] = true; + } + if (!empty($def['autoincrement'])) { + $autoincrement = $fieldname; + } + } + if (!is_null($autoincrement) && count($pk_fields) > 1) { + $options['primary'] = $pk_fields; + } else { + // the PK constraint is on max one field => OK + $autoincrement = null; + } + } + + $query = $this->_getCreateTableQuery($name, $fields, $options); + if (PEAR::isError($query)) { + return $query; + } + + if (!is_null($autoincrement)) { + // we have to remove the PK clause added by _getIntegerDeclaration() + $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query); + } + + $options_strings = array(); + + if (!empty($options['comment'])) { + $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text'); + } + + if (!empty($options['charset'])) { + $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset']; + if (!empty($options['collate'])) { + $options_strings['charset'].= ' COLLATE '.$options['collate']; + } + } + + $type = false; + if (!empty($options['type'])) { + $type = $options['type']; + } elseif ($db->options['default_table_type']) { + $type = $db->options['default_table_type']; + } + if ($type) { + $options_strings[] = "ENGINE = $type"; + } + + if (!empty($options_strings)) { + $query .= ' '.implode(' ', $options_strings); + } + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + return MDB2_OK; + } + + // }}} + // {{{ dropTable() + + /** + * drop an existing table + * + * @param string $name name of the table that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + //delete the triggers associated to existing FK constraints + $constraints = $this->listTableConstraints($name); + if (!PEAR::isError($constraints) && !empty($constraints)) { + $db->loadModule('Reverse', null, true); + foreach ($constraints as $constraint) { + $definition = $db->reverse->getTableConstraintDefinition($name, $constraint); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + + return parent::dropTable($name); + } + + // }}} + // {{{ truncateTable() + + /** + * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, + * it falls back to a DELETE FROM TABLE query) + * + * @param string $name name of the table that should be truncated + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function truncateTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("TRUNCATE TABLE $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($table)) { + $table = $this->listTables(); + if (PEAR::isError($table)) { + return $table; + } + } + if (is_array($table)) { + foreach (array_keys($table) as $k) { + $table[$k] = $db->quoteIdentifier($table[$k], true); + } + $table = implode(', ', $table); + } else { + $table = $db->quoteIdentifier($table, true); + } + + $result = $db->exec('OPTIMIZE TABLE '.$table); + if (PEAR::isError($result)) { + return $result; + } + if (!empty($options['analyze'])) { + return $db->exec('ANALYZE TABLE '.$table); + } + return MDB2_OK; + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @access public + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + case 'remove': + case 'change': + case 'rename': + case 'name': + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'" not yet supported', __FUNCTION__); + } + } + + if ($check) { + return MDB2_OK; + } + + $query = ''; + if (!empty($changes['name'])) { + $change_name = $db->quoteIdentifier($changes['name'], true); + $query .= 'RENAME TO ' . $change_name; + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $query.= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); + } + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $field_name = $db->quoteIdentifier($field_name, true); + $query.= 'DROP ' . $field_name; + } + } + + $rename = array(); + if (!empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $field_name => $field) { + $rename[$field['name']] = $field_name; + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + if (isset($rename[$field_name])) { + $old_field_name = $rename[$field_name]; + unset($rename[$field_name]); + } else { + $old_field_name = $field_name; + } + $old_field_name = $db->quoteIdentifier($old_field_name, true); + $query.= "CHANGE $old_field_name " . $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']); + } + } + + if (!empty($rename) && is_array($rename)) { + foreach ($rename as $rename_name => $renamed_field) { + if ($query) { + $query.= ', '; + } + $field = $changes['rename'][$renamed_field]; + $renamed_field = $db->quoteIdentifier($renamed_field, true); + $query.= 'CHANGE ' . $renamed_field . ' ' . $db->getDeclaration($field['definition']['type'], $field['name'], $field['definition']); + } + } + + if (!$query) { + return MDB2_OK; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("ALTER TABLE $name $query"); + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->queryCol('SHOW DATABASES'); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->queryCol('SELECT DISTINCT USER FROM mysql.USER'); + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions in the current database + * + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM mysql.proc"; + /* + SELECT ROUTINE_NAME + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_TYPE = 'FUNCTION' + */ + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SHOW TRIGGERS'; + if (!is_null($table)) { + $table = $db->quote($table, 'text'); + $query .= " LIKE $table"; + } + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @param string database, the current is default + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SHOW /*!50002 FULL*/ TABLES"; + if (!is_null($database)) { + $query .= " FROM $database"; + } + $query.= "/*!50002 WHERE Table_type = 'BASE TABLE'*/"; + + $table_names = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED); + if (PEAR::isError($table_names)) { + return $table_names; + } + + $result = array(); + foreach ($table_names as $table) { + if (!$this->_fixSequenceName($table[0], true)) { + $result[] = $table[0]; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @param string database, the current is default + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SHOW FULL TABLES'; + if (!is_null($database)) { + $query.= " FROM $database"; + } + $query.= " WHERE Table_type = 'VIEW'"; + + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $result = $db->queryCol("SHOW COLUMNS FROM $table"); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ createIndex() + + /** + * Get the stucture of a field into an array + * + * @author Leoncx + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function supports() to determine whether the DBMS driver can manage indexes. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ascending' + * 'length' => 10 + * ), + * 'last_login' => array() + * ) + * ) + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createIndex($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "CREATE INDEX $name ON $table"; + $fields = array(); + foreach ($definition['fields'] as $field => $fieldinfo) { + if (!empty($fieldinfo['length'])) { + $fields[] = $db->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')'; + } else { + $fields[] = $db->quoteIdentifier($field, true); + } + } + $query .= ' ('. implode(', ', $fields) . ')'; + return $db->exec($query); + } + + // }}} + // {{{ dropIndex() + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropIndex($table, $name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + return $db->exec("DROP INDEX $name ON $table"); + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $key_name = 'Key_name'; + $non_unique = 'Non_unique'; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + $non_unique = strtolower($non_unique); + } else { + $key_name = strtoupper($key_name); + $non_unique = strtoupper($non_unique); + } + } + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW INDEX FROM $table"; + $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $index_data) { + if ($index_data[$non_unique] && ($index = $this->_fixIndexName($index_data[$key_name]))) { + $result[$index] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createConstraint() + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array() + * ) + * ) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createConstraint($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $type = ''; + $name = $db->quoteIdentifier($db->getIndexName($name), true); + if (!empty($definition['primary'])) { + $type = 'PRIMARY'; + $name = 'KEY'; + } elseif (!empty($definition['unique'])) { + $type = 'UNIQUE'; + } elseif (!empty($definition['foreign'])) { + $type = 'CONSTRAINT'; + } + if (empty($type)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'invalid definition, could not create constraint', __FUNCTION__); + } + + $table_quoted = $db->quoteIdentifier($table, true); + $query = "ALTER TABLE $table_quoted ADD $type $name"; + if (!empty($definition['foreign'])) { + $query .= ' FOREIGN KEY'; + } + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $fields) . ')'; + if (!empty($definition['foreign'])) { + $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true); + $referenced_fields = array(); + foreach (array_keys($definition['references']['fields']) as $field) { + $referenced_fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $referenced_fields) . ')'; + $query .= $this->_getAdvancedFKOptions($definition); + } + $res = $db->exec($query); + if (PEAR::isError($res)) { + return $res; + } + if (!empty($definition['foreign'])) { + return $this->_createFKTriggers($table, array($name => $definition)); + } + return MDB2_OK; + } + + // }}} + // {{{ dropConstraint() + + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropConstraint($table, $name, $primary = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($primary || strtolower($name) == 'primary') { + $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY'; + return $db->exec($query); + } + + //is it a FK constraint? If so, also delete the associated triggers + $db->loadModule('Reverse', null, true); + $definition = $db->reverse->getTableConstraintDefinition($table, $name); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + //first drop the FK enforcing triggers + $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + //then drop the constraint itself + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "ALTER TABLE $table DROP FOREIGN KEY $name"; + return $db->exec($query); + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "ALTER TABLE $table DROP INDEX $name"; + return $db->exec($query); + } + + // }}} + // {{{ _createFKTriggers() + + /** + * Create triggers to enforce the FOREIGN KEY constraint on the table + * + * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql, + * we call a non-existent procedure to raise the FK violation message. + * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877 + * + * @param string $table table name + * @param array $foreign_keys FOREIGN KEY definitions + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _createFKTriggers($table, $foreign_keys) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + // create triggers to enforce FOREIGN KEY constraints + if ($db->supports('triggers') && !empty($foreign_keys)) { + $table = $db->quoteIdentifier($table, true); + foreach ($foreign_keys as $fkname => $fkdef) { + if (empty($fkdef)) { + continue; + } + //set actions to 'RESTRICT' if not set + $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']); + $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']); + + $trigger_names = array( + 'insert' => $fkname.'_insert_trg', + 'update' => $fkname.'_update_trg', + 'pk_update' => $fkname.'_pk_update_trg', + 'pk_delete' => $fkname.'_pk_delete_trg', + ); + $table_fields = array_keys($fkdef['fields']); + $referenced_fields = array_keys($fkdef['references']['fields']); + + //create the ON [UPDATE|DELETE] triggers on the primary table + $restrict_action = ' IF (SELECT '; + $aliased_fields = array(); + foreach ($table_fields as $field) { + $aliased_fields[] = $table .'.'.$field .' AS '.$field; + } + $restrict_action .= implode(',', $aliased_fields) + .' FROM '.$table + .' WHERE '; + $conditions = array(); + $new_values = array(); + $null_values = array(); + for ($i=0; $iloadModule('Reverse', null, true); + $default_values = array(); + foreach ($table_fields as $table_field) { + $field_definition = $db->reverse->getTableFieldDefinition($table, $field); + if (PEAR::isError($field_definition)) { + return $field_definition; + } + $default_values[] = $table_field .' = '. $field_definition[0]['default']; + } + $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';'; + } + + $query = 'CREATE TRIGGER %s' + .' %s ON '.$fkdef['references']['table'] + .' FOR EACH ROW BEGIN ' + .' SET FOREIGN_KEY_CHECKS = 0; '; //only really needed for ON UPDATE CASCADE + + if ('CASCADE' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $cascade_action_update; + } elseif ('SET NULL' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action; + } elseif ('SET DEFAULT' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action; + } elseif ('NO ACTION' == $fkdef['onupdate']) { + $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update'); + } else { + //'RESTRICT' + $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update'); + } + if ('CASCADE' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $cascade_action_delete; + } elseif ('SET NULL' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action; + } elseif ('SET DEFAULT' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action; + } elseif ('NO ACTION' == $fkdef['ondelete']) { + $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete'); + } else { + //'RESTRICT' + $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete'); + } + $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; + $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; + + $db->pushErrorHandling(PEAR_ERROR_RETURN); + $db->expectError(MDB2_ERROR_CANNOT_CREATE); + $result = $db->exec($sql_delete); + $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table'; + $db->popExpect(); + $db->popErrorHandling(); + if (PEAR::isError($result)) { + if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { + return $result; + } + $db->warnings[] = $expected_errmsg; + } + $db->pushErrorHandling(PEAR_ERROR_RETURN); + $db->expectError(MDB2_ERROR_CANNOT_CREATE); + $result = $db->exec($sql_update); + $db->popExpect(); + $db->popErrorHandling(); + if (PEAR::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) { + if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { + return $result; + } + $db->warnings[] = $expected_errmsg; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ _dropFKTriggers() + + /** + * Drop the triggers created to enforce the FOREIGN KEY constraint on the table + * + * @param string $table table name + * @param string $fkname FOREIGN KEY constraint name + * @param string $referenced_table referenced table name + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _dropFKTriggers($table, $fkname, $referenced_table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $triggers = $this->listTableTriggers($table); + $triggers2 = $this->listTableTriggers($referenced_table); + if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) { + $triggers = array_merge($triggers, $triggers2); + $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i'; + foreach ($triggers as $trigger) { + if (preg_match($pattern, $trigger)) { + $result = $db->exec('DROP TRIGGER '.$trigger); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $key_name = 'Key_name'; + $non_unique = 'Non_unique'; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + $non_unique = strtolower($non_unique); + } else { + $key_name = strtoupper($key_name); + $non_unique = strtoupper($non_unique); + } + } + + $query = 'SHOW INDEX FROM ' . $db->quoteIdentifier($table, true); + $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $index_data) { + if (!$index_data[$non_unique]) { + if ($index_data[$key_name] !== 'PRIMARY') { + $index = $this->_fixIndexName($index_data[$key_name]); + } else { + $index = 'PRIMARY'; + } + if (!empty($index)) { + $result[$index] = true; + } + } + } + + //list FOREIGN KEY constraints... + $query = 'SHOW CREATE TABLE '. $db->escape($table); + $definition = $db->queryOne($query, 'text', 1); + if (!PEAR::isError($definition) && !empty($definition)) { + $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims'; + if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) { + foreach ($matches[1] as $constraint) { + $result[$constraint] = true; + } + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true); + + $options_strings = array(); + + if (!empty($options['comment'])) { + $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text'); + } + + if (!empty($options['charset'])) { + $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset']; + if (!empty($options['collate'])) { + $options_strings['charset'].= ' COLLATE '.$options['collate']; + } + } + + $type = false; + if (!empty($options['type'])) { + $type = $options['type']; + } elseif ($db->options['default_table_type']) { + $type = $db->options['default_table_type']; + } + if ($type) { + $options_strings[] = "ENGINE = $type"; + } + + $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))"; + if (!empty($options_strings)) { + $query .= ' '.implode(' ', $options_strings); + } + $res = $db->exec($query); + if (PEAR::isError($res)) { + return $res; + } + + if ($start == 1) { + return MDB2_OK; + } + + $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')'; + $res = $db->exec($query); + if (!PEAR::isError($res)) { + return MDB2_OK; + } + + // Handle error + $result = $db->exec("DROP TABLE $sequence_name"); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'could not drop inconsistent sequence table', __FUNCTION__); + } + + return $db->raiseError($res, null, null, + 'could not create sequence table', __FUNCTION__); + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("DROP TABLE $sequence_name"); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @param string database, the current is default + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SHOW TABLES"; + if (!is_null($database)) { + $query .= " FROM $database"; + } + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + + $result = array(); + foreach ($table_names as $table_name) { + if ($sqn = $this->_fixSequenceName($table_name, true)) { + $result[] = $sqn; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/mysqli.php b/lib/Pear/MDB2/Driver/Manager/mysqli.php new file mode 100644 index 0000000..db4f875 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/mysqli.php @@ -0,0 +1,1418 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysqli.php,v 1.95 2008/03/11 19:58:12 quipo Exp $ +// + +require_once 'MDB2/Driver/Manager/Common.php'; + +/** + * MDB2 MySQLi driver for the management modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common +{ + + // }}} + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = 'CREATE DATABASE ' . $name; + if (!empty($options['charset'])) { + $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); + } + if (!empty($options['collation'])) { + $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ alterDatabase() + + /** + * alter an existing database + * + * @param string $name name of the database that is intended to be changed + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); + if (!empty($options['charset'])) { + $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); + } + if (!empty($options['collation'])) { + $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = "DROP DATABASE $name"; + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['match'])) { + $query .= ' MATCH '.$definition['match']; + } + if (!empty($definition['onupdate'])) { + $query .= ' ON UPDATE '.$definition['onupdate']; + } + if (!empty($definition['ondelete'])) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + return $query; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + // if we have an AUTO_INCREMENT column and a PK on more than one field, + // we have to handle it differently... + $autoincrement = null; + if (empty($options['primary'])) { + $pk_fields = array(); + foreach ($fields as $fieldname => $def) { + if (!empty($def['primary'])) { + $pk_fields[$fieldname] = true; + } + if (!empty($def['autoincrement'])) { + $autoincrement = $fieldname; + } + } + if (!is_null($autoincrement) && count($pk_fields) > 1) { + $options['primary'] = $pk_fields; + } else { + // the PK constraint is on max one field => OK + $autoincrement = null; + } + } + + $query = $this->_getCreateTableQuery($name, $fields, $options); + if (PEAR::isError($query)) { + return $query; + } + + if (!is_null($autoincrement)) { + // we have to remove the PK clause added by _getIntegerDeclaration() + $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query); + } + + $options_strings = array(); + + if (!empty($options['comment'])) { + $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text'); + } + + if (!empty($options['charset'])) { + $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset']; + if (!empty($options['collate'])) { + $options_strings['charset'].= ' COLLATE '.$options['collate']; + } + } + + $type = false; + if (!empty($options['type'])) { + $type = $options['type']; + } elseif ($db->options['default_table_type']) { + $type = $db->options['default_table_type']; + } + if ($type) { + $options_strings[] = "ENGINE = $type"; + } + + if (!empty($options_strings)) { + $query .= ' '.implode(' ', $options_strings); + } + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + return MDB2_OK; + } + + // }}} + // {{{ dropTable() + + /** + * drop an existing table + * + * @param string $name name of the table that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + //delete the triggers associated to existing FK constraints + $constraints = $this->listTableConstraints($name); + if (!PEAR::isError($constraints) && !empty($constraints)) { + $db->loadModule('Reverse', null, true); + foreach ($constraints as $constraint) { + $definition = $db->reverse->getTableConstraintDefinition($name, $constraint); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + + return parent::dropTable($name); + } + + // }}} + // {{{ truncateTable() + + /** + * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, + * it falls back to a DELETE FROM TABLE query) + * + * @param string $name name of the table that should be truncated + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function truncateTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("TRUNCATE TABLE $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($table)) { + $table = $this->listTables(); + if (PEAR::isError($table)) { + return $table; + } + } + if (is_array($table)) { + foreach (array_keys($table) as $k) { + $table[$k] = $db->quoteIdentifier($table[$k], true); + } + $table = implode(', ', $table); + } else { + $table = $db->quoteIdentifier($table, true); + } + + $result = $db->exec('OPTIMIZE TABLE '.$table); + if (PEAR::isError($result)) { + return $result; + } + if (!empty($options['analyze'])) { + return $db->exec('ANALYZE TABLE '.$table); + } + return MDB2_OK; + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @access public + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + case 'remove': + case 'change': + case 'rename': + case 'name': + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'" not yet supported', __FUNCTION__); + } + } + + if ($check) { + return MDB2_OK; + } + + $query = ''; + if (!empty($changes['name'])) { + $change_name = $db->quoteIdentifier($changes['name'], true); + $query .= 'RENAME TO ' . $change_name; + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $query.= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); + } + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + $field_name = $db->quoteIdentifier($field_name, true); + $query.= 'DROP ' . $field_name; + } + } + + $rename = array(); + if (!empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $field_name => $field) { + $rename[$field['name']] = $field_name; + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $field_name => $field) { + if ($query) { + $query.= ', '; + } + if (isset($rename[$field_name])) { + $old_field_name = $rename[$field_name]; + unset($rename[$field_name]); + } else { + $old_field_name = $field_name; + } + $old_field_name = $db->quoteIdentifier($old_field_name, true); + $query.= "CHANGE $old_field_name " . $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']); + } + } + + if (!empty($rename) && is_array($rename)) { + foreach ($rename as $rename_name => $renamed_field) { + if ($query) { + $query.= ', '; + } + $field = $changes['rename'][$renamed_field]; + $renamed_field = $db->quoteIdentifier($renamed_field, true); + $query.= 'CHANGE ' . $renamed_field . ' ' . $db->getDeclaration($field['definition']['type'], $field['name'], $field['definition']); + } + } + + if (!$query) { + return MDB2_OK; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("ALTER TABLE $name $query"); + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->queryCol('SHOW DATABASES'); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->queryCol('SELECT DISTINCT USER FROM mysql.USER'); + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions in the current database + * + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM mysql.proc"; + /* + SELECT ROUTINE_NAME + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_TYPE = 'FUNCTION' + */ + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SHOW TRIGGERS'; + if (!is_null($table)) { + $table = $db->quote($table, 'text'); + $query .= " LIKE $table"; + } + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @param string database, the current is default + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SHOW /*!50002 FULL*/ TABLES"; + if (!is_null($database)) { + $query .= " FROM $database"; + } + $query.= "/*!50002 WHERE Table_type = 'BASE TABLE'*/"; + + $table_names = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED); + if (PEAR::isError($table_names)) { + return $table_names; + } + + $result = array(); + foreach ($table_names as $table) { + if (!$this->_fixSequenceName($table[0], true)) { + $result[] = $table[0]; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @param string database, the current is default + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SHOW FULL TABLES'; + if (!is_null($database)) { + $query.= " FROM $database"; + } + $query.= " WHERE Table_type = 'VIEW'"; + + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $result = $db->queryCol("SHOW COLUMNS FROM $table"); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ createIndex() + + /** + * Get the stucture of a field into an array + * + * @author Leoncx + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function supports() to determine whether the DBMS driver can manage indexes. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ascending' + * 'length' => 10 + * ), + * 'last_login' => array() + * ) + * ) + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createIndex($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "CREATE INDEX $name ON $table"; + $fields = array(); + foreach ($definition['fields'] as $field => $fieldinfo) { + if (!empty($fieldinfo['length'])) { + $fields[] = $db->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')'; + } else { + $fields[] = $db->quoteIdentifier($field, true); + } + } + $query .= ' ('. implode(', ', $fields) . ')'; + return $db->exec($query); + } + + // }}} + // {{{ dropIndex() + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropIndex($table, $name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + return $db->exec("DROP INDEX $name ON $table"); + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $key_name = 'Key_name'; + $non_unique = 'Non_unique'; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + $non_unique = strtolower($non_unique); + } else { + $key_name = strtoupper($key_name); + $non_unique = strtoupper($non_unique); + } + } + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW INDEX FROM $table"; + $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $index_data) { + if ($index_data[$non_unique] && ($index = $this->_fixIndexName($index_data[$key_name]))) { + $result[$index] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createConstraint() + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array() + * ) + * ) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createConstraint($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $type = ''; + $name = $db->quoteIdentifier($db->getIndexName($name), true); + if (!empty($definition['primary'])) { + $type = 'PRIMARY'; + $name = 'KEY'; + } elseif (!empty($definition['unique'])) { + $type = 'UNIQUE'; + } elseif (!empty($definition['foreign'])) { + $type = 'CONSTRAINT'; + } + if (empty($type)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'invalid definition, could not create constraint', __FUNCTION__); + } + + $table_quoted = $db->quoteIdentifier($table, true); + $query = "ALTER TABLE $table_quoted ADD $type $name"; + if (!empty($definition['foreign'])) { + $query .= ' FOREIGN KEY'; + } + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $fields) . ')'; + if (!empty($definition['foreign'])) { + $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true); + $referenced_fields = array(); + foreach (array_keys($definition['references']['fields']) as $field) { + $referenced_fields[] = $db->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $referenced_fields) . ')'; + $query .= $this->_getAdvancedFKOptions($definition); + } + $res = $db->exec($query); + if (PEAR::isError($res)) { + return $res; + } + if (!empty($definition['foreign'])) { + return $this->_createFKTriggers($table, array($name => $definition)); + } + return MDB2_OK; + } + + // }}} + // {{{ dropConstraint() + + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropConstraint($table, $name, $primary = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($primary || strtolower($name) == 'primary') { + $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY'; + return $db->exec($query); + } + + //is it a FK constraint? If so, also delete the associated triggers + $db->loadModule('Reverse', null, true); + $definition = $db->reverse->getTableConstraintDefinition($table, $name); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + //first drop the FK enforcing triggers + $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + //then drop the constraint itself + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "ALTER TABLE $table DROP FOREIGN KEY $name"; + return $db->exec($query); + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($db->getIndexName($name), true); + $query = "ALTER TABLE $table DROP INDEX $name"; + return $db->exec($query); + } + + // }}} + // {{{ _createFKTriggers() + + /** + * Create triggers to enforce the FOREIGN KEY constraint on the table + * + * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql, + * we call a non-existent procedure to raise the FK violation message. + * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877 + * + * @param string $table table name + * @param array $foreign_keys FOREIGN KEY definitions + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _createFKTriggers($table, $foreign_keys) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + // create triggers to enforce FOREIGN KEY constraints + if ($db->supports('triggers') && !empty($foreign_keys)) { + $table = $db->quoteIdentifier($table, true); + foreach ($foreign_keys as $fkname => $fkdef) { + if (empty($fkdef)) { + continue; + } + //set actions to 'RESTRICT' if not set + $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']); + $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']); + + $trigger_names = array( + 'insert' => $fkname.'_insert_trg', + 'update' => $fkname.'_update_trg', + 'pk_update' => $fkname.'_pk_update_trg', + 'pk_delete' => $fkname.'_pk_delete_trg', + ); + $table_fields = array_keys($fkdef['fields']); + $referenced_fields = array_keys($fkdef['references']['fields']); + + //create the ON [UPDATE|DELETE] triggers on the primary table + $restrict_action = ' IF (SELECT '; + $aliased_fields = array(); + foreach ($table_fields as $field) { + $aliased_fields[] = $table .'.'.$field .' AS '.$field; + } + $restrict_action .= implode(',', $aliased_fields) + .' FROM '.$table + .' WHERE '; + $conditions = array(); + $new_values = array(); + $null_values = array(); + for ($i=0; $iloadModule('Reverse', null, true); + $default_values = array(); + foreach ($table_fields as $table_field) { + $field_definition = $db->reverse->getTableFieldDefinition($table, $field); + if (PEAR::isError($field_definition)) { + return $field_definition; + } + $default_values[] = $table_field .' = '. $field_definition[0]['default']; + } + $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';'; + } + + $query = 'CREATE TRIGGER %s' + .' %s ON '.$fkdef['references']['table'] + .' FOR EACH ROW BEGIN ' + .' SET FOREIGN_KEY_CHECKS = 0; '; //only really needed for ON UPDATE CASCADE + + if ('CASCADE' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $cascade_action_update; + } elseif ('SET NULL' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action; + } elseif ('SET DEFAULT' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action; + } elseif ('NO ACTION' == $fkdef['onupdate']) { + $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update'); + } else { + //'RESTRICT' + $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update'); + } + if ('CASCADE' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $cascade_action_delete; + } elseif ('SET NULL' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action; + } elseif ('SET DEFAULT' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action; + } elseif ('NO ACTION' == $fkdef['ondelete']) { + $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete'); + } else { + //'RESTRICT' + $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete'); + } + $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; + $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; + + $db->pushErrorHandling(PEAR_ERROR_RETURN); + $db->expectError(MDB2_ERROR_CANNOT_CREATE); + $result = $db->exec($sql_delete); + $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table'; + $db->popExpect(); + $db->popErrorHandling(); + if (PEAR::isError($result)) { + if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { + return $result; + } + $db->warnings[] = $expected_errmsg; + } + $db->pushErrorHandling(PEAR_ERROR_RETURN); + $db->expectError(MDB2_ERROR_CANNOT_CREATE); + $result = $db->exec($sql_update); + $db->popExpect(); + $db->popErrorHandling(); + if (PEAR::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) { + if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { + return $result; + } + $db->warnings[] = $expected_errmsg; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ _dropFKTriggers() + + /** + * Drop the triggers created to enforce the FOREIGN KEY constraint on the table + * + * @param string $table table name + * @param string $fkname FOREIGN KEY constraint name + * @param string $referenced_table referenced table name + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _dropFKTriggers($table, $fkname, $referenced_table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $triggers = $this->listTableTriggers($table); + $triggers2 = $this->listTableTriggers($referenced_table); + if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) { + $triggers = array_merge($triggers, $triggers2); + $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i'; + foreach ($triggers as $trigger) { + if (preg_match($pattern, $trigger)) { + $result = $db->exec('DROP TRIGGER '.$trigger); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $key_name = 'Key_name'; + $non_unique = 'Non_unique'; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + $non_unique = strtolower($non_unique); + } else { + $key_name = strtoupper($key_name); + $non_unique = strtoupper($non_unique); + } + } + + $query = 'SHOW INDEX FROM ' . $db->quoteIdentifier($table, true); + $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $index_data) { + if (!$index_data[$non_unique]) { + if ($index_data[$key_name] !== 'PRIMARY') { + $index = $this->_fixIndexName($index_data[$key_name]); + } else { + $index = 'PRIMARY'; + } + if (!empty($index)) { + $result[$index] = true; + } + } + } + + //list FOREIGN KEY constraints... + $query = 'SHOW CREATE TABLE '. $db->escape($table); + $definition = $db->queryOne($query, 'text', 1); + if (!PEAR::isError($definition) && !empty($definition)) { + $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims'; + if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) { + foreach ($matches[1] as $constraint) { + $result[$constraint] = true; + } + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true); + + $options_strings = array(); + + if (!empty($options['comment'])) { + $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text'); + } + + if (!empty($options['charset'])) { + $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset']; + if (!empty($options['collate'])) { + $options_strings['charset'].= ' COLLATE '.$options['collate']; + } + } + + $type = false; + if (!empty($options['type'])) { + $type = $options['type']; + } elseif ($db->options['default_table_type']) { + $type = $db->options['default_table_type']; + } + if ($type) { + $options_strings[] = "ENGINE = $type"; + } + + $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))"; + if (!empty($options_strings)) { + $query .= ' '.implode(' ', $options_strings); + } + $res = $db->exec($query); + if (PEAR::isError($res)) { + return $res; + } + + if ($start == 1) { + return MDB2_OK; + } + + $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')'; + $res = $db->exec($query); + if (!PEAR::isError($res)) { + return MDB2_OK; + } + + // Handle error + $result = $db->exec("DROP TABLE $sequence_name"); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'could not drop inconsistent sequence table', __FUNCTION__); + } + + return $db->raiseError($res, null, null, + 'could not create sequence table', __FUNCTION__); + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("DROP TABLE $sequence_name"); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @param string database, the current is default + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences($database = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SHOW TABLES"; + if (!is_null($database)) { + $query .= " FROM $database"; + } + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + + $result = array(); + foreach ($table_names as $table_name) { + if ($sqn = $this->_fixSequenceName($table_name, true)) { + $result[] = $sqn; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/oci8.php b/lib/Pear/MDB2/Driver/Manager/oci8.php new file mode 100644 index 0000000..0537f6b --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/oci8.php @@ -0,0 +1,1338 @@ + | +// +----------------------------------------------------------------------+ + +// $Id: oci8.php,v 1.107 2008/03/12 15:16:42 afz Exp $ + +require_once 'MDB2/Driver/Manager/Common.php'; + +/** + * MDB2 oci8 driver for the management modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Manager_oci8 extends MDB2_Driver_Manager_Common +{ + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset, collation info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $username = $db->options['database_name_prefix'].$name; + $password = $db->dsn['password'] ? $db->dsn['password'] : $name; + $tablespace = $db->options['default_tablespace'] + ? ' DEFAULT TABLESPACE '.$db->options['default_tablespace'] : ''; + + $query = 'CREATE USER '.$username.' IDENTIFIED BY '.$password.$tablespace; + $result = $db->standaloneQuery($query, null, true); + if (PEAR::isError($result)) { + return $result; + } + $query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO '.$username; + $result = $db->standaloneQuery($query, null, true); + if (PEAR::isError($result)) { + $query = 'DROP USER '.$username.' CASCADE'; + $result2 = $db->standaloneQuery($query, null, true); + if (PEAR::isError($result2)) { + return $db->raiseError($result2, null, null, + 'could not setup the database user', __FUNCTION__); + } + return $result; + } + return MDB2_OK; + } + + // }}} + // {{{ alterDatabase() + + /** + * alter an existing database + * + * IMPORTANT: the safe way to change the db charset is to do a full import/export! + * If - and only if - the new character set is a strict superset of the current + * character set, it is possible to use the ALTER DATABASE CHARACTER SET to + * expedite the change in the database character set. + * + * @param string $name name of the database that is intended to be changed + * @param array $options array with name, charset info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterDatabase($name, $options = array()) + { + //disabled + //return parent::alterDatabase($name, $options); + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($options['name'])) { + $query = 'ALTER DATABASE ' . $db->quoteIdentifier($name, true) + .' RENAME GLOBAL_NAME TO ' . $db->quoteIdentifier($options['name'], true); + $result = $db->standaloneQuery($query); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($options['charset'])) { + $queries = array(); + $queries[] = 'SHUTDOWN IMMEDIATE'; //or NORMAL + $queries[] = 'STARTUP MOUNT'; + $queries[] = 'ALTER SYSTEM ENABLE RESTRICTED SESSION'; + $queries[] = 'ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0'; + $queries[] = 'ALTER DATABASE OPEN'; + $queries[] = 'ALTER DATABASE CHARACTER SET ' . $options['charset']; + $queries[] = 'ALTER DATABASE NATIONAL CHARACTER SET ' . $options['charset']; + $queries[] = 'SHUTDOWN IMMEDIATE'; //or NORMAL + $queries[] = 'STARTUP'; + + foreach ($queries as $query) { + $result = $db->standaloneQuery($query); + if (PEAR::isError($result)) { + return $result; + } + } + } + + return MDB2_OK; + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param object $db database object that is extended by this class + * @param string $name name of the database that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $username = $db->options['database_name_prefix'].$name; + return $db->standaloneQuery('DROP USER '.$username.' CASCADE', null, true); + } + + + // }}} + // {{{ _makeAutoincrement() + + /** + * add an autoincrement sequence + trigger + * + * @param string $name name of the PK field + * @param string $table name of the table + * @param string $start start value for the sequence + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _makeAutoincrement($name, $table, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table_uppercase = strtoupper($table); + $index_name = $table_uppercase . '_AI_PK'; + $definition = array( + 'primary' => true, + 'fields' => array($name => true), + ); + $idxname_format = $db->getOption('idxname_format'); + $db->setOption('idxname_format', '%s'); + $result = $this->createConstraint($table, $index_name, $definition); + $db->setOption('idxname_format', $idxname_format); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'primary key for autoincrement PK could not be created', __FUNCTION__); + } + + $seq_name = $table.'_'.$name; + if (is_null($start)) { + $db->beginTransaction(); + $query = 'SELECT MAX(' . $db->quoteIdentifier($name, true) . ') FROM ' . $db->quoteIdentifier($table, true); + $start = $this->db->queryOne($query, 'integer'); + if (PEAR::isError($start)) { + return $start; + } + ++$start; + $result = $this->createSequence($seq_name, $start); + $db->commit(); + } else { + $result = $this->createSequence($seq_name, $start); + } + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'sequence for autoincrement PK could not be created', __FUNCTION__); + } + $seq_name = $db->getSequenceName($seq_name); + $trigger_name = $db->quoteIdentifier($table_uppercase . '_AI_PK', true); + $seq_name_quoted = $db->quoteIdentifier($seq_name, true); + $table = $db->quoteIdentifier($table, true); + $name = $db->quoteIdentifier($name, true); + $trigger_sql = ' +CREATE TRIGGER '.$trigger_name.' + BEFORE INSERT + ON '.$table.' + FOR EACH ROW +DECLARE + last_Sequence NUMBER; + last_InsertID NUMBER; +BEGIN + SELECT '.$seq_name_quoted.'.NEXTVAL INTO :NEW.'.$name.' FROM DUAL; + IF (:NEW.'.$name.' IS NULL OR :NEW.'.$name.' = 0) THEN + SELECT '.$seq_name_quoted.'.NEXTVAL INTO :NEW.'.$name.' FROM DUAL; + ELSE + SELECT NVL(Last_Number, 0) INTO last_Sequence + FROM User_Sequences + WHERE UPPER(Sequence_Name) = UPPER(\''.$seq_name.'\'); + SELECT :NEW.'.$name.' INTO last_InsertID FROM DUAL; + WHILE (last_InsertID > last_Sequence) LOOP + SELECT '.$seq_name_quoted.'.NEXTVAL INTO last_Sequence FROM DUAL; + END LOOP; + END IF; +END; +'; + $result = $db->exec($trigger_sql); + if (PEAR::isError($result)) { + return $result; + } + return MDB2_OK; + } + + // }}} + // {{{ _dropAutoincrement() + + /** + * drop an existing autoincrement sequence + trigger + * + * @param string $table name of the table + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _dropAutoincrement($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = strtoupper($table); + $trigger_name = $table . '_AI_PK'; + $trigger_name_quoted = $db->quote($trigger_name, 'text'); + $query = 'SELECT trigger_name FROM user_triggers'; + $query.= ' WHERE trigger_name='.$trigger_name_quoted.' OR trigger_name='.strtoupper($trigger_name_quoted); + $trigger = $db->queryOne($query); + if (PEAR::isError($trigger)) { + return $trigger; + } + + if ($trigger) { + $trigger_name = $db->quoteIdentifier($table . '_AI_PK', true); + $trigger_sql = 'DROP TRIGGER ' . $trigger_name; + $result = $db->exec($trigger_sql); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'trigger for autoincrement PK could not be dropped', __FUNCTION__); + } + + $result = $this->dropSequence($table); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'sequence for autoincrement PK could not be dropped', __FUNCTION__); + } + + $index_name = $table . '_AI_PK'; + $idxname_format = $db->getOption('idxname_format'); + $db->setOption('idxname_format', '%s'); + $result1 = $this->dropConstraint($table, $index_name); + $db->setOption('idxname_format', $idxname_format); + $result2 = $this->dropConstraint($table, $index_name); + if (PEAR::isError($result1) && PEAR::isError($result2)) { + return $db->raiseError($result1, null, null, + 'primary key for autoincrement PK could not be dropped', __FUNCTION__); + } + } + + return MDB2_OK; + } + + // }}} + // {{{ _getTemporaryTableQuery() + + /** + * A method to return the required SQL string that fits between CREATE ... TABLE + * to create the table as a temporary table. + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + function _getTemporaryTableQuery() + { + return 'GLOBAL TEMPORARY'; + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['ondelete']) && (strtoupper($definition['ondelete']) != 'NO ACTION')) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + if (!empty($definition['deferrable'])) { + $query .= ' DEFERRABLE'; + } else { + $query .= ' NOT DEFERRABLE'; + } + if (!empty($definition['initiallydeferred'])) { + $query .= ' INITIALLY DEFERRED'; + } else { + $query .= ' INITIALLY IMMEDIATE'; + } + return $query; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * + * Example + * array( + * + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'temporary' => true|false, + * ); + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $db->beginNestedTransaction(); + $result = parent::createTable($name, $fields, $options); + if (!PEAR::isError($result)) { + foreach ($fields as $field_name => $field) { + if (!empty($field['autoincrement'])) { + $result = $this->_makeAutoincrement($field_name, $name); + } + } + } + $db->completeNestedTransaction(); + return $result; + } + + // }}} + // {{{ dropTable() + + /** + * drop an existing table + * + * @param string $name name of the table that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $db->beginNestedTransaction(); + $result = $this->_dropAutoincrement($name); + if (!PEAR::isError($result)) { + $result = parent::dropTable($name); + } + $db->completeNestedTransaction(); + return $result; + } + + // }}} + // {{{ truncateTable() + + /** + * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, + * it falls back to a DELETE FROM TABLE query) + * + * @param string $name name of the table that should be truncated + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function truncateTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("TRUNCATE TABLE $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + // not needed in Oracle + return MDB2_OK; + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @access public + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + case 'remove': + case 'change': + case 'name': + case 'rename': + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'" not yet supported', __FUNCTION__); + } + } + + if ($check) { + return MDB2_OK; + } + + $name = $db->quoteIdentifier($name, true); + + if (!empty($changes['add']) && is_array($changes['add'])) { + $fields = array(); + foreach ($changes['add'] as $field_name => $field) { + $fields[] = $db->getDeclaration($field['type'], $field_name, $field); + } + $result = $db->exec("ALTER TABLE $name ADD (". implode(', ', $fields).')'); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + $fields = array(); + foreach ($changes['change'] as $field_name => $field) { + $fields[] = $field_name. ' ' . $db->getDeclaration($field['definition']['type'], '', $field['definition']); + } + $result = $db->exec("ALTER TABLE $name MODIFY (". implode(', ', $fields).')'); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $field_name => $field) { + $field_name = $db->quoteIdentifier($field_name, true); + $query = "ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name']); + $result = $db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + $fields = array(); + foreach ($changes['remove'] as $field_name => $field) { + $fields[] = $db->quoteIdentifier($field_name, true); + } + $result = $db->exec("ALTER TABLE $name DROP COLUMN ". implode(', ', $fields)); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($changes['name'])) { + $change_name = $db->quoteIdentifier($changes['name'], true); + $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name); + if (PEAR::isError($result)) { + return $result; + } + } + + return MDB2_OK; + } + + // }}} + // {{{ _fetchCol() + + /** + * Utility method to fetch and format a column from a resultset + * + * @param resource $result + * @param boolean $fixname (used when listing indices or constraints) + * @return mixed array of names on success, a MDB2 error on failure + * @access private + */ + function _fetchCol($result, $fixname = false) + { + if (PEAR::isError($result)) { + return $result; + } + $col = $result->fetchCol(); + if (PEAR::isError($col)) { + return $col; + } + $result->free(); + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($fixname) { + foreach ($col as $k => $v) { + $col[$k] = $this->_fixIndexName($v); + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + && $db->options['field_case'] == CASE_LOWER + ) { + $col = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $col); + } + return $col; + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!$db->options['emulate_database']) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'database listing is only supported if the "emulate_database" option is enabled', __FUNCTION__); + } + + if ($db->options['database_name_prefix']) { + $query = 'SELECT SUBSTR(username, '; + $query.= (strlen($db->options['database_name_prefix'])+1); + $query.= ") FROM sys.dba_users WHERE username LIKE '"; + $query.= $db->options['database_name_prefix']."%'"; + } else { + $query = 'SELECT username FROM sys.dba_users'; + } + $result = $db->standaloneQuery($query, array('text'), false); + return $this->_fetchCol($result); + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($db->options['emulate_database'] && $db->options['database_name_prefix']) { + $query = 'SELECT SUBSTR(username, '; + $query.= (strlen($db->options['database_name_prefix'])+1); + $query.= ") FROM sys.dba_users WHERE username NOT LIKE '"; + $query.= $db->options['database_name_prefix']."%'"; + } else { + $query = 'SELECT username FROM sys.dba_users'; + } + return $db->queryCol($query); + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @param string owner, the current is default + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews($owner = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT view_name + FROM sys.all_views + WHERE owner=? OR owner=?'; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $result = $stmt->execute(array($owner, strtoupper($owner))); + return $this->_fetchCol($result); + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions in the current database + * + * @param string owner, the current is default + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions($owner = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = "SELECT name + FROM sys.all_source + WHERE line = 1 + AND type = 'FUNCTION' + AND (owner=? OR owner=?)"; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $result = $stmt->execute(array($owner, strtoupper($owner))); + return $this->_fetchCol($result); + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = "SELECT trigger_name + FROM sys.all_triggers + WHERE (table_name=? OR table_name=?) + AND (owner=? OR owner=?)"; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $args = array( + $table, + strtoupper($table), + $owner, + strtoupper($owner), + ); + $result = $stmt->execute($args); + return $this->_fetchCol($result); + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the database + * + * @param string owner, the current is default + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables($owner = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT table_name + FROM sys.all_tables + WHERE owner=? OR owner=?'; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $result = $stmt->execute(array($owner, strtoupper($owner))); + return $this->_fetchCol($result); + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($owner, $table) = $this->splitTableSchema($table); + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT column_name + FROM all_tab_columns + WHERE (table_name=? OR table_name=?) + AND (owner=? OR owner=?) + ORDER BY column_id'; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $args = array( + $table, + strtoupper($table), + $owner, + strtoupper($owner), + ); + $result = $stmt->execute($args); + return $this->_fetchCol($result); + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($owner, $table) = $this->splitTableSchema($table); + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT i.index_name name + FROM all_indexes i + LEFT JOIN all_constraints c + ON c.index_name = i.index_name + AND c.owner = i.owner + AND c.table_name = i.table_name + WHERE (i.table_name=? OR i.table_name=?) + AND (i.owner=? OR i.owner=?) + AND c.index_name IS NULL + AND i.generated=' .$db->quote('N', 'text'); + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $args = array( + $table, + strtoupper($table), + $owner, + strtoupper($owner), + ); + $result = $stmt->execute($args); + return $this->_fetchCol($result, true); + } + + // }}} + // {{{ createConstraint() + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array() + * ) + * ) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createConstraint($table, $name, $definition) + { + $result = parent::createConstraint($table, $name, $definition); + if (PEAR::isError($result)) { + return $result; + } + if (!empty($definition['foreign'])) { + return $this->_createFKTriggers($table, array($name => $definition)); + } + return MDB2_OK; + } + + // }}} + // {{{ dropConstraint() + + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropConstraint($table, $name, $primary = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + //is it a FK constraint? If so, also delete the associated triggers + $db->loadModule('Reverse', null, true); + $definition = $db->reverse->getTableConstraintDefinition($table, $name); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + //first drop the FK enforcing triggers + $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + } + + return parent::dropConstraint($table, $name, $primary); + } + + // }}} + // {{{ _createFKTriggers() + + /** + * Create triggers to enforce the FOREIGN KEY constraint on the table + * + * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql, + * we call a non-existent procedure to raise the FK violation message. + * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877 + * + * @param string $table table name + * @param array $foreign_keys FOREIGN KEY definitions + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _createFKTriggers($table, $foreign_keys) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + // create triggers to enforce FOREIGN KEY constraints + if ($db->supports('triggers') && !empty($foreign_keys)) { + $table = $db->quoteIdentifier($table, true); + foreach ($foreign_keys as $fkname => $fkdef) { + if (empty($fkdef) || empty($fkdef['onupdate'])) { + continue; + } + $fkdef['onupdate'] = strtoupper($fkdef['onupdate']); + if ('RESTRICT' == $fkdef['onupdate'] || 'NO ACTION' == $fkdef['onupdate']) { + // already handled by default + continue; + } + + $trigger_name = substr(strtolower($fkname.'_pk_upd_trg'), 0, $db->options['max_identifiers_length']); + $table_fields = array_keys($fkdef['fields']); + $referenced_fields = array_keys($fkdef['references']['fields']); + + //create the ON UPDATE trigger on the primary table + $restrict_action = ' IF (SELECT '; + $aliased_fields = array(); + foreach ($table_fields as $field) { + $aliased_fields[] = $table .'.'.$field .' AS '.$field; + } + $restrict_action .= implode(',', $aliased_fields) + .' FROM '.$table + .' WHERE '; + $conditions = array(); + $new_values = array(); + $null_values = array(); + for ($i=0; $iloadModule('Reverse', null, true); + $default_values = array(); + foreach ($table_fields as $table_field) { + $field_definition = $db->reverse->getTableFieldDefinition($table, $field); + if (PEAR::isError($field_definition)) { + return $field_definition; + } + $default_values[] = $table_field .' = '. $field_definition[0]['default']; + } + $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';'; + } + + $query = 'CREATE TRIGGER %s' + .' %s ON '.$fkdef['references']['table'] + .' FOR EACH ROW ' + .' BEGIN '; + + if ('CASCADE' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_name, 'BEFORE UPDATE', 'update') . $cascade_action; + } elseif ('SET NULL' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_name, 'BEFORE UPDATE', 'update') . $setnull_action; + } elseif ('SET DEFAULT' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_name, 'BEFORE UPDATE', 'update') . $setdefault_action; + } + $sql_update .= ' END;'; + $result = $db->exec($sql_update); + if (PEAR::isError($result)) { + return $result; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ _dropFKTriggers() + + /** + * Drop the triggers created to enforce the FOREIGN KEY constraint on the table + * + * @param string $table table name + * @param string $fkname FOREIGN KEY constraint name + * @param string $referenced_table referenced table name + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _dropFKTriggers($table, $fkname, $referenced_table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $triggers = $this->listTableTriggers($table); + $triggers2 = $this->listTableTriggers($referenced_table); + if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) { + $triggers = array_merge($triggers, $triggers2); + $trigger_name = substr(strtolower($fkname.'_pk_upd_trg'), 0, $db->options['max_identifiers_length']); + $pattern = '/^'.$trigger_name.'$/i'; + foreach ($triggers as $trigger) { + if (preg_match($pattern, $trigger)) { + $result = $db->exec('DROP TRIGGER '.$trigger); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($owner, $table) = $this->splitTableSchema($table); + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT constraint_name + FROM all_constraints + WHERE (table_name=? OR table_name=?) + AND (owner=? OR owner=?)'; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $args = array( + $table, + strtoupper($table), + $owner, + strtoupper($owner), + ); + $result = $stmt->execute($args); + return $this->_fetchCol($result, true); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param object $db database object that is extended by this class + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + $query = "CREATE SEQUENCE $sequence_name START WITH $start INCREMENT BY 1 NOCACHE"; + $query.= ($start < 1 ? " MINVALUE $start" : ''); + return $db->exec($query); + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param object $db database object that is extended by this class + * @param string $seq_name name of the sequence to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("DROP SEQUENCE $sequence_name"); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @param string owner, the current is default + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences($owner = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT sequence_name + FROM sys.all_sequences + WHERE (sequence_owner=? OR sequence_owner=?)'; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $result = $stmt->execute(array($owner, strtoupper($owner))); + if (PEAR::isError($result)) { + return $result; + } + $col = $result->fetchCol(); + if (PEAR::isError($col)) { + return $col; + } + $result->free(); + + foreach ($col as $k => $v) { + $col[$k] = $this->_fixSequenceName($v); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + && $db->options['field_case'] == CASE_LOWER + ) { + $col = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $col); + } + return $col; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/pgsql.php b/lib/Pear/MDB2/Driver/Manager/pgsql.php new file mode 100644 index 0000000..1015c2b --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/pgsql.php @@ -0,0 +1,859 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: pgsql.php,v 1.82 2008/03/05 12:55:57 afz Exp $ + +require_once 'MDB2/Driver/Manager/Common.php'; + +/** + * MDB2 MySQL driver for the management modules + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common +{ + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = 'CREATE DATABASE ' . $name; + if (!empty($options['charset'])) { + $query .= ' WITH ENCODING ' . $db->quote($options['charset'], 'text'); + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ alterDatabase() + + /** + * alter an existing database + * + * @param string $name name of the database that is intended to be changed + * @param array $options array with name, owner info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function alterDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); + if (!empty($options['name'])) { + $query .= ' RENAME TO ' . $options['name']; + } + if (!empty($options['owner'])) { + $query .= ' OWNER TO ' . $options['owner']; + } + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + $query = "DROP DATABASE $name"; + return $db->standaloneQuery($query, null, true); + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['match'])) { + $query .= ' MATCH '.$definition['match']; + } + if (!empty($definition['onupdate'])) { + $query .= ' ON UPDATE '.$definition['onupdate']; + } + if (!empty($definition['ondelete'])) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + if (!empty($definition['deferrable'])) { + $query .= ' DEFERRABLE'; + } else { + $query .= ' NOT DEFERRABLE'; + } + if (!empty($definition['initiallydeferred'])) { + $query .= ' INITIALLY DEFERRED'; + } else { + $query .= ' INITIALLY IMMEDIATE'; + } + return $query; + } + + // }}} + // {{{ truncateTable() + + /** + * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, + * it falls back to a DELETE FROM TABLE query) + * + * @param string $name name of the table that should be truncated + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function truncateTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("TRUNCATE TABLE $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $query = 'VACUUM'; + + if (!empty($options['full'])) { + $query .= ' FULL'; + } + if (!empty($options['freeze'])) { + $query .= ' FREEZE'; + } + if (!empty($options['analyze'])) { + $query .= ' ANALYZE'; + } + + if (!empty($table)) { + $query .= ' '.$db->quoteIdentifier($table, true); + } + return $db->exec($query); + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @access public + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function alterTable($name, $changes, $check) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + case 'remove': + case 'change': + case 'name': + case 'rename': + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'\" not yet supported', __FUNCTION__); + } + } + + if ($check) { + return MDB2_OK; + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $field_name => $field) { + $field_name = $db->quoteIdentifier($field_name, true); + $query = 'DROP ' . $field_name; + $result = $db->exec("ALTER TABLE $name $query"); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (!empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $field_name => $field) { + $field_name = $db->quoteIdentifier($field_name, true); + $result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true)); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $field_name => $field) { + $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); + $result = $db->exec("ALTER TABLE $name $query"); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $field_name => $field) { + $field_name = $db->quoteIdentifier($field_name, true); + if (!empty($field['definition']['type'])) { + $server_info = $db->getServerVersion(); + if (PEAR::isError($server_info)) { + return $server_info; + } + if (is_array($server_info) && $server_info['major'] < 8) { + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__); + } + $db->loadModule('Datatype', null, true); + $query = "ALTER $field_name TYPE ".$db->datatype->getTypeDeclaration($field['definition']); + $result = $db->exec("ALTER TABLE $name $query"); + if (PEAR::isError($result)) { + return $result; + } + } + if (array_key_exists('default', $field['definition'])) { + $query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']); + $result = $db->exec("ALTER TABLE $name $query"); + if (PEAR::isError($result)) { + return $result; + } + } + if (!empty($field['definition']['notnull'])) { + $query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL'; + $result = $db->exec("ALTER TABLE $name $query"); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + + $name = $db->quoteIdentifier($name, true); + if (!empty($changes['name'])) { + $change_name = $db->quoteIdentifier($changes['name'], true); + $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name); + if (PEAR::isError($result)) { + return $result; + } + } + + return MDB2_OK; + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT datname FROM pg_database'; + $result2 = $db->standaloneQuery($query, array('text'), false); + if (!MDB2::isResultCommon($result2)) { + return $result2; + } + + $result = $result2->fetchCol(); + $result2->free(); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT usename FROM pg_user'; + $result2 = $db->standaloneQuery($query, array('text'), false); + if (!MDB2::isResultCommon($result2)) { + return $result2; + } + + $result = $result2->fetchCol(); + $result2->free(); + return $result; + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT viewname + FROM pg_views + WHERE schemaname NOT IN ('pg_catalog', 'information_schema') + AND viewname !~ '^pg_'"; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableViews() + + /** + * list the views in the database that reference a given table + * + * @param string table for which all referenced views should be found + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listTableViews($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables'; + $query.= ' WHERE tablename ='.$db->quote($table, 'text'); + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listFunctions() + + /** + * list all functions in the current database + * + * @return mixed array of function names on success, a MDB2 error on failure + * @access public + */ + function listFunctions() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = " + SELECT + proname + FROM + pg_proc pr, + pg_type tp + WHERE + tp.oid = pr.prorettype + AND pr.proisagg = FALSE + AND tp.typname <> 'trigger' + AND pr.pronamespace IN + (SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')"; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT trg.tgname AS trigger_name + FROM pg_trigger trg, + pg_class tbl + WHERE trg.tgrelid = tbl.oid'; + if (!is_null($table)) { + $table = $db->quote(strtoupper($table), 'text'); + $query .= " AND tbl.relname = $table"; + } + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + // gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php + $query = 'SELECT c.relname AS "Name"' + . ' FROM pg_class c, pg_user u' + . ' WHERE c.relowner = u.usesysid' + . " AND c.relkind = 'r'" + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_views' + . ' WHERE viewname = c.relname)' + . " AND c.relname !~ '^(pg_|sql_)'" + . ' UNION' + . ' SELECT c.relname AS "Name"' + . ' FROM pg_class c' + . " WHERE c.relkind = 'r'" + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_views' + . ' WHERE viewname = c.relname)' + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_user' + . ' WHERE usesysid = c.relowner)' + . " AND c.relname !~ '^pg_'"; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $db->setLimit(1); + $result2 = $db->query("SELECT * FROM $table"); + if (PEAR::isError($result2)) { + return $result2; + } + $result = $result2->getColumnNames(); + $result2->free(); + if (PEAR::isError($result)) { + return $result; + } + return array_flip($result); + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quote($table, 'text'); + $subquery = "SELECT indexrelid FROM pg_index, pg_class"; + $subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND indisunique != 't' AND indisprimary != 't'"; + $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)"; + $indexes = $db->queryCol($query, 'text'); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $index) { + $index = $this->_fixIndexName($index); + if (!empty($index)) { + $result[$index] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quote($table, 'text'); + $query = 'SELECT conname + FROM pg_constraint, pg_class + WHERE pg_constraint.conrelid = pg_class.oid + AND relname = ' .$table; + $constraints = $db->queryCol($query); + if (PEAR::isError($constraints)) { + return $constraints; + } + + $result = array(); + foreach ($constraints as $constraint) { + $constraint = $this->_fixIndexName($constraint); + if (!empty($constraint)) { + $result[$constraint] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + && $db->options['field_case'] == CASE_LOWER + ) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1". + ($start < 1 ? " MINVALUE $start" : '')." START $start"); + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("DROP SEQUENCE $sequence_name"); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN"; + $query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')"; + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + $result = array(); + foreach ($table_names as $table_name) { + $result[] = $this->_fixSequenceName($table_name); + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Manager/sqlite.php b/lib/Pear/MDB2/Driver/Manager/sqlite.php new file mode 100644 index 0000000..676127c --- /dev/null +++ b/lib/Pear/MDB2/Driver/Manager/sqlite.php @@ -0,0 +1,1356 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: sqlite.php,v 1.74 2008/03/05 11:08:53 quipo Exp $ +// + +require_once 'MDB2/Driver/Manager/Common.php'; + +/** + * MDB2 SQLite driver for the management modules + * + * @package MDB2 + * @category Database + * @author Lukas Smith + * @author Lorenzo Alberton + */ +class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common +{ + // {{{ createDatabase() + + /** + * create a new database + * + * @param string $name name of the database that should be created + * @param array $options array with charset info + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createDatabase($name, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $database_file = $db->_getDatabaseFile($name); + if (file_exists($database_file)) { + return $db->raiseError(MDB2_ERROR_ALREADY_EXISTS, null, null, + 'database already exists', __FUNCTION__); + } + $php_errormsg = ''; + $handle = @sqlite_open($database_file, $db->dsn['mode'], $php_errormsg); + if (!$handle) { + return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null, + (isset($php_errormsg) ? $php_errormsg : 'could not create the database file'), __FUNCTION__); + } + if (!empty($options['charset'])) { + $query = 'PRAGMA encoding = ' . $db->quote($options['charset'], 'text'); + @sqlite_query($query, $handle); + } + @sqlite_close($handle); + return MDB2_OK; + } + + // }}} + // {{{ dropDatabase() + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropDatabase($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $database_file = $db->_getDatabaseFile($name); + if (!@file_exists($database_file)) { + return $db->raiseError(MDB2_ERROR_CANNOT_DROP, null, null, + 'database does not exist', __FUNCTION__); + } + $result = @unlink($database_file); + if (!$result) { + return $db->raiseError(MDB2_ERROR_CANNOT_DROP, null, null, + (isset($php_errormsg) ? $php_errormsg : 'could not remove the database file'), __FUNCTION__); + } + return MDB2_OK; + } + + // }}} + // {{{ _getAdvancedFKOptions() + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + * @access protected + */ + function _getAdvancedFKOptions($definition) + { + $query = ''; + if (!empty($definition['match'])) { + $query .= ' MATCH '.$definition['match']; + } + if (!empty($definition['onupdate']) && (strtoupper($definition['onupdate']) != 'NO ACTION')) { + $query .= ' ON UPDATE '.$definition['onupdate']; + } + if (!empty($definition['ondelete']) && (strtoupper($definition['ondelete']) != 'NO ACTION')) { + $query .= ' ON DELETE '.$definition['ondelete']; + } + if (!empty($definition['deferrable'])) { + $query .= ' DEFERRABLE'; + } else { + $query .= ' NOT DEFERRABLE'; + } + if (!empty($definition['initiallydeferred'])) { + $query .= ' INITIALLY DEFERRED'; + } else { + $query .= ' INITIALLY IMMEDIATE'; + } + return $query; + } + + // }}} + // {{{ _getCreateTableQuery() + + /** + * Create a basic SQL query for a new table creation + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * @param array $options An associative array of table options + * @return mixed string (the SQL query) on success, a MDB2 error on failure + * @see createTable() + */ + function _getCreateTableQuery($name, $fields, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!$name) { + return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null, + 'no valid table name specified', __FUNCTION__); + } + if (empty($fields)) { + return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null, + 'no fields specified for table "'.$name.'"', __FUNCTION__); + } + $query_fields = $this->getFieldDeclarationList($fields); + if (PEAR::isError($query_fields)) { + return $query_fields; + } + if (!empty($options['primary'])) { + $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')'; + } + if (!empty($options['foreign_keys'])) { + foreach ($options['foreign_keys'] as $fkname => $fkdef) { + if (empty($fkdef)) { + continue; + } + $query_fields.= ', CONSTRAINT '.$fkname.' FOREIGN KEY ('.implode(', ', array_keys($fkdef['fields'])).')'; + $query_fields.= ' REFERENCES '.$fkdef['references']['table'].' ('.implode(', ', array_keys($fkdef['references']['fields'])).')'; + $query_fields.= $this->_getAdvancedFKOptions($fkdef); + } + } + + $name = $db->quoteIdentifier($name, true); + $result = 'CREATE '; + if (!empty($options['temporary'])) { + $result .= $this->_getTemporaryTableQuery(); + } + $result .= " TABLE $name ($query_fields)"; + return $result; + } + + // }}} + // {{{ createTable() + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * @param array $options An associative array of table options + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createTable($name, $fields, $options = array()) + { + $result = parent::createTable($name, $fields, $options); + if (PEAR::isError($result)) { + return $result; + } + // create triggers to enforce FOREIGN KEY constraints + if (!empty($options['foreign_keys'])) { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + foreach ($options['foreign_keys'] as $fkname => $fkdef) { + if (empty($fkdef)) { + continue; + } + //set actions to 'RESTRICT' if not set + $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']); + $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']); + + $trigger_names = array( + 'insert' => $fkname.'_insert_trg', + 'update' => $fkname.'_update_trg', + 'pk_update' => $fkname.'_pk_update_trg', + 'pk_delete' => $fkname.'_pk_delete_trg', + ); + + //create the [insert|update] triggers on the FK table + $table_fields = array_keys($fkdef['fields']); + $referenced_fields = array_keys($fkdef['references']['fields']); + $query = 'CREATE TRIGGER %s BEFORE %s ON '.$name + .' FOR EACH ROW BEGIN' + .' SELECT RAISE(ROLLBACK, \'%s on table "'.$name.'" violates FOREIGN KEY constraint "'.$fkname.'"\')' + .' WHERE (SELECT '; + $aliased_fields = array(); + foreach ($referenced_fields as $field) { + $aliased_fields[] = $fkdef['references']['table'] .'.'.$field .' AS '.$field; + } + $query .= implode(',', $aliased_fields) + .' FROM '.$fkdef['references']['table'] + .' WHERE '; + $conditions = array(); + for ($i=0; $iexec(sprintf($query, $trigger_names['insert'], 'INSERT', 'insert')); + if (PEAR::isError($result)) { + return $result; + } + + $result = $db->exec(sprintf($query, $trigger_names['update'], 'UPDATE', 'update')); + if (PEAR::isError($result)) { + return $result; + } + + //create the ON [UPDATE|DELETE] triggers on the primary table + $restrict_action = 'SELECT RAISE(ROLLBACK, \'%s on table "'.$name.'" violates FOREIGN KEY constraint "'.$fkname.'"\')' + .' WHERE (SELECT '; + $aliased_fields = array(); + foreach ($table_fields as $field) { + $aliased_fields[] = $name .'.'.$field .' AS '.$field; + } + $restrict_action .= implode(',', $aliased_fields) + .' FROM '.$name + .' WHERE '; + $conditions = array(); + $new_values = array(); + $null_values = array(); + for ($i=0; $iloadModule('Reverse', null, true); + $default_values = array(); + foreach ($table_fields as $table_field) { + $field_definition = $db->reverse->getTableFieldDefinition($name, $field); + if (PEAR::isError($field_definition)) { + return $field_definition; + } + $default_values[] = $table_field .' = '. $field_definition[0]['default']; + } + $setdefault_action = 'UPDATE '.$name.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions); + } + + $query = 'CREATE TRIGGER %s' + .' %s ON '.$fkdef['references']['table'] + .' FOR EACH ROW BEGIN '; + + if ('CASCADE' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'AFTER UPDATE', 'update') . $cascade_action_update. '; END;'; + } elseif ('SET NULL' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action. '; END;'; + } elseif ('SET DEFAULT' == $fkdef['onupdate']) { + $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action. '; END;'; + } elseif ('NO ACTION' == $fkdef['onupdate']) { + $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update') . '; END;'; + } else { + //'RESTRICT' + $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . '; END;'; + } + if ('CASCADE' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete') . $cascade_action_delete. '; END;'; + } elseif ('SET NULL' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action. '; END;'; + } elseif ('SET DEFAULT' == $fkdef['ondelete']) { + $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action. '; END;'; + } elseif ('NO ACTION' == $fkdef['ondelete']) { + $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete') . '; END;'; + } else { + //'RESTRICT' + $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . '; END;'; + } + + if (PEAR::isError($result)) { + return $result; + } + $result = $db->exec($sql_delete); + if (PEAR::isError($result)) { + return $result; + } + $result = $db->exec($sql_update); + if (PEAR::isError($result)) { + return $result; + } + } + } + if (PEAR::isError($result)) { + return $result; + } + return MDB2_OK; + } + + // }}} + // {{{ dropTable() + + /** + * drop an existing table + * + * @param string $name name of the table that should be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropTable($name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + //delete the triggers associated to existing FK constraints + $constraints = $this->listTableConstraints($name); + if (!PEAR::isError($constraints) && !empty($constraints)) { + $db->loadModule('Reverse', null, true); + foreach ($constraints as $constraint) { + $definition = $db->reverse->getTableConstraintDefinition($name, $constraint); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + + $name = $db->quoteIdentifier($name, true); + return $db->exec("DROP TABLE $name"); + } + + // }}} + // {{{ vacuum() + + /** + * Optimize (vacuum) all the tables in the db (or only the specified table) + * and optionally run ANALYZE. + * + * @param string $table table name (all the tables if empty) + * @param array $options an array with driver-specific options: + * - timeout [int] (in seconds) [mssql-only] + * - analyze [boolean] [pgsql and mysql] + * - full [boolean] [pgsql-only] + * - freeze [boolean] [pgsql-only] + * + * @return mixed MDB2_OK success, a MDB2 error on failure + * @access public + */ + function vacuum($table = null, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'VACUUM'; + if (!empty($table)) { + $query .= ' '.$db->quoteIdentifier($table, true); + } + return $db->exec($query); + } + + // }}} + // {{{ alterTable() + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @access public + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function alterTable($name, $changes, $check, $options = array()) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + case 'remove': + case 'change': + case 'name': + case 'rename': + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'" not yet supported', __FUNCTION__); + } + } + + if ($check) { + return MDB2_OK; + } + + $db->loadModule('Reverse', null, true); + + // actually sqlite 2.x supports no ALTER TABLE at all .. so we emulate it + $fields = $db->manager->listTableFields($name); + if (PEAR::isError($fields)) { + return $fields; + } + + $fields = array_flip($fields); + foreach ($fields as $field => $value) { + $definition = $db->reverse->getTableFieldDefinition($name, $field); + if (PEAR::isError($definition)) { + return $definition; + } + $fields[$field] = $definition[0]; + } + + $indexes = $db->manager->listTableIndexes($name); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $indexes = array_flip($indexes); + foreach ($indexes as $index => $value) { + $definition = $db->reverse->getTableIndexDefinition($name, $index); + if (PEAR::isError($definition)) { + return $definition; + } + $indexes[$index] = $definition; + } + + $constraints = $db->manager->listTableConstraints($name); + if (PEAR::isError($constraints)) { + return $constraints; + } + + if (!array_key_exists('foreign_keys', $options)) { + $options['foreign_keys'] = array(); + } + $constraints = array_flip($constraints); + foreach ($constraints as $constraint => $value) { + if (!empty($definition['primary'])) { + if (!array_key_exists('primary', $options)) { + $options['primary'] = $definition['fields']; + //remove from the $constraint array, it's already handled by createTable() + unset($constraints[$constraint]); + } + } else { + $c_definition = $db->reverse->getTableConstraintDefinition($name, $constraint); + if (PEAR::isError($c_definition)) { + return $c_definition; + } + if (!empty($c_definition['foreign'])) { + if (!array_key_exists($constraint, $options['foreign_keys'])) { + $options['foreign_keys'][$constraint] = $c_definition; + } + //remove from the $constraint array, it's already handled by createTable() + unset($constraints[$constraint]); + } else { + $constraints[$constraint] = $c_definition; + } + } + } + + $name_new = $name; + $create_order = $select_fields = array_keys($fields); + foreach ($changes as $change_name => $change) { + switch ($change_name) { + case 'add': + foreach ($change as $field_name => $field) { + $fields[$field_name] = $field; + $create_order[] = $field_name; + } + break; + case 'remove': + foreach ($change as $field_name => $field) { + unset($fields[$field_name]); + $select_fields = array_diff($select_fields, array($field_name)); + $create_order = array_diff($create_order, array($field_name)); + } + break; + case 'change': + foreach ($change as $field_name => $field) { + $fields[$field_name] = $field['definition']; + } + break; + case 'name': + $name_new = $change; + break; + case 'rename': + foreach ($change as $field_name => $field) { + unset($fields[$field_name]); + $fields[$field['name']] = $field['definition']; + $create_order[array_search($field_name, $create_order)] = $field['name']; + } + break; + default: + return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, + 'change type "'.$change_name.'" not yet supported', __FUNCTION__); + } + } + + $data = null; + if (!empty($select_fields)) { + $query = 'SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier($name, true); + $data = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED); + } + + $result = $this->dropTable($name); + if (PEAR::isError($result)) { + return $result; + } + + $result = $this->createTable($name_new, $fields, $options); + if (PEAR::isError($result)) { + return $result; + } + + foreach ($indexes as $index => $definition) { + $this->createIndex($name_new, $index, $definition); + } + + foreach ($constraints as $constraint => $definition) { + $this->createConstraint($name_new, $constraint, $definition); + } + + if (!empty($select_fields) && !empty($data)) { + $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true); + $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')'; + $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')'; + $stmt =& $db->prepare($query, null, MDB2_PREPARE_MANIP); + if (PEAR::isError($stmt)) { + return $stmt; + } + foreach ($data as $row) { + $result = $stmt->execute($row); + if (PEAR::isError($result)) { + return $result; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ listDatabases() + + /** + * list all databases + * + * @return mixed array of database names on success, a MDB2 error on failure + * @access public + */ + function listDatabases() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'list databases is not supported', __FUNCTION__); + } + + // }}} + // {{{ listUsers() + + /** + * list all users + * + * @return mixed array of user names on success, a MDB2 error on failure + * @access public + */ + function listUsers() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'list databases is not supported', __FUNCTION__); + } + + // }}} + // {{{ listViews() + + /** + * list all views in the current database + * + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listViews() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM sqlite_master WHERE type='view' AND sql NOT NULL"; + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableViews() + + /** + * list the views in the database that reference a given table + * + * @param string table for which all referenced views should be found + * @return mixed array of view names on success, a MDB2 error on failure + * @access public + */ + function listTableViews($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL"; + $views = $db->queryAll($query, array('text', 'text'), MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($views)) { + return $views; + } + $result = array(); + foreach ($views as $row) { + if (preg_match("/^create view .* \bfrom\b\s+\b{$table}\b /i", $row['sql'])) { + if (!empty($row['name'])) { + $result[$row['name']] = true; + } + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ listTables() + + /** + * list all tables in the current database + * + * @return mixed array of table names on success, a MDB2 error on failure + * @access public + */ + function listTables() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name"; + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + $result = array(); + foreach ($table_names as $table_name) { + if (!$this->_fixSequenceName($table_name, true)) { + $result[] = $table_name; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ listTableFields() + + /** + * list all fields in a table in the current database + * + * @param string $table name of table that should be used in method + * @return mixed array of field names on success, a MDB2 error on failure + * @access public + */ + function listTableFields($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Reverse', null, true); + if (PEAR::isError($result)) { + return $result; + } + $query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text'); + } else { + $query.= 'name='.$db->quote($table, 'text'); + } + $sql = $db->queryOne($query); + if (PEAR::isError($sql)) { + return $sql; + } + $columns = $db->reverse->_getTableColumns($sql); + $fields = array(); + foreach ($columns as $column) { + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } else { + $column = array_change_key_case($column, $db->options['field_case']); + } + $fields[] = $column['name']; + } + return $fields; + } + + // }}} + // {{{ listTableTriggers() + + /** + * list all triggers in the database that reference a given table + * + * @param string table for which all referenced triggers should be found + * @return mixed array of trigger names on success, a MDB2 error on failure + * @access public + */ + function listTableTriggers($table = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM sqlite_master WHERE type='trigger' AND sql NOT NULL"; + if (!is_null($table)) { + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= ' AND LOWER(tbl_name)='.$db->quote(strtolower($table), 'text'); + } else { + $query.= ' AND tbl_name='.$db->quote($table, 'text'); + } + } + $result = $db->queryCol($query); + if (PEAR::isError($result)) { + return $result; + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} + // {{{ createIndex() + + /** + * Get the stucture of a field into an array + * + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function support() to determine whether the DBMS driver can manage indexes. + + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ascending' + * ), + * 'last_login' => array() + * ) + * ) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createIndex($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->getIndexName($name); + $query = "CREATE INDEX $name ON $table"; + $fields = array(); + foreach ($definition['fields'] as $field_name => $field) { + $field_string = $field_name; + if (!empty($field['sorting'])) { + switch ($field['sorting']) { + case 'ascending': + $field_string.= ' ASC'; + break; + case 'descending': + $field_string.= ' DESC'; + break; + } + } + $fields[] = $field_string; + } + $query .= ' ('.implode(', ', $fields) . ')'; + return $db->exec($query); + } + + // }}} + // {{{ dropIndex() + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropIndex($table, $name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $name = $db->getIndexName($name); + return $db->exec("DROP INDEX $name"); + } + + // }}} + // {{{ listTableIndexes() + + /** + * list all indexes in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of index names on success, a MDB2 error on failure + * @access public + */ + function listTableIndexes($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quote($table, 'text'); + $query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(tbl_name)='.strtolower($table); + } else { + $query.= "tbl_name=$table"; + } + $query.= " AND sql NOT NULL ORDER BY name"; + $indexes = $db->queryCol($query, 'text'); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $sql) { + if (preg_match("/^create index ([^ ]+) on /i", $sql, $tmp)) { + $index = $this->_fixIndexName($tmp[1]); + if (!empty($index)) { + $result[$index] = true; + } + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createConstraint() + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array() + * ) + * ) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createConstraint($table, $name, $definition) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!empty($definition['primary'])) { + return $db->manager->alterTable($table, array(), false, array('primary' => $definition['fields'])); + } + + if (!empty($definition['foreign'])) { + return $db->manager->alterTable($table, array(), false, array('foreign_keys' => array($name => $definition))); + } + + $table = $db->quoteIdentifier($table, true); + $name = $db->getIndexName($name); + $query = "CREATE UNIQUE INDEX $name ON $table"; + $fields = array(); + foreach ($definition['fields'] as $field_name => $field) { + $field_string = $field_name; + if (!empty($field['sorting'])) { + switch ($field['sorting']) { + case 'ascending': + $field_string.= ' ASC'; + break; + case 'descending': + $field_string.= ' DESC'; + break; + } + } + $fields[] = $field_string; + } + $query .= ' ('.implode(', ', $fields) . ')'; + return $db->exec($query); + } + + // }}} + // {{{ dropConstraint() + + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropConstraint($table, $name, $primary = false) + { + if ($primary || $name == 'PRIMARY') { + return $this->alterTable($table, array(), false, array('primary' => null)); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + //is it a FK constraint? If so, also delete the associated triggers + $db->loadModule('Reverse', null, true); + $definition = $db->reverse->getTableConstraintDefinition($table, $name); + if (!PEAR::isError($definition) && !empty($definition['foreign'])) { + //first drop the FK enforcing triggers + $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']); + if (PEAR::isError($result)) { + return $result; + } + //then drop the constraint itself + return $this->alterTable($table, array(), false, array('foreign_keys' => array($name => null))); + } + + $name = $db->getIndexName($name); + return $db->exec("DROP INDEX $name"); + } + + // }}} + // {{{ _dropFKTriggers() + + /** + * Drop the triggers created to enforce the FOREIGN KEY constraint on the table + * + * @param string $table table name + * @param string $fkname FOREIGN KEY constraint name + * @param string $referenced_table referenced table name + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function _dropFKTriggers($table, $fkname, $referenced_table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $triggers = $this->listTableTriggers($table); + $triggers2 = $this->listTableTriggers($referenced_table); + if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) { + $triggers = array_merge($triggers, $triggers2); + $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i'; + foreach ($triggers as $trigger) { + if (preg_match($pattern, $trigger)) { + $result = $db->exec('DROP TRIGGER '.$trigger); + if (PEAR::isError($result)) { + return $result; + } + } + } + } + return MDB2_OK; + } + + // }]] + // {{{ listTableConstraints() + + /** + * list all constraints in a table + * + * @param string $table name of table that should be used in method + * @return mixed array of constraint names on success, a MDB2 error on failure + * @access public + */ + function listTableConstraints($table) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $table = $db->quote($table, 'text'); + $query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(tbl_name)='.strtolower($table); + } else { + $query.= "tbl_name=$table"; + } + $query.= " AND sql NOT NULL ORDER BY name"; + $indexes = $db->queryCol($query, 'text'); + if (PEAR::isError($indexes)) { + return $indexes; + } + + $result = array(); + foreach ($indexes as $sql) { + if (preg_match("/^create unique index ([^ ]+) on /i", $sql, $tmp)) { + $index = $this->_fixIndexName($tmp[1]); + if (!empty($index)) { + $result[$index] = true; + } + } + } + + // also search in table definition for PRIMARY KEYs... + $query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(name)='.strtolower($table); + } else { + $query.= "name=$table"; + } + $query.= " AND sql NOT NULL ORDER BY name"; + $table_def = $db->queryOne($query, 'text'); + if (PEAR::isError($table_def)) { + return $table_def; + } + if (preg_match("/\bPRIMARY\s+KEY\b/i", $table_def, $tmp)) { + $result['primary'] = true; + } + + // ...and for FOREIGN KEYs + if (preg_match_all("/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN\s+KEY/imsx", $table_def, $tmp)) { + foreach ($tmp[1] as $fk) { + $result[$fk] = true; + } + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_change_key_case($result, $db->options['field_case']); + } + return array_keys($result); + } + + // }}} + // {{{ createSequence() + + /** + * create sequence + * + * @param string $seq_name name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function createSequence($seq_name, $start = 1) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true); + $query = "CREATE TABLE $sequence_name ($seqcol_name INTEGER PRIMARY KEY DEFAULT 0 NOT NULL)"; + $res = $db->exec($query); + if (PEAR::isError($res)) { + return $res; + } + if ($start == 1) { + return MDB2_OK; + } + $res = $db->exec("INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')'); + if (!PEAR::isError($res)) { + return MDB2_OK; + } + // Handle error + $result = $db->exec("DROP TABLE $sequence_name"); + if (PEAR::isError($result)) { + return $db->raiseError($result, null, null, + 'could not drop inconsistent sequence table', __FUNCTION__); + } + return $db->raiseError($res, null, null, + 'could not create sequence table', __FUNCTION__); + } + + // }}} + // {{{ dropSequence() + + /** + * drop existing sequence + * + * @param string $seq_name name of the sequence to be dropped + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function dropSequence($seq_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); + return $db->exec("DROP TABLE $sequence_name"); + } + + // }}} + // {{{ listSequences() + + /** + * list all sequences in the current database + * + * @return mixed array of sequence names on success, a MDB2 error on failure + * @access public + */ + function listSequences() + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name"; + $table_names = $db->queryCol($query); + if (PEAR::isError($table_names)) { + return $table_names; + } + $result = array(); + foreach ($table_names as $table_name) { + if ($sqn = $this->_fixSequenceName($table_name, true)) { + $result[] = $sqn; + } + } + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); + } + return $result; + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/Common.php b/lib/Pear/MDB2/Driver/Native/Common.php new file mode 100644 index 0000000..c01caa3 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/Common.php @@ -0,0 +1,61 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.2 2007/09/09 13:47:36 quipo Exp $ +// + +/** + * Base class for the natuve modules that is extended by each MDB2 driver + * + * To load this module in the MDB2 object: + * $mdb->loadModule('Native'); + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_Common extends MDB2_Module_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/ibase.php b/lib/Pear/MDB2/Driver/Native/ibase.php new file mode 100644 index 0000000..f387e6f --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/ibase.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: ibase.php,v 1.10 2006/06/18 21:59:05 lsmith Exp $ +// + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 FireBird/InterBase driver for the native module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_ibase extends MDB2_Driver_Native_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/mssql.php b/lib/Pear/MDB2/Driver/Native/mssql.php new file mode 100644 index 0000000..e72faba --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/mssql.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mssql.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $ +// + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 MSSQL driver for the native module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_mssql extends MDB2_Driver_Native_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/mysql.php b/lib/Pear/MDB2/Driver/Native/mysql.php new file mode 100644 index 0000000..90ff068 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/mysql.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $ +// + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 MySQL driver for the native module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_mysql extends MDB2_Driver_Native_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/mysqli.php b/lib/Pear/MDB2/Driver/Native/mysqli.php new file mode 100644 index 0000000..326c1d8 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/mysqli.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysqli.php,v 1.8 2006/06/18 21:59:05 lsmith Exp $ +// + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 MySQLi driver for the native module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_mysqli extends MDB2_Driver_Native_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/oci8.php b/lib/Pear/MDB2/Driver/Native/oci8.php new file mode 100644 index 0000000..39053d0 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/oci8.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: oci8.php,v 1.8 2006/06/18 21:59:05 lsmith Exp $ +// + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 Oracle driver for the native module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_oci8 extends MDB2_Driver_Native_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/pgsql.php b/lib/Pear/MDB2/Driver/Native/pgsql.php new file mode 100644 index 0000000..acab838 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/pgsql.php @@ -0,0 +1,88 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: pgsql.php,v 1.12 2006/07/15 13:07:15 lsmith Exp $ + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 PostGreSQL driver for the native module + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_Driver_Native_pgsql extends MDB2_Driver_Native_Common +{ + // }}} + // {{{ deleteOID() + + /** + * delete an OID + * + * @param integer $OID + * @return mixed MDB2_OK on success or MDB2 Error Object on failure + * @access public + */ + function deleteOID($OID) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $connection = $db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + if (!@pg_lo_unlink($connection, $OID)) { + return $db->raiseError(null, null, null, + 'Unable to unlink OID: '.$OID, __FUNCTION__); + } + return MDB2_OK; + } + +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Native/sqlite.php b/lib/Pear/MDB2/Driver/Native/sqlite.php new file mode 100644 index 0000000..0213293 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Native/sqlite.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: sqlite.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $ +// + +require_once 'MDB2/Driver/Native/Common.php'; + +/** + * MDB2 SQLite driver for the native module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common +{ +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/Common.php b/lib/Pear/MDB2/Driver/Reverse/Common.php new file mode 100644 index 0000000..18e9da9 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/Common.php @@ -0,0 +1,513 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.42 2008/01/12 12:50:58 quipo Exp $ +// + +/** + * @package MDB2 + * @category Database + */ + +/** + * These are constants for the tableInfo-function + * they are bitwised or'ed. so if there are more constants to be defined + * in the future, adjust MDB2_TABLEINFO_FULL accordingly + */ + +define('MDB2_TABLEINFO_ORDER', 1); +define('MDB2_TABLEINFO_ORDERTABLE', 2); +define('MDB2_TABLEINFO_FULL', 3); + +/** + * Base class for the schema reverse engineering module that is extended by each MDB2 driver + * + * To load this module in the MDB2 object: + * $mdb->loadModule('Reverse'); + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Reverse_Common extends MDB2_Module_Common +{ + // {{{ splitTableSchema() + + /** + * Split the "[owner|schema].table" notation into an array + * @access private + */ + function splitTableSchema($table) + { + $ret = array(); + if (strpos($table, '.') !== false) { + return explode('.', $table); + } + return array(null, $table); + } + + // }}} + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table name of table that should be used in method + * @param string $field name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure. + * The returned array contains an array for each field definition, + * with all or some of these indices, depending on the field data type: + * [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type] + * @access public + */ + function getTableFieldDefinition($table, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table name of table that should be used in method + * @param string $index name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + * + * array ( + * [fields] => array ( + * [field1name] => array() // one entry per each field covered + * [field2name] => array() // by the index + * [field3name] => array( + * [sorting] => ascending + * ) + * ) + * ); + * + * @access public + */ + function getTableIndexDefinition($table, $index) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of an constraints into an array + * + * @param string $table name of table that should be used in method + * @param string $index name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + *
+     *          array (
+     *              [primary] => 0
+     *              [unique]  => 0
+     *              [foreign] => 1
+     *              [check]   => 0
+     *              [fields] => array (
+     *                  [field1name] => array() // one entry per each field covered
+     *                  [field2name] => array() // by the index
+     *                  [field3name] => array(
+     *                      [sorting]  => ascending
+     *                      [position] => 3
+     *                  )
+     *              )
+     *              [references] => array(
+     *                  [table] => name
+     *                  [fields] => array(
+     *                      [field1name] => array(  //one entry per each referenced field
+     *                           [position] => 1
+     *                      )
+     *                  )
+     *              )
+     *              [deferrable] => 0
+     *              [initiallydeferred] => 0
+     *              [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [match] => SIMPLE|PARTIAL|FULL
+     *          );
+     *          
+ * @access public + */ + function getTableConstraintDefinition($table, $index) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ getSequenceDefinition() + + /** + * Get the structure of a sequence into an array + * + * @param string $sequence name of sequence that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + *
+     *          array (
+     *              [start] => n
+     *          );
+     *          
+ * @access public + */ + function getSequenceDefinition($sequence) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $start = $db->currId($sequence); + if (PEAR::isError($start)) { + return $start; + } + if ($db->supports('current_id')) { + $start++; + } else { + $db->warnings[] = 'database does not support getting current + sequence value, the sequence value was incremented'; + } + $definition = array(); + if ($start != 1) { + $definition = array('start' => $start); + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + *
+     *          array (
+     *              [trigger_name]    => 'trigger name',
+     *              [table_name]      => 'table name',
+     *              [trigger_body]    => 'trigger body definition',
+     *              [trigger_type]    => 'BEFORE' | 'AFTER',
+     *              [trigger_event]   => 'INSERT' | 'UPDATE' | 'DELETE'
+     *                  //or comma separated list of multiple events, when supported
+     *              [trigger_enabled] => true|false
+     *              [trigger_comment] => 'trigger comment',
+     *          );
+     *          
+ * The oci8 driver also returns a [when_clause] index. + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * The format of the resulting array depends on which $mode + * you select. The sample output below is based on this query: + *
+     *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
+     *    FROM tblFoo
+     *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
+     * 
+ * + *
    + *
  • + * + * null (default) + *
    +     *   [0] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   [1] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldPhone
    +     *       [type] => string
    +     *       [len] => 20
    +     *       [flags] =>
    +     *   )
    +     *   [2] => Array (
    +     *       [table] => tblBar
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   
    + * + *
  • + * + * MDB2_TABLEINFO_ORDER + * + *

    In addition to the information found in the default output, + * a notation of the number of columns is provided by the + * num_fields element while the order + * element provides an array with the column names as the keys and + * their location index number (corresponding to the keys in the + * the default output) as the values.

    + * + *

    If a result set has identical field names, the last one is + * used.

    + * + *
    +     *   [num_fields] => 3
    +     *   [order] => Array (
    +     *       [fldId] => 2
    +     *       [fldTrans] => 1
    +     *   )
    +     *   
    + * + *
  • + * + * MDB2_TABLEINFO_ORDERTABLE + * + *

    Similar to MDB2_TABLEINFO_ORDER but adds more + * dimensions to the array in which the table names are keys and + * the field names are sub-keys. This is helpful for queries that + * join tables which have identical field names.

    + * + *
    +     *   [num_fields] => 3
    +     *   [ordertable] => Array (
    +     *       [tblFoo] => Array (
    +     *           [fldId] => 0
    +     *           [fldPhone] => 1
    +     *       )
    +     *       [tblBar] => Array (
    +     *           [fldId] => 2
    +     *       )
    +     *   )
    +     *   
    + * + *
  • + *
+ * + * The flags element contains a space separated list + * of extra information about the field. This data is inconsistent + * between DBMS's due to the way each DBMS works. + * + primary_key + * + unique_key + * + multiple_key + * + not_null + * + * Most DBMS's only provide the table and flags + * elements if $result is a table name. The following DBMS's + * provide full information from queries: + * + fbsql + * + mysql + * + * If the 'portability' option has MDB2_PORTABILITY_FIX_CASE + * turned on, the names of tables and fields will be lower or upper cased. + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode either unused or one of the tableInfo modes: + * MDB2_TABLEINFO_ORDERTABLE, + * MDB2_TABLEINFO_ORDER or + * MDB2_TABLEINFO_FULL (which does both). + * These are bitwise, so the first two can be + * combined using |. + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::setOption() + */ + function tableInfo($result, $mode = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!is_string($result)) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + $db->loadModule('Manager', null, true); + $fields = $db->manager->listTableFields($result); + if (PEAR::isError($fields)) { + return $fields; + } + + $flags = array(); + + $idxname_format = $db->getOption('idxname_format'); + $db->setOption('idxname_format', '%s'); + + $indexes = $db->manager->listTableIndexes($result); + if (PEAR::isError($indexes)) { + $db->setOption('idxname_format', $idxname_format); + return $indexes; + } + + foreach ($indexes as $index) { + $definition = $this->getTableIndexDefinition($result, $index); + if (PEAR::isError($definition)) { + $db->setOption('idxname_format', $idxname_format); + return $definition; + } + if (count($definition['fields']) > 1) { + foreach ($definition['fields'] as $field => $sort) { + $flags[$field] = 'multiple_key'; + } + } + } + + $constraints = $db->manager->listTableConstraints($result); + if (PEAR::isError($constraints)) { + return $constraints; + } + + foreach ($constraints as $constraint) { + $definition = $this->getTableConstraintDefinition($result, $constraint); + if (PEAR::isError($definition)) { + $db->setOption('idxname_format', $idxname_format); + return $definition; + } + $flag = !empty($definition['primary']) + ? 'primary_key' : (!empty($definition['unique']) + ? 'unique_key' : false); + if ($flag) { + foreach ($definition['fields'] as $field => $sort) { + if (empty($flags[$field]) || $flags[$field] != 'primary_key') { + $flags[$field] = $flag; + } + } + } + } + + $res = array(); + + if ($mode) { + $res['num_fields'] = count($fields); + } + + foreach ($fields as $i => $field) { + $definition = $this->getTableFieldDefinition($result, $field); + if (PEAR::isError($definition)) { + $db->setOption('idxname_format', $idxname_format); + return $definition; + } + $res[$i] = $definition[0]; + $res[$i]['name'] = $field; + $res[$i]['table'] = $result; + $res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype'])); + // 'primary_key', 'unique_key', 'multiple_key' + $res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field]; + // not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]' + if (!empty($res[$i]['notnull'])) { + $res[$i]['flags'].= ' not_null'; + } + if (!empty($res[$i]['unsigned'])) { + $res[$i]['flags'].= ' unsigned'; + } + if (!empty($res[$i]['auto_increment'])) { + $res[$i]['flags'].= ' autoincrement'; + } + if (!empty($res[$i]['default'])) { + $res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']); + } + + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + $db->setOption('idxname_format', $idxname_format); + return $res; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/ibase.php b/lib/Pear/MDB2/Driver/Reverse/ibase.php new file mode 100644 index 0000000..ac828a6 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/ibase.php @@ -0,0 +1,581 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: ibase.php,v 1.78 2007/11/25 13:38:29 quipo Exp $ +// + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 InterbaseBase driver for the reverse engineering module + * + * @package MDB2 + * @category Database + * @author Lorenzo Alberton + */ +class MDB2_Driver_Reverse_ibase extends MDB2_Driver_Reverse_Common +{ + /** + * Array for converting constant values to text values + * @var array + * @access public + */ + var $types = array( + 7 => 'smallint', + 8 => 'integer', + 9 => 'quad', + 10 => 'float', + 11 => 'd_float', + 12 => 'date', //dialect 3 DATE + 13 => 'time', + 14 => 'char', + 16 => 'int64', + 27 => 'double', + 35 => 'timestamp', //DATE in older versions + 37 => 'varchar', + 40 => 'cstring', + 261 => 'blob', + ); + + /** + * Array for converting constant values to text values + * @var array + * @access public + */ + var $subtypes = array( + //char subtypes + 14 => array( + 0 => 'unspecified', + 1 => 'fixed', //BINARY data + ), + //blob subtypes + 261 => array( + 0 => 'unspecified', + 1 => 'text', + 2 => 'BLR', //Binary Language Representation + 3 => 'access control list', + 4 => 'reserved for future use', + 5 => 'encoded description of a table\'s current metadata', + 6 => 'description of multi-database transaction that finished irregularly', + ), + //smallint subtypes + 7 => array( + 0 => 'RDB$FIELD_TYPE', + 1 => 'numeric', + 2 => 'decimal', + ), + //integer subtypes + 8 => array( + 0 => 'RDB$FIELD_TYPE', + 1 => 'numeric', + 2 => 'decimal', + ), + //int64 subtypes + 16 => array( + 0 => 'RDB$FIELD_TYPE', + 1 => 'numeric', + 2 => 'decimal', + ), + ); + + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quote(strtoupper($table), 'text'); + $field_name = $db->quote(strtoupper($field_name), 'text'); + $query = "SELECT RDB\$RELATION_FIELDS.RDB\$FIELD_NAME AS name, + RDB\$FIELDS.RDB\$FIELD_LENGTH AS \"length\", + RDB\$FIELDS.RDB\$FIELD_PRECISION AS \"precision\", + (RDB\$FIELDS.RDB\$FIELD_SCALE * -1) AS \"scale\", + RDB\$FIELDS.RDB\$FIELD_TYPE AS field_type_code, + RDB\$FIELDS.RDB\$FIELD_SUB_TYPE AS field_sub_type_code, + RDB\$RELATION_FIELDS.RDB\$DESCRIPTION AS description, + RDB\$RELATION_FIELDS.RDB\$NULL_FLAG AS null_flag, + RDB\$FIELDS.RDB\$DEFAULT_SOURCE AS default_source + FROM RDB\$FIELDS + LEFT JOIN RDB\$RELATION_FIELDS ON RDB\$FIELDS.RDB\$FIELD_NAME = RDB\$RELATION_FIELDS.RDB\$FIELD_SOURCE + WHERE UPPER(RDB\$RELATION_FIELDS.RDB\$RELATION_NAME)=$table + AND UPPER(RDB\$RELATION_FIELDS.RDB\$FIELD_NAME)=$field_name;"; + $column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($column)) { + return $column; + } + if (empty($column)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table column', __FUNCTION__); + } + $column = array_change_key_case($column, CASE_LOWER); + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } + + $column['type'] = array_key_exists((int)$column['field_type_code'], $this->types) + ? $this->types[(int)$column['field_type_code']] : 'undefined'; + if ($column['field_sub_type_code'] + && array_key_exists((int)$column['field_type_code'], $this->subtypes) + && array_key_exists($column['field_sub_type_code'], $this->subtypes[(int)$column['field_type_code']]) + ) { + $column['field_sub_type'] = $this->subtypes[(int)$column['field_type_code']][$column['field_sub_type_code']]; + } else { + $column['field_sub_type'] = null; + } + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = !empty($column['null_flag']); + $default = $column['default_source']; + if (is_null($default) && $notnull) { + $default = ($types[0] == 'integer') ? 0 : ''; + } + + $definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + return $definition; + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name, $format_index_name = true) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quote(strtoupper($table), 'text'); + $query = "SELECT RDB\$INDEX_SEGMENTS.RDB\$FIELD_NAME AS field_name, + RDB\$INDICES.RDB\$DESCRIPTION AS description, + (RDB\$INDEX_SEGMENTS.RDB\$FIELD_POSITION + 1) AS field_position + FROM RDB\$INDEX_SEGMENTS + LEFT JOIN RDB\$INDICES ON RDB\$INDICES.RDB\$INDEX_NAME = RDB\$INDEX_SEGMENTS.RDB\$INDEX_NAME + LEFT JOIN RDB\$RELATION_CONSTRAINTS ON RDB\$RELATION_CONSTRAINTS.RDB\$INDEX_NAME = RDB\$INDEX_SEGMENTS.RDB\$INDEX_NAME + WHERE UPPER(RDB\$INDICES.RDB\$RELATION_NAME)=$table + AND UPPER(RDB\$INDICES.RDB\$INDEX_NAME)=%s + AND RDB\$RELATION_CONSTRAINTS.RDB\$CONSTRAINT_TYPE IS NULL + ORDER BY RDB\$INDEX_SEGMENTS.RDB\$FIELD_POSITION"; + $index_name_mdb2 = $db->quote(strtoupper($db->getIndexName($index_name)), 'text'); + $result = $db->queryRow(sprintf($query, $index_name_mdb2)); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $index_name = $index_name_mdb2; + } else { + $index_name = $db->quote(strtoupper($index_name), 'text'); + } + $result = $db->query(sprintf($query, $index_name)); + if (PEAR::isError($result)) { + return $result; + } + + $definition = array(); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $column_name = $row['field_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => (int)$row['field_position'], + ); + /* + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' + ? 'ascending' : 'descending'); + } + */ + } + + $result->free(); + if (empty($definition)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table index', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quote(strtoupper($table), 'text'); + $query = "SELECT rc.RDB\$CONSTRAINT_NAME, + s.RDB\$FIELD_NAME AS field_name, + CASE WHEN rc.RDB\$CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1 ELSE 0 END AS \"primary\", + CASE WHEN rc.RDB\$CONSTRAINT_TYPE = 'FOREIGN KEY' THEN 1 ELSE 0 END AS \"foreign\", + CASE WHEN rc.RDB\$CONSTRAINT_TYPE = 'UNIQUE' THEN 1 ELSE 0 END AS \"unique\", + CASE WHEN rc.RDB\$CONSTRAINT_TYPE = 'CHECK' THEN 1 ELSE 0 END AS \"check\", + i.RDB\$DESCRIPTION AS description, + CASE WHEN rc.RDB\$DEFERRABLE = 'NO' THEN 0 ELSE 1 END AS deferrable, + CASE WHEN rc.RDB\$INITIALLY_DEFERRED = 'NO' THEN 0 ELSE 1 END AS initiallydeferred, + refc.RDB\$UPDATE_RULE AS onupdate, + refc.RDB\$DELETE_RULE AS ondelete, + refc.RDB\$MATCH_OPTION AS \"match\", + i2.RDB\$RELATION_NAME AS references_table, + s2.RDB\$FIELD_NAME AS references_field, + (s.RDB\$FIELD_POSITION + 1) AS field_position + FROM RDB\$INDEX_SEGMENTS s + LEFT JOIN RDB\$INDICES i ON i.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME + LEFT JOIN RDB\$RELATION_CONSTRAINTS rc ON rc.RDB\$INDEX_NAME = s.RDB\$INDEX_NAME + LEFT JOIN RDB\$REF_CONSTRAINTS refc ON rc.RDB\$CONSTRAINT_NAME = refc.RDB\$CONSTRAINT_NAME + LEFT JOIN RDB\$RELATION_CONSTRAINTS rc2 ON rc2.RDB\$CONSTRAINT_NAME = refc.RDB\$CONST_NAME_UQ + LEFT JOIN RDB\$INDICES i2 ON i2.RDB\$INDEX_NAME = rc2.RDB\$INDEX_NAME + LEFT JOIN RDB\$INDEX_SEGMENTS s2 ON i2.RDB\$INDEX_NAME = s2.RDB\$INDEX_NAME + AND s.RDB\$FIELD_POSITION = s2.RDB\$FIELD_POSITION + WHERE UPPER(i.RDB\$RELATION_NAME)=$table + AND UPPER(rc.RDB\$CONSTRAINT_NAME)=%s + AND rc.RDB\$CONSTRAINT_TYPE IS NOT NULL + ORDER BY s.RDB\$FIELD_POSITION"; + $constraint_name_mdb2 = $db->quote(strtoupper($db->getIndexName($constraint_name)), 'text'); + $result = $db->queryRow(sprintf($query, $constraint_name_mdb2)); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $constraint_name = $constraint_name_mdb2; + } else { + $constraint_name = $db->quote(strtoupper($constraint_name), 'text'); + } + $result = $db->query(sprintf($query, $constraint_name)); + if (PEAR::isError($result)) { + return $result; + } + + $definition = array(); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $column_name = $row['field_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => (int)$row['field_position'] + ); + if ($row['foreign']) { + $ref_column_name = $row['references_field']; + $ref_table_name = $row['references_table']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $ref_column_name = strtolower($ref_column_name); + $ref_table_name = strtolower($ref_table_name); + } else { + $ref_column_name = strtoupper($ref_column_name); + $ref_table_name = strtoupper($ref_table_name); + } + } + $definition['references']['table'] = $ref_table_name; + $definition['references']['fields'][$ref_column_name] = array( + 'position' => (int)$row['field_position'] + ); + } + //collation?!? + /* + if (!empty($row['collation'])) { + $definition['fields'][$field]['sorting'] = ($row['collation'] == 'A' + ? 'ascending' : 'descending'); + } + */ + $lastrow = $row; + // otherwise $row is no longer usable on exit from loop + } + $result->free(); + if (empty($definition)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + + $definition['primary'] = (boolean)$lastrow['primary']; + $definition['unique'] = (boolean)$lastrow['unique']; + $definition['foreign'] = (boolean)$lastrow['foreign']; + $definition['check'] = (boolean)$lastrow['check']; + $definition['deferrable'] = (boolean)$lastrow['deferrable']; + $definition['initiallydeferred'] = (boolean)$lastrow['initiallydeferred']; + $definition['onupdate'] = $lastrow['onupdate']; + $definition['ondelete'] = $lastrow['ondelete']; + $definition['match'] = $lastrow['match']; + + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $trigger = $db->quote(strtoupper($trigger), 'text'); + $query = "SELECT RDB\$TRIGGER_NAME AS trigger_name, + RDB\$RELATION_NAME AS table_name, + RDB\$TRIGGER_SOURCE AS trigger_body, + CASE RDB\$TRIGGER_TYPE + WHEN 1 THEN 'BEFORE' + WHEN 2 THEN 'AFTER' + WHEN 3 THEN 'BEFORE' + WHEN 4 THEN 'AFTER' + WHEN 5 THEN 'BEFORE' + WHEN 6 THEN 'AFTER' + END AS trigger_type, + CASE RDB\$TRIGGER_TYPE + WHEN 1 THEN 'INSERT' + WHEN 2 THEN 'INSERT' + WHEN 3 THEN 'UPDATE' + WHEN 4 THEN 'UPDATE' + WHEN 5 THEN 'DELETE' + WHEN 6 THEN 'DELETE' + END AS trigger_event, + CASE RDB\$TRIGGER_INACTIVE + WHEN 1 THEN 0 ELSE 1 + END AS trigger_enabled, + RDB\$DESCRIPTION AS trigger_comment + FROM RDB\$TRIGGERS + WHERE UPPER(RDB\$TRIGGER_NAME)=$trigger"; + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'clob', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + 'trigger_comment' => 'text', + 'trigger_enabled' => 'boolean', + ); + + $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($def)) { + return $def; + } + + $clob = $def['trigger_body']; + if (!PEAR::isError($clob) && is_resource($clob)) { + $value = ''; + while (!feof($clob)) { + $data = fread($clob, 8192); + $value.= $data; + } + $db->datatype->destroyLOB($clob); + $def['trigger_body'] = $value; + } + + return $def; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; + if (!is_resource($resource)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Could not generate result resource', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $case_func = 'strtolower'; + } else { + $case_func = 'strtoupper'; + } + } else { + $case_func = 'strval'; + } + + $count = @ibase_num_fields($resource); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + $db->loadModule('Datatype', null, true); + for ($i = 0; $i < $count; $i++) { + $info = @ibase_field_info($resource, $i); + if (($pos = strpos($info['type'], '(')) !== false) { + $info['type'] = substr($info['type'], 0, $pos); + } + $res[$i] = array( + 'table' => $case_func($info['relation']), + 'name' => $case_func($info['name']), + 'type' => $info['type'], + 'length' => $info['length'], + 'flags' => '', + ); + $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); + if (PEAR::isError($mdb2type_info)) { + return $mdb2type_info; + } + $res[$i]['mdb2type'] = $mdb2type_info[0][0]; + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/mssql.php b/lib/Pear/MDB2/Driver/Reverse/mssql.php new file mode 100644 index 0000000..0991190 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/mssql.php @@ -0,0 +1,653 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: mssql.php,v 1.49 2008/02/17 15:30:57 quipo Exp $ +// + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 MSSQL driver for the schema reverse engineering module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + * @author Lorenzo Alberton + */ +class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common +{ + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + $fldname = $db->quoteIdentifier($field_name, true); + + $query = "SELECT t.table_name, + c.column_name 'name', + c.data_type 'type', + CASE c.is_nullable WHEN 'YES' THEN 1 ELSE 0 END AS 'is_nullable', + c.column_default, + c.character_maximum_length 'length', + c.numeric_precision, + c.numeric_scale, + c.character_set_name, + c.collation_name + FROM INFORMATION_SCHEMA.TABLES t, + INFORMATION_SCHEMA.COLUMNS c + WHERE t.table_name = c.table_name + AND t.table_name = '$table' + AND c.column_name = '$fldname'"; + if (!empty($schema)) { + $query .= " AND t.table_schema = '" .$db->quoteIdentifier($schema, true) ."'"; + } + $query .= ' ORDER BY t.table_name'; + $column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($column)) { + return $column; + } + if (empty($column)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table column', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } else { + $column = array_change_key_case($column, $db->options['field_case']); + } + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = true; + if ($column['is_nullable']) { + $notnull = false; + } + $default = false; + if (array_key_exists('column_default', $column)) { + $default = $column['column_default']; + if (is_null($default) && $notnull) { + $default = ''; + } elseif (strlen($default) > 4 + && substr($default, 0, 1) == '(' + && substr($default, -1, 1) == ')' + ) { + //mssql wraps the default value in parentheses: "((1234))", "(NULL)" + $default = trim($default, '()'); + if ($default == 'NULL') { + $default = null; + } + } + } + $definition[0] = array( + 'notnull' => $notnull, + 'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type']) + ); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + return $definition; + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + //$idxname = $db->quoteIdentifier($index_name, true); + + $query = "SELECT OBJECT_NAME(i.id) tablename, + i.name indexname, + c.name field_name, + CASE INDEXKEY_PROPERTY(i.id, i.indid, ik.keyno, 'IsDescending') + WHEN 1 THEN 'DESC' ELSE 'ASC' + END 'collation', + ik.keyno 'position' + FROM sysindexes i + JOIN sysindexkeys ik ON ik.id = i.id AND ik.indid = i.indid + JOIN syscolumns c ON c.id = ik.id AND c.colid = ik.colid + WHERE OBJECT_NAME(i.id) = '$table' + AND i.name = '%s' + AND NOT EXISTS ( + SELECT * + FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k + WHERE k.table_name = OBJECT_NAME(i.id) + AND k.constraint_name = i.name"; + if (!empty($schema)) { + $query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'"; + } + $query .= ') + ORDER BY tablename, indexname, ik.keyno'; + + $index_name_mdb2 = $db->getIndexName($index_name); + $result = $db->queryRow(sprintf($query, $index_name_mdb2)); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $index_name = $index_name_mdb2; + } + $result = $db->query(sprintf($query, $index_name)); + if (PEAR::isError($result)) { + return $result; + } + + $definition = array(); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $column_name = $row['field_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => (int)$row['position'], + ); + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC' + ? 'ascending' : 'descending'); + } + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table index', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + $query = "SELECT k.table_name, + k.column_name field_name, + CASE c.constraint_type WHEN 'PRIMARY KEY' THEN 1 ELSE 0 END 'primary', + CASE c.constraint_type WHEN 'UNIQUE' THEN 1 ELSE 0 END 'unique', + CASE c.constraint_type WHEN 'FOREIGN KEY' THEN 1 ELSE 0 END 'foreign', + CASE c.constraint_type WHEN 'CHECK' THEN 1 ELSE 0 END 'check', + CASE c.is_deferrable WHEN 'NO' THEN 0 ELSE 1 END 'deferrable', + CASE c.initially_deferred WHEN 'NO' THEN 0 ELSE 1 END 'initiallydeferred', + rc.match_option 'match', + rc.update_rule 'onupdate', + rc.delete_rule 'ondelete', + kcu.table_name 'references_table', + kcu.column_name 'references_field', + k.ordinal_position 'field_position' + FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k + LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c + ON k.table_name = c.table_name + AND k.table_schema = c.table_schema + AND k.table_catalog = c.table_catalog + AND k.constraint_catalog = c.constraint_catalog + AND k.constraint_name = c.constraint_name + LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc + ON rc.constraint_schema = c.constraint_schema + AND rc.constraint_catalog = c.constraint_catalog + AND rc.constraint_name = c.constraint_name + LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu + ON rc.unique_constraint_schema = kcu.constraint_schema + AND rc.unique_constraint_catalog = kcu.constraint_catalog + AND rc.unique_constraint_name = kcu.constraint_name + AND k.ordinal_position = kcu.ordinal_position + WHERE k.constraint_catalog = DB_NAME() + AND k.table_name = '$table' + AND k.constraint_name = '%s'"; + if (!empty($schema)) { + $query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'"; + } + $query .= ' ORDER BY k.constraint_name, + k.ordinal_position'; + + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + $result = $db->queryRow(sprintf($query, $constraint_name_mdb2)); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $constraint_name = $constraint_name_mdb2; + } + $result = $db->query(sprintf($query, $constraint_name)); + if (PEAR::isError($result)) { + return $result; + } + + $definition = array( + 'fields' => array() + ); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $column_name = $row['field_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => (int)$row['field_position'] + ); + if ($row['foreign']) { + $ref_column_name = $row['references_field']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $ref_column_name = strtolower($ref_column_name); + } else { + $ref_column_name = strtoupper($ref_column_name); + } + } + $definition['references']['table'] = $row['references_table']; + $definition['references']['fields'][$ref_column_name] = array( + 'position' => (int)$row['field_position'] + ); + } + //collation?!? + /* + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC' + ? 'ascending' : 'descending'); + } + */ + $lastrow = $row; + // otherwise $row is no longer usable on exit from loop + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + + $definition['primary'] = (boolean)$lastrow['primary']; + $definition['unique'] = (boolean)$lastrow['unique']; + $definition['foreign'] = (boolean)$lastrow['foreign']; + $definition['check'] = (boolean)$lastrow['check']; + $definition['deferrable'] = (boolean)$lastrow['deferrable']; + $definition['initiallydeferred'] = (boolean)$lastrow['initiallydeferred']; + $definition['onupdate'] = $lastrow['onupdate']; + $definition['ondelete'] = $lastrow['ondelete']; + $definition['match'] = $lastrow['match']; + + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT sys1.name trigger_name, + sys2.name table_name, + c.text trigger_body, + c.encrypted is_encripted, + CASE + WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1 + THEN 0 ELSE 1 + END trigger_enabled, + CASE + WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1 + THEN 'INSERT' + WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1 + THEN 'UPDATE' + WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1 + THEN 'DELETE' + END trigger_event, + CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1 + THEN 'INSTEAD OF' ELSE 'AFTER' + END trigger_type, + '' trigger_comment + FROM sysobjects sys1 + JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id + JOIN syscomments c ON sys1.id = c.id + WHERE sys1.xtype = 'TR' + AND sys1.name = ". $db->quote($trigger, 'text'); + + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'text', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + 'trigger_comment' => 'text', + 'trigger_enabled' => 'boolean', + 'is_encripted' => 'boolean', + ); + + $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($def)) { + return $def; + } + $trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text'); + if (!PEAR::isError($trg_body)) { + $def['trigger_body'] = implode(' ', $trg_body); + } + return $def; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; + if (!is_resource($resource)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Could not generate result resource', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $case_func = 'strtolower'; + } else { + $case_func = 'strtoupper'; + } + } else { + $case_func = 'strval'; + } + + $count = @mssql_num_fields($resource); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + $db->loadModule('Datatype', null, true); + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => '', + 'name' => $case_func(@mssql_field_name($resource, $i)), + 'type' => @mssql_field_type($resource, $i), + 'length' => @mssql_field_length($resource, $i), + 'flags' => '', + ); + $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); + if (PEAR::isError($mdb2type_info)) { + return $mdb2type_info; + } + $res[$i]['mdb2type'] = $mdb2type_info[0][0]; + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } + + // }}} + // {{{ _mssql_field_flags() + + /** + * Get a column's flags + * + * Supports "not_null", "primary_key", + * "auto_increment" (mssql identity), "timestamp" (mssql timestamp), + * "unique_key" (mssql unique index, unique check or primary_key) and + * "multiple_key" (multikey index) + * + * mssql timestamp is NOT similar to the mysql timestamp so this is maybe + * not useful at all - is the behaviour of mysql_field_flags that primary + * keys are alway unique? is the interpretation of multiple_key correct? + * + * @param string $table the table name + * @param string $column the field name + * + * @return string the flags + * + * @access protected + * @author Joern Barthel + */ + function _mssql_field_flags($table, $column) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + static $tableName = null; + static $flags = array(); + + if ($table != $tableName) { + + $flags = array(); + $tableName = $table; + + // get unique and primary keys + $res = $db->queryAll("EXEC SP_HELPINDEX[$table]", null, MDB2_FETCHMODE_ASSOC); + + foreach ($res as $val) { + $val = array_change_key_case($val, CASE_LOWER); + $keys = explode(', ', $val['index_keys']); + + if (sizeof($keys) > 1) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'multiple_key'); + } + } + + if (strpos($val['index_description'], 'primary key')) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'primary_key'); + } + } elseif (strpos($val['index_description'], 'unique')) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'unique_key'); + } + } + } + + // get auto_increment, not_null and timestamp + $res = $db->queryAll("EXEC SP_COLUMNS[$table]", null, MDB2_FETCHMODE_ASSOC); + + foreach ($res as $val) { + $val = array_change_key_case($val, CASE_LOWER); + if ($val['nullable'] == '0') { + $this->_add_flag($flags[$val['column_name']], 'not_null'); + } + if (strpos($val['type_name'], 'identity')) { + $this->_add_flag($flags[$val['column_name']], 'auto_increment'); + } + if (strpos($val['type_name'], 'timestamp')) { + $this->_add_flag($flags[$val['column_name']], 'timestamp'); + } + } + } + + if (!empty($flags[$column])) { + return(implode(' ', $flags[$column])); + } + return ''; + } + + // }}} + // {{{ _add_flag() + + /** + * Adds a string to the flags array if the flag is not yet in there + * - if there is no flag present the array is created + * + * @param array &$array the reference to the flag-array + * @param string $value the flag value + * + * @return void + * + * @access protected + * @author Joern Barthel + */ + function _add_flag(&$array, $value) + { + if (!is_array($array)) { + $array = array($value); + } elseif (!in_array($value, $array)) { + array_push($array, $value); + } + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/mysql.php b/lib/Pear/MDB2/Driver/Reverse/mysql.php new file mode 100644 index 0000000..ac6abed --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/mysql.php @@ -0,0 +1,514 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.79 2007/11/25 13:38:29 quipo Exp $ +// + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 MySQL driver for the schema reverse engineering module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + * @author Lorenzo Alberton + */ +class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common +{ + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name); + $columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($columns)) { + return $columns; + } + foreach ($columns as $column) { + $column = array_change_key_case($column, CASE_LOWER); + $column['name'] = $column['field']; + unset($column['field']); + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } else { + $column = array_change_key_case($column, $db->options['field_case']); + } + if ($field_name == $column['name']) { + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = false; + if (empty($column['null']) || $column['null'] !== 'YES') { + $notnull = true; + } + $default = false; + if (array_key_exists('default', $column)) { + $default = $column['default']; + if (is_null($default) && $notnull) { + $default = ''; + } + } + $autoincrement = false; + if (!empty($column['extra']) && $column['extra'] == 'auto_increment') { + $autoincrement = true; + } + $collate = null; + if (!empty($column['collation'])) { + $collate = $column['collation']; + $charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate); + } + + $definition[0] = array( + 'notnull' => $notnull, + 'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type']) + ); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + if ($autoincrement !== false) { + $definition[0]['autoincrement'] = $autoincrement; + } + if (!is_null($collate)) { + $definition[0]['collate'] = $collate; + $definition[0]['charset'] = $charset; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) { + $definition[$key]['default'] = '0000-00-00 00:00:00'; + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + return $definition; + } + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table column', __FUNCTION__); + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */"; + $index_name_mdb2 = $db->getIndexName($index_name); + $result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2))); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $index_name = $index_name_mdb2; + } + $result = $db->query(sprintf($query, $db->quote($index_name))); + if (PEAR::isError($result)) { + return $result; + } + $colpos = 1; + $definition = array(); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $key_name = $row['key_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + } else { + $key_name = strtoupper($key_name); + } + } + if ($index_name == $key_name) { + if (!$row['non_unique']) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name . ' is not an existing table index', __FUNCTION__); + } + $column_name = $row['column_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => $colpos++ + ); + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' + ? 'ascending' : 'descending'); + } + } + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name . ' is not an existing table index', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + $constraint_name_original = $constraint_name; + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */"; + if (strtolower($constraint_name) != 'primary') { + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + $result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2))); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $constraint_name = $constraint_name_mdb2; + } + } + $result = $db->query(sprintf($query, $db->quote($constraint_name))); + if (PEAR::isError($result)) { + return $result; + } + $colpos = 1; + //default values, eventually overridden + $definition = array( + 'primary' => false, + 'unique' => false, + 'foreign' => false, + 'check' => false, + 'fields' => array(), + 'references' => array( + 'table' => '', + 'fields' => array(), + ), + 'onupdate' => '', + 'ondelete' => '', + 'match' => '', + 'deferrable' => false, + 'initiallydeferred' => false, + ); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $key_name = $row['key_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + } else { + $key_name = strtoupper($key_name); + } + } + if ($constraint_name == $key_name) { + if ($row['non_unique']) { + //FOREIGN KEY? + $query = 'SHOW CREATE TABLE '. $db->escape($table); + $constraint = $db->queryOne($query, 'text', 1); + if (!PEAR::isError($constraint) && !empty($constraint)) { + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $constraint = strtolower($constraint); + } else { + $constraint = strtoupper($constraint); + } + } + $pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i'; + if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) { + //fallback to original constraint name + $pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i'; + } + if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) { + $definition['foreign'] = true; + $column_names = explode(',', $matches[1]); + $referenced_cols = explode(',', $matches[3]); + $definition['references'] = array( + 'table' => $matches[2], + 'fields' => array(), + ); + $colpos = 1; + foreach ($column_names as $column_name) { + $definition['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + $colpos = 1; + foreach ($referenced_cols as $column_name) { + $definition['references']['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + $definition['onupdate'] = 'NO ACTION'; + $definition['ondelete'] = 'NO ACTION'; + $definition['match'] = 'SIMPLE'; + return $definition; + } + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + if ($row['key_name'] == 'PRIMARY') { + $definition['primary'] = true; + } elseif (!$row['non_unique']) { + $definition['unique'] = true; + } + $column_name = $row['column_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => $colpos++ + ); + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' + ? 'ascending' : 'descending'); + } + } + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT trigger_name, + event_object_table AS table_name, + action_statement AS trigger_body, + action_timing AS trigger_type, + event_manipulation AS trigger_event + FROM information_schema.triggers + WHERE trigger_name = '. $db->quote($trigger, 'text'); + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'text', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + ); + $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($def)) { + return $def; + } + $def['trigger_comment'] = ''; + $def['trigger_enabled'] = true; + return $def; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::setOption() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; + if (!is_resource($resource)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Could not generate result resource', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $case_func = 'strtolower'; + } else { + $case_func = 'strtoupper'; + } + } else { + $case_func = 'strval'; + } + + $count = @mysql_num_fields($resource); + $res = array(); + if ($mode) { + $res['num_fields'] = $count; + } + + $db->loadModule('Datatype', null, true); + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $case_func(@mysql_field_table($resource, $i)), + 'name' => $case_func(@mysql_field_name($resource, $i)), + 'type' => @mysql_field_type($resource, $i), + 'length' => @mysql_field_len($resource, $i), + 'flags' => @mysql_field_flags($resource, $i), + ); + if ($res[$i]['type'] == 'string') { + $res[$i]['type'] = 'char'; + } elseif ($res[$i]['type'] == 'unknown') { + $res[$i]['type'] = 'decimal'; + } + $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); + if (PEAR::isError($mdb2type_info)) { + return $mdb2type_info; + } + $res[$i]['mdb2type'] = $mdb2type_info[0][0]; + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/mysqli.php b/lib/Pear/MDB2/Driver/Reverse/mysqli.php new file mode 100644 index 0000000..741fac0 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/mysqli.php @@ -0,0 +1,578 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysqli.php,v 1.69 2007/11/25 13:38:29 quipo Exp $ +// + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 MySQLi driver for the schema reverse engineering module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + * @author Lorenzo Alberton + */ +class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common +{ + /** + * Array for converting MYSQLI_*_FLAG constants to text values + * @var array + * @access public + */ + var $flags = array( + MYSQLI_NOT_NULL_FLAG => 'not_null', + MYSQLI_PRI_KEY_FLAG => 'primary_key', + MYSQLI_UNIQUE_KEY_FLAG => 'unique_key', + MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key', + MYSQLI_BLOB_FLAG => 'blob', + MYSQLI_UNSIGNED_FLAG => 'unsigned', + MYSQLI_ZEROFILL_FLAG => 'zerofill', + MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment', + MYSQLI_TIMESTAMP_FLAG => 'timestamp', + MYSQLI_SET_FLAG => 'set', + // MYSQLI_NUM_FLAG => 'numeric', // unnecessary + // MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie + MYSQLI_GROUP_FLAG => 'group_by' + ); + + /** + * Array for converting MYSQLI_TYPE_* constants to text values + * @var array + * @access public + */ + var $types = array( + MYSQLI_TYPE_DECIMAL => 'decimal', + 246 => 'decimal', + MYSQLI_TYPE_TINY => 'tinyint', + MYSQLI_TYPE_SHORT => 'int', + MYSQLI_TYPE_LONG => 'int', + MYSQLI_TYPE_FLOAT => 'float', + MYSQLI_TYPE_DOUBLE => 'double', + // MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it + MYSQLI_TYPE_TIMESTAMP => 'timestamp', + MYSQLI_TYPE_LONGLONG => 'bigint', + MYSQLI_TYPE_INT24 => 'mediumint', + MYSQLI_TYPE_DATE => 'date', + MYSQLI_TYPE_TIME => 'time', + MYSQLI_TYPE_DATETIME => 'datetime', + MYSQLI_TYPE_YEAR => 'year', + MYSQLI_TYPE_NEWDATE => 'date', + MYSQLI_TYPE_ENUM => 'enum', + MYSQLI_TYPE_SET => 'set', + MYSQLI_TYPE_TINY_BLOB => 'tinyblob', + MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', + MYSQLI_TYPE_LONG_BLOB => 'longblob', + MYSQLI_TYPE_BLOB => 'blob', + MYSQLI_TYPE_VAR_STRING => 'varchar', + MYSQLI_TYPE_STRING => 'char', + MYSQLI_TYPE_GEOMETRY => 'geometry', + ); + + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name); + $columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($columns)) { + return $columns; + } + foreach ($columns as $column) { + $column = array_change_key_case($column, CASE_LOWER); + $column['name'] = $column['field']; + unset($column['field']); + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } else { + $column = array_change_key_case($column, $db->options['field_case']); + } + if ($field_name == $column['name']) { + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = false; + if (empty($column['null']) || $column['null'] !== 'YES') { + $notnull = true; + } + $default = false; + if (array_key_exists('default', $column)) { + $default = $column['default']; + if (is_null($default) && $notnull) { + $default = ''; + } + } + $autoincrement = false; + if (!empty($column['extra']) && $column['extra'] == 'auto_increment') { + $autoincrement = true; + } + $collate = null; + if (!empty($column['collation'])) { + $collate = $column['collation']; + $charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate); + } + + $definition[0] = array( + 'notnull' => $notnull, + 'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type']) + ); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + if ($autoincrement !== false) { + $definition[0]['autoincrement'] = $autoincrement; + } + if (!is_null($collate)) { + $definition[0]['collate'] = $collate; + $definition[0]['charset'] = $charset; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) { + $definition[$key]['default'] = '0000-00-00 00:00:00'; + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + return $definition; + } + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table column', __FUNCTION__); + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */"; + $index_name_mdb2 = $db->getIndexName($index_name); + $result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2))); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $index_name = $index_name_mdb2; + } + $result = $db->query(sprintf($query, $db->quote($index_name))); + if (PEAR::isError($result)) { + return $result; + } + $colpos = 1; + $definition = array(); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $key_name = $row['key_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + } else { + $key_name = strtoupper($key_name); + } + } + if ($index_name == $key_name) { + if (!$row['non_unique']) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name . ' is not an existing table index', __FUNCTION__); + } + $column_name = $row['column_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => $colpos++ + ); + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' + ? 'ascending' : 'descending'); + } + } + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name . ' is not an existing table index', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + $constraint_name_original = $constraint_name; + + $table = $db->quoteIdentifier($table, true); + $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */"; + if (strtolower($constraint_name) != 'primary') { + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + $result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2))); + if (!PEAR::isError($result) && !is_null($result)) { + // apply 'idxname_format' only if the query succeeded, otherwise + // fallback to the given $index_name, without transformation + $constraint_name = $constraint_name_mdb2; + } + } + $result = $db->query(sprintf($query, $db->quote($constraint_name))); + if (PEAR::isError($result)) { + return $result; + } + $colpos = 1; + //default values, eventually overridden + $definition = array( + 'primary' => false, + 'unique' => false, + 'foreign' => false, + 'check' => false, + 'fields' => array(), + 'references' => array( + 'table' => '', + 'fields' => array(), + ), + 'onupdate' => '', + 'ondelete' => '', + 'match' => '', + 'deferrable' => false, + 'initiallydeferred' => false, + ); + while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { + $row = array_change_key_case($row, CASE_LOWER); + $key_name = $row['key_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $key_name = strtolower($key_name); + } else { + $key_name = strtoupper($key_name); + } + } + if ($constraint_name == $key_name) { + if ($row['non_unique']) { + //FOREIGN KEY? + $query = 'SHOW CREATE TABLE '. $db->escape($table); + $constraint = $db->queryOne($query, 'text', 1); + if (!PEAR::isError($constraint) && !empty($constraint)) { + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $constraint = strtolower($constraint); + } else { + $constraint = strtoupper($constraint); + } + } + $pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i'; + if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) { + //fallback to original constraint name + $pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i'; + } + if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) { + $definition['foreign'] = true; + $column_names = explode(',', $matches[1]); + $referenced_cols = explode(',', $matches[3]); + $definition['references'] = array( + 'table' => $matches[2], + 'fields' => array(), + ); + $colpos = 1; + foreach ($column_names as $column_name) { + $definition['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + $colpos = 1; + foreach ($referenced_cols as $column_name) { + $definition['references']['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + $definition['onupdate'] = 'NO ACTION'; + $definition['ondelete'] = 'NO ACTION'; + $definition['match'] = 'SIMPLE'; + return $definition; + } + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + if ($row['key_name'] == 'PRIMARY') { + $definition['primary'] = true; + } elseif (!$row['non_unique']) { + $definition['unique'] = true; + } + $column_name = $row['column_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => $colpos++ + ); + if (!empty($row['collation'])) { + $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' + ? 'ascending' : 'descending'); + } + } + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT trigger_name, + event_object_table AS table_name, + action_statement AS trigger_body, + action_timing AS trigger_type, + event_manipulation AS trigger_event + FROM information_schema.triggers + WHERE trigger_name = '. $db->quote($trigger, 'text'); + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'text', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + ); + $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($def)) { + return $def; + } + $def['trigger_comment'] = ''; + $def['trigger_enabled'] = true; + return $def; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::setOption() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; + if (!is_object($resource)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Could not generate result resource', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $case_func = 'strtolower'; + } else { + $case_func = 'strtoupper'; + } + } else { + $case_func = 'strval'; + } + + $count = @mysqli_num_fields($resource); + $res = array(); + if ($mode) { + $res['num_fields'] = $count; + } + + $db->loadModule('Datatype', null, true); + for ($i = 0; $i < $count; $i++) { + $tmp = @mysqli_fetch_field($resource); + + $flags = ''; + foreach ($this->flags as $const => $means) { + if ($tmp->flags & $const) { + $flags.= $means . ' '; + } + } + if ($tmp->def) { + $flags.= 'default_' . rawurlencode($tmp->def); + } + $flags = trim($flags); + + $res[$i] = array( + 'table' => $case_func($tmp->table), + 'name' => $case_func($tmp->name), + 'type' => isset($this->types[$tmp->type]) + ? $this->types[$tmp->type] : 'unknown', + // http://bugs.php.net/?id=36579 + 'length' => $tmp->length, + 'flags' => $flags, + ); + $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); + if (PEAR::isError($mdb2type_info)) { + return $mdb2type_info; + } + $res[$i]['mdb2type'] = $mdb2type_info[0][0]; + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/oci8.php b/lib/Pear/MDB2/Driver/Reverse/oci8.php new file mode 100644 index 0000000..d5ea6cc --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/oci8.php @@ -0,0 +1,621 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: oci8.php,v 1.74 2007/11/25 13:38:29 quipo Exp $ +// + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 Oracle driver for the schema reverse engineering module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Reverse_oci8 extends MDB2_Driver_Reverse_Common +{ + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + list($owner, $table) = $this->splitTableSchema($table_name); + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT column_name name, + data_type "type", + nullable, + data_default "default", + COALESCE(data_precision, data_length) "length", + data_scale "scale" + FROM all_tab_columns + WHERE (table_name=? OR table_name=?) + AND (owner=? OR owner=?) + AND (column_name=? OR column_name=?) + ORDER BY column_id'; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $args = array( + $table, + strtoupper($table), + $owner, + strtoupper($owner), + $field_name, + strtoupper($field_name) + ); + $result = $stmt->execute($args); + if (PEAR::isError($result)) { + return $result; + } + $column = $result->fetchRow(MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($column)) { + return $column; + } + $stmt->free(); + $result->free(); + + if (empty($column)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $field_name . ' is not a column in table ' . $table_name, __FUNCTION__); + } + + $column = array_change_key_case($column, CASE_LOWER); + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = false; + if (!empty($column['nullable']) && $column['nullable'] == 'N') { + $notnull = true; + } + $default = false; + if (array_key_exists('default', $column)) { + $default = $column['default']; + if ($default === 'NULL') { + $default = null; + } + if (is_null($default) && $notnull) { + $default = ''; + } + } + + $definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + if ($type == 'integer') { + $query= "SELECT trigger_body + FROM all_triggers + WHERE table_name=? + AND triggering_event='INSERT' + AND trigger_type='BEFORE EACH ROW'"; + // ^^ pretty reasonable mimic for "auto_increment" in oracle? + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $result = $stmt->execute(strtoupper($table)); + if (PEAR::isError($result)) { + return $result; + } + while ($triggerstr = $result->fetchOne()) { + if (preg_match('/.*SELECT\W+(.+)\.nextval +into +\:NEW\.'.$field_name.' +FROM +dual/im', $triggerstr, $matches)) { + $definition[0]['autoincrement'] = $matches[1]; + } + } + $stmt->free(); + $result->free(); + } + return $definition; + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($owner, $table) = $this->splitTableSchema($table_name); + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = "SELECT aic.column_name, + aic.column_position, + aic.descend, + aic.table_owner, + alc.constraint_type + FROM all_ind_columns aic + LEFT JOIN all_constraints alc + ON aic.index_name = alc.constraint_name + AND aic.table_name = alc.table_name + AND aic.table_owner = alc.owner + WHERE (aic.table_name=? OR aic.table_name=?) + AND (aic.index_name=? OR aic.index_name=?) + AND (aic.table_owner=? OR aic.table_owner=?) + ORDER BY column_position"; + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + $indexnames = array_unique(array($db->getIndexName($index_name), $index_name)); + $i = 0; + $row = null; + while (is_null($row) && array_key_exists($i, $indexnames)) { + $args = array( + $table, + strtoupper($table), + $indexnames[$i], + strtoupper($indexnames[$i]), + $owner, + strtoupper($owner) + ); + $result = $stmt->execute($args); + if (PEAR::isError($result)) { + return $result; + } + $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($row)) { + return $row; + } + $i++; + } + if (is_null($row)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name. ' is not an index on table '. $table_name, __FUNCTION__); + } + if ($row['constraint_type'] == 'U' || $row['constraint_type'] == 'P') { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name. ' is a constraint, not an index on table '. $table_name, __FUNCTION__); + } + + $definition = array(); + while (!is_null($row)) { + $row = array_change_key_case($row, CASE_LOWER); + $column_name = $row['column_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => (int)$row['column_position'], + ); + if (!empty($row['descend'])) { + $definition['fields'][$column_name]['sorting'] = + ($row['descend'] == 'ASC' ? 'ascending' : 'descending'); + } + $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC); + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $index_name. ' is not an index on table '. $table_name, __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($owner, $table) = $this->splitTableSchema($table_name); + if (empty($owner)) { + $owner = $db->dsn['username']; + } + + $query = 'SELECT alc.constraint_name, + CASE alc.constraint_type WHEN \'P\' THEN 1 ELSE 0 END "primary", + CASE alc.constraint_type WHEN \'R\' THEN 1 ELSE 0 END "foreign", + CASE alc.constraint_type WHEN \'U\' THEN 1 ELSE 0 END "unique", + CASE alc.constraint_type WHEN \'C\' THEN 1 ELSE 0 END "check", + alc.DELETE_RULE "ondelete", + \'NO ACTION\' "onupdate", + \'SIMPLE\' "match", + CASE alc.deferrable WHEN \'NOT DEFERRABLE\' THEN 0 ELSE 1 END "deferrable", + CASE alc.deferred WHEN \'IMMEDIATE\' THEN 0 ELSE 1 END "initiallydeferred", + alc.search_condition, + alc.table_name, + cols.column_name, + cols.position, + r_alc.table_name "references_table", + r_cols.column_name "references_field", + r_cols.position "references_field_position" + FROM all_cons_columns cols + LEFT JOIN all_constraints alc + ON alc.constraint_name = cols.constraint_name + AND alc.owner = cols.owner + LEFT JOIN all_constraints r_alc + ON alc.r_constraint_name = r_alc.constraint_name + AND alc.r_owner = r_alc.owner + LEFT JOIN all_cons_columns r_cols + ON r_alc.constraint_name = r_cols.constraint_name + AND r_alc.owner = r_cols.owner + AND cols.position = r_cols.position + WHERE (alc.constraint_name=? OR alc.constraint_name=?) + AND alc.constraint_name = cols.constraint_name + AND (alc.owner=? OR alc.owner=?)'; + $tablenames = array(); + if (!empty($table)) { + $query.= ' AND (alc.table_name=? OR alc.table_name=?)'; + $tablenames = array($table, strtoupper($table)); + } + $stmt = $db->prepare($query); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $constraintnames = array_unique(array($db->getIndexName($constraint_name), $constraint_name)); + $c = 0; + $row = null; + while (is_null($row) && array_key_exists($c, $constraintnames)) { + $args = array( + $constraintnames[$c], + strtoupper($constraintnames[$c]), + $owner, + strtoupper($owner) + ); + if (!empty($table)) { + $args = array_merge($args, $tablenames); + } + $result = $stmt->execute($args); + if (PEAR::isError($result)) { + return $result; + } + $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($row)) { + return $row; + } + $c++; + } + + $definition = array( + 'primary' => (boolean)$row['primary'], + 'unique' => (boolean)$row['unique'], + 'foreign' => (boolean)$row['foreign'], + 'check' => (boolean)$row['check'], + 'deferrable' => (boolean)$row['deferrable'], + 'initiallydeferred' => (boolean)$row['initiallydeferred'], + 'ondelete' => $row['ondelete'], + 'onupdate' => $row['onupdate'], + 'match' => $row['match'], + ); + + if ($definition['check']) { + // pattern match constraint for check constraint values into enum-style output: + $enumregex = '/'.$row['column_name'].' in \((.+?)\)/i'; + if (preg_match($enumregex, $row['search_condition'], $rangestr)) { + $definition['fields'][$column_name] = array(); + $allowed = explode(',', $rangestr[1]); + foreach ($allowed as $val) { + $val = trim($val); + $val = preg_replace('/^\'/', '', $val); + $val = preg_replace('/\'$/', '', $val); + array_push($definition['fields'][$column_name], $val); + } + } + } + + while (!is_null($row)) { + $row = array_change_key_case($row, CASE_LOWER); + $column_name = $row['column_name']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column_name = strtolower($column_name); + } else { + $column_name = strtoupper($column_name); + } + } + $definition['fields'][$column_name] = array( + 'position' => (int)$row['position'] + ); + if ($row['foreign']) { + $ref_column_name = $row['references_field']; + $ref_table_name = $row['references_table']; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $ref_column_name = strtolower($ref_column_name); + $ref_table_name = strtolower($ref_table_name); + } else { + $ref_column_name = strtoupper($ref_column_name); + $ref_table_name = strtoupper($ref_table_name); + } + } + $definition['references']['table'] = $ref_table_name; + $definition['references']['fields'][$ref_column_name] = array( + 'position' => (int)$row['references_field_position'] + ); + } + $lastrow = $row; + $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC); + } + $result->free(); + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not a constraint on table '. $table_name, __FUNCTION__); + } + + return $definition; + } + + // }}} + // {{{ getSequenceDefinition() + + /** + * Get the structure of a sequence into an array + * + * @param string $sequence name of sequence that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getSequenceDefinition($sequence) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $sequence_name = $db->getSequenceName($sequence); + $query = 'SELECT last_number FROM user_sequences'; + $query.= ' WHERE sequence_name='.$db->quote($sequence_name, 'text'); + $query.= ' OR sequence_name='.$db->quote(strtoupper($sequence_name), 'text'); + $start = $db->queryOne($query, 'integer'); + if (PEAR::isError($start)) { + return $start; + } + $definition = array(); + if ($start != 1) { + $definition = array('start' => $start); + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = 'SELECT trigger_name, + table_name, + trigger_body, + trigger_type, + triggering_event trigger_event, + description trigger_comment, + 1 trigger_enabled, + when_clause + FROM user_triggers + WHERE trigger_name = \''. strtoupper($trigger).'\''; + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'text', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + 'trigger_comment' => 'text', + 'trigger_enabled' => 'boolean', + 'when_clause' => 'text', + ); + $result = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($result)) { + return $result; + } + if (!empty($result['trigger_type'])) { + //$result['trigger_type'] = array_shift(explode(' ', $result['trigger_type'])); + $result['trigger_type'] = preg_replace('/(\S+).*/', '\\1', $result['trigger_type']); + } + return $result; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * NOTE: flags won't contain index information. + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; + if (!is_resource($resource)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Could not generate result resource', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $case_func = 'strtolower'; + } else { + $case_func = 'strtoupper'; + } + } else { + $case_func = 'strval'; + } + + $count = @OCINumCols($resource); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + $db->loadModule('Datatype', null, true); + for ($i = 0; $i < $count; $i++) { + $column = array( + 'table' => '', + 'name' => $case_func(@OCIColumnName($resource, $i+1)), + 'type' => @OCIColumnType($resource, $i+1), + 'length' => @OCIColumnSize($resource, $i+1), + 'flags' => '', + ); + $res[$i] = $column; + $res[$i]['mdb2type'] = $db->datatype->mapNativeDatatype($res[$i]); + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + return $res; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/pgsql.php b/lib/Pear/MDB2/Driver/Reverse/pgsql.php new file mode 100644 index 0000000..7d5c9f1 --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/pgsql.php @@ -0,0 +1,530 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: pgsql.php,v 1.70 2008/03/13 20:38:09 quipo Exp $ + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 PostGreSQL driver for the schema reverse engineering module + * + * @package MDB2 + * @category Database + * @author Paul Cooper + * @author Lorenzo Alberton + */ +class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common +{ + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $query = "SELECT a.attname AS name, + t.typname AS type, + CASE a.attlen + WHEN -1 THEN + CASE t.typname + WHEN 'numeric' THEN (a.atttypmod / 65536) + WHEN 'decimal' THEN (a.atttypmod / 65536) + WHEN 'money' THEN (a.atttypmod / 65536) + ELSE CASE a.atttypmod + WHEN -1 THEN NULL + ELSE a.atttypmod - 4 + END + END + ELSE a.attlen + END AS length, + CASE t.typname + WHEN 'numeric' THEN (a.atttypmod % 65536) - 4 + WHEN 'decimal' THEN (a.atttypmod % 65536) - 4 + WHEN 'money' THEN (a.atttypmod % 65536) - 4 + ELSE 0 + END AS scale, + a.attnotnull, + a.atttypmod, + a.atthasdef, + (SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128) + FROM pg_attrdef d + WHERE d.adrelid = a.attrelid + AND d.adnum = a.attnum + AND a.atthasdef + ) as default + FROM pg_attribute a, + pg_class c, + pg_type t + WHERE c.relname = ".$db->quote($table, 'text')." + AND a.atttypid = t.oid + AND c.oid = a.attrelid + AND NOT a.attisdropped + AND a.attnum > 0 + AND a.attname = ".$db->quote($field_name, 'text')." + ORDER BY a.attnum"; + $column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($column)) { + return $column; + } + + if (empty($column)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table column', __FUNCTION__); + } + + $column = array_change_key_case($column, CASE_LOWER); + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = false; + if (!empty($column['attnotnull']) && $column['attnotnull'] == 't') { + $notnull = true; + } + $default = null; + if ($column['atthasdef'] === 't' + && !preg_match("/nextval\('([^']+)'/", $column['default']) + ) { + $pattern = '/(\'.*\')::[\w ]+$/i'; + $default = $column['default'];#substr($column['adsrc'], 1, -1); + if (is_null($default) && $notnull) { + $default = ''; + } elseif (!empty($default) && preg_match($pattern, $default)) { + //remove data type cast + $default = preg_replace ($pattern, '\\1', $default); + } + } + $autoincrement = false; + if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) { + $autoincrement = true; + } + $definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + if ($autoincrement !== false) { + $definition[0]['autoincrement'] = $autoincrement; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + return $definition; + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $query = 'SELECT relname, indkey FROM pg_index, pg_class'; + $query.= ' WHERE pg_class.oid = pg_index.indexrelid'; + $query.= " AND indisunique != 't' AND indisprimary != 't'"; + $query.= ' AND pg_class.relname = %s'; + $index_name_mdb2 = $db->getIndexName($index_name); + $row = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($row) || empty($row)) { + // fallback to the given $index_name, without transformation + $row = $db->queryRow(sprintf($query, $db->quote($index_name, 'text')), null, MDB2_FETCHMODE_ASSOC); + } + if (PEAR::isError($row)) { + return $row; + } + + if (empty($row)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table index', __FUNCTION__); + } + + $row = array_change_key_case($row, CASE_LOWER); + + $db->loadModule('Manager', null, true); + $columns = $db->manager->listTableFields($table_name); + + $definition = array(); + + $index_column_numbers = explode(' ', $row['indkey']); + + $colpos = 1; + foreach ($index_column_numbers as $number) { + $definition['fields'][$columns[($number - 1)]] = array( + 'position' => $colpos++, + 'sorting' => 'ascending', + ); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $query = "SELECT c.oid, + c.conname AS constraint_name, + CASE WHEN c.contype = 'c' THEN 1 ELSE 0 END AS \"check\", + CASE WHEN c.contype = 'f' THEN 1 ELSE 0 END AS \"foreign\", + CASE WHEN c.contype = 'p' THEN 1 ELSE 0 END AS \"primary\", + CASE WHEN c.contype = 'u' THEN 1 ELSE 0 END AS \"unique\", + CASE WHEN c.condeferrable = 'f' THEN 0 ELSE 1 END AS deferrable, + CASE WHEN c.condeferred = 'f' THEN 0 ELSE 1 END AS initiallydeferred, + --array_to_string(c.conkey, ' ') AS constraint_key, + t.relname AS table_name, + t2.relname AS references_table, + CASE confupdtype + WHEN 'a' THEN 'NO ACTION' + WHEN 'r' THEN 'RESTRICT' + WHEN 'c' THEN 'CASCADE' + WHEN 'n' THEN 'SET NULL' + WHEN 'd' THEN 'SET DEFAULT' + END AS onupdate, + CASE confdeltype + WHEN 'a' THEN 'NO ACTION' + WHEN 'r' THEN 'RESTRICT' + WHEN 'c' THEN 'CASCADE' + WHEN 'n' THEN 'SET NULL' + WHEN 'd' THEN 'SET DEFAULT' + END AS ondelete, + CASE confmatchtype + WHEN 'u' THEN 'UNSPECIFIED' + WHEN 'f' THEN 'FULL' + WHEN 'p' THEN 'PARTIAL' + END AS match, + --array_to_string(c.confkey, ' ') AS fk_constraint_key, + consrc + FROM pg_constraint c + LEFT JOIN pg_class t ON c.conrelid = t.oid + LEFT JOIN pg_class t2 ON c.confrelid = t2.oid + WHERE c.conname = %s + AND t.relname = " . $db->quote($table, 'text'); + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($row) || empty($row)) { + // fallback to the given $index_name, without transformation + $constraint_name_mdb2 = $constraint_name; + $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); + } + if (PEAR::isError($row)) { + return $row; + } + + if (empty($row)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + + $row = array_change_key_case($row, CASE_LOWER); + + $definition = array( + 'primary' => (boolean)$row['primary'], + 'unique' => (boolean)$row['unique'], + 'foreign' => (boolean)$row['foreign'], + 'check' => (boolean)$row['check'], + 'fields' => array(), + 'references' => array( + 'table' => $row['references_table'], + 'fields' => array(), + ), + 'deferrable' => (boolean)$row['deferrable'], + 'initiallydeferred' => (boolean)$row['initiallydeferred'], + 'onupdate' => $row['onupdate'], + 'ondelete' => $row['ondelete'], + 'match' => $row['match'], + ); + + $query = 'SELECT a.attname + FROM pg_constraint c + LEFT JOIN pg_class t ON c.conrelid = t.oid + LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey) + WHERE c.conname = %s + AND t.relname = ' . $db->quote($table, 'text'); + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + $fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null); + if (PEAR::isError($fields)) { + return $fields; + } + $colpos = 1; + foreach ($fields as $field) { + $definition['fields'][$field] = array( + 'position' => $colpos++, + 'sorting' => 'ascending', + ); + } + + if ($definition['foreign']) { + $query = 'SELECT a.attname + FROM pg_constraint c + LEFT JOIN pg_class t ON c.confrelid = t.oid + LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey) + WHERE c.conname = %s + AND t.relname = ' . $db->quote($definition['references']['table'], 'text'); + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + $foreign_fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null); + if (PEAR::isError($foreign_fields)) { + return $foreign_fields; + } + $colpos = 1; + foreach ($foreign_fields as $foreign_field) { + $definition['references']['fields'][$foreign_field] = array( + 'position' => $colpos++, + ); + } + } + + if ($definition['check']) { + $check_def = $db->queryOne("SELECT pg_get_constraintdef(" . $row['oid'] . ", 't')"); + // ... + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + * + * @TODO: add support for plsql functions and functions with args + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT trg.tgname AS trigger_name, + tbl.relname AS table_name, + CASE + WHEN p.proname IS NOT NULL THEN 'EXECUTE PROCEDURE ' || p.proname || '();' + ELSE '' + END AS trigger_body, + CASE trg.tgtype & cast(2 as int2) + WHEN 0 THEN 'AFTER' + ELSE 'BEFORE' + END AS trigger_type, + CASE trg.tgtype & cast(28 as int2) + WHEN 16 THEN 'UPDATE' + WHEN 8 THEN 'DELETE' + WHEN 4 THEN 'INSERT' + WHEN 20 THEN 'INSERT, UPDATE' + WHEN 28 THEN 'INSERT, UPDATE, DELETE' + WHEN 24 THEN 'UPDATE, DELETE' + WHEN 12 THEN 'INSERT, DELETE' + END AS trigger_event, + CASE trg.tgenabled + WHEN 'O' THEN 't' + ELSE trg.tgenabled + END AS trigger_enabled, + obj_description(trg.oid, 'pg_trigger') AS trigger_comment + FROM pg_trigger trg, + pg_class tbl, + pg_proc p + WHERE trg.tgrelid = tbl.oid + AND trg.tgfoid = p.oid + AND trg.tgname = ". $db->quote($trigger, 'text'); + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'text', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + 'trigger_comment' => 'text', + 'trigger_enabled' => 'boolean', + ); + return $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; + if (!is_resource($resource)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Could not generate result resource', __FUNCTION__); + } + + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $case_func = 'strtolower'; + } else { + $case_func = 'strtoupper'; + } + } else { + $case_func = 'strval'; + } + + $count = @pg_num_fields($resource); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + $db->loadModule('Datatype', null, true); + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => function_exists('pg_field_table') ? @pg_field_table($resource, $i) : '', + 'name' => $case_func(@pg_field_name($resource, $i)), + 'type' => @pg_field_type($resource, $i), + 'length' => @pg_field_size($resource, $i), + 'flags' => '', + ); + $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); + if (PEAR::isError($mdb2type_info)) { + return $mdb2type_info; + } + $res[$i]['mdb2type'] = $mdb2type_info[0][0]; + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/Reverse/sqlite.php b/lib/Pear/MDB2/Driver/Reverse/sqlite.php new file mode 100644 index 0000000..abd9cbc --- /dev/null +++ b/lib/Pear/MDB2/Driver/Reverse/sqlite.php @@ -0,0 +1,585 @@ + | +// | Lorenzo Alberton | +// +----------------------------------------------------------------------+ +// +// $Id: sqlite.php,v 1.79 2008/03/05 11:08:53 quipo Exp $ +// + +require_once 'MDB2/Driver/Reverse/Common.php'; + +/** + * MDB2 SQlite driver for the schema reverse engineering module + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common +{ + function _getTableColumns($sql) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $start_pos = strpos($sql, '('); + $end_pos = strrpos($sql, ')'); + $column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1); + // replace the decimal length-places-separator with a colon + $column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def); + $column_sql = split(',', $column_def); + $columns = array(); + $count = count($column_sql); + if ($count == 0) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unexpected empty table column definition list', __FUNCTION__); + } + $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( UNSIGNED)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?$/i'; + $regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i'; + for ($i=0, $j=0; $i<$count; ++$i) { + if (!preg_match($regexp, trim($column_sql[$i]), $matches)) { + if (!preg_match($regexp2, trim($column_sql[$i]))) { + continue; + } + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'unexpected table column SQL definition: "'.$column_sql[$i].'"', __FUNCTION__); + } + $columns[$j]['name'] = trim($matches[1], implode('', $db->identifier_quoting)); + $columns[$j]['type'] = strtolower($matches[2]); + if (isset($matches[4]) && strlen($matches[4])) { + $columns[$j]['length'] = $matches[4]; + } + if (isset($matches[6]) && strlen($matches[6])) { + $columns[$j]['decimal'] = $matches[6]; + } + if (isset($matches[7]) && strlen($matches[7])) { + $columns[$j]['unsigned'] = true; + } + if (isset($matches[8]) && strlen($matches[8])) { + $columns[$j]['autoincrement'] = true; + } + if (isset($matches[10]) && strlen($matches[10])) { + $default = $matches[10]; + if (strlen($default) && $default[0]=="'") { + $default = str_replace("''", "'", substr($default, 1, strlen($default)-2)); + } + if ($default === 'NULL') { + $default = null; + } + $columns[$j]['default'] = $default; + } + if (isset($matches[11]) && strlen($matches[11])) { + $columns[$j]['notnull'] = ($matches[11] === ' NOT NULL'); + } + ++$j; + } + return $columns; + } + + // {{{ getTableFieldDefinition() + + /** + * Get the stucture of a field into an array + * + * @param string $table_name name of table that should be used in method + * @param string $field_name name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure. + * The returned array contains an array for each field definition, + * with (some of) these indices: + * [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type] + * @access public + */ + function getTableFieldDefinition($table_name, $field_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $result = $db->loadModule('Datatype', null, true); + if (PEAR::isError($result)) { + return $result; + } + $query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text'); + } else { + $query.= 'name='.$db->quote($table, 'text'); + } + $sql = $db->queryOne($query); + if (PEAR::isError($sql)) { + return $sql; + } + $columns = $this->_getTableColumns($sql); + foreach ($columns as $column) { + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + if ($db->options['field_case'] == CASE_LOWER) { + $column['name'] = strtolower($column['name']); + } else { + $column['name'] = strtoupper($column['name']); + } + } else { + $column = array_change_key_case($column, $db->options['field_case']); + } + if ($field_name == $column['name']) { + $mapped_datatype = $db->datatype->mapNativeDatatype($column); + if (PEAR::isError($mapped_datatype)) { + return $mapped_datatype; + } + list($types, $length, $unsigned, $fixed) = $mapped_datatype; + $notnull = false; + if (!empty($column['notnull'])) { + $notnull = $column['notnull']; + } + $default = false; + if (array_key_exists('default', $column)) { + $default = $column['default']; + if (is_null($default) && $notnull) { + $default = ''; + } + } + $autoincrement = false; + if (!empty($column['autoincrement'])) { + $autoincrement = true; + } + + $definition[0] = array( + 'notnull' => $notnull, + 'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type']) + ); + if (!is_null($length)) { + $definition[0]['length'] = $length; + } + if (!is_null($unsigned)) { + $definition[0]['unsigned'] = $unsigned; + } + if (!is_null($fixed)) { + $definition[0]['fixed'] = $fixed; + } + if ($default !== false) { + $definition[0]['default'] = $default; + } + if ($autoincrement !== false) { + $definition[0]['autoincrement'] = $autoincrement; + } + foreach ($types as $key => $type) { + $definition[$key] = $definition[0]; + if ($type == 'clob' || $type == 'blob') { + unset($definition[$key]['default']); + } + $definition[$key]['type'] = $type; + $definition[$key]['mdb2type'] = $type; + } + return $definition; + } + } + + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table column', __FUNCTION__); + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the stucture of an index into an array + * + * @param string $table_name name of table that should be used in method + * @param string $index_name name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableIndexDefinition($table_name, $index_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text'); + } else { + $query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text'); + } + $query.= ' AND sql NOT NULL ORDER BY name'; + $index_name_mdb2 = $db->getIndexName($index_name); + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $qry = sprintf($query, $db->quote(strtolower($index_name_mdb2), 'text')); + } else { + $qry = sprintf($query, $db->quote($index_name_mdb2, 'text')); + } + $sql = $db->queryOne($qry, 'text'); + if (PEAR::isError($sql) || empty($sql)) { + // fallback to the given $index_name, without transformation + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $qry = sprintf($query, $db->quote(strtolower($index_name), 'text')); + } else { + $qry = sprintf($query, $db->quote($index_name, 'text')); + } + $sql = $db->queryOne($qry, 'text'); + } + if (PEAR::isError($sql)) { + return $sql; + } + if (!$sql) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table index', __FUNCTION__); + } + + $sql = strtolower($sql); + $start_pos = strpos($sql, '('); + $end_pos = strrpos($sql, ')'); + $column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1); + $column_names = split(',', $column_names); + + if (preg_match("/^create unique/", $sql)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table index', __FUNCTION__); + } + + $definition = array(); + $count = count($column_names); + for ($i=0; $i<$count; ++$i) { + $column_name = strtok($column_names[$i], ' '); + $collation = strtok(' '); + $definition['fields'][$column_name] = array( + 'position' => $i+1 + ); + if (!empty($collation)) { + $definition['fields'][$column_name]['sorting'] = + ($collation=='ASC' ? 'ascending' : 'descending'); + } + } + + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing table index', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the stucture of a constraint into an array + * + * @param string $table_name name of table that should be used in method + * @param string $constraint_name name of constraint that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTableConstraintDefinition($table_name, $constraint_name) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + list($schema, $table) = $this->splitTableSchema($table_name); + + $query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text'); + } else { + $query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text'); + } + $query.= ' AND sql NOT NULL ORDER BY name'; + $constraint_name_mdb2 = $db->getIndexName($constraint_name); + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text')); + } else { + $qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text')); + } + $sql = $db->queryOne($qry, 'text'); + if (PEAR::isError($sql) || empty($sql)) { + // fallback to the given $index_name, without transformation + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text')); + } else { + $qry = sprintf($query, $db->quote($constraint_name, 'text')); + } + $sql = $db->queryOne($qry, 'text'); + } + if (PEAR::isError($sql)) { + return $sql; + } + //default values, eventually overridden + $definition = array( + 'primary' => false, + 'unique' => false, + 'foreign' => false, + 'check' => false, + 'fields' => array(), + 'references' => array( + 'table' => '', + 'fields' => array(), + ), + 'onupdate' => '', + 'ondelete' => '', + 'match' => '', + 'deferrable' => false, + 'initiallydeferred' => false, + ); + if (!$sql) { + $query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text'); + } else { + $query.= 'name='.$db->quote($table, 'text'); + } + $query.= " AND sql NOT NULL ORDER BY name"; + $sql = $db->queryOne($query, 'text'); + if (PEAR::isError($sql)) { + return $sql; + } + if ($constraint_name == 'primary') { + // search in table definition for PRIMARY KEYs + if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) { + $definition['primary'] = true; + $definition['fields'] = array(); + $column_names = split(',', $tmp[1]); + $colpos = 1; + foreach ($column_names as $column_name) { + $definition['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + return $definition; + } + if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) { + $definition['primary'] = true; + $definition['fields'] = array(); + $column_names = split(',', $tmp[1]); + $colpos = 1; + foreach ($column_names as $column_name) { + $definition['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + return $definition; + } + } else { + // search in table definition for FOREIGN KEYs + $pattern = "/\bCONSTRAINT\b\s+%s\s+ + \bFOREIGN\s+KEY\b\s*\(([^\)]+)\)\s* + \bREFERENCES\b\s+([^\s]+)\s*\(([^\)]+)\)\s* + (?:\bMATCH\s*([^\s]+))?\s* + (?:\bON\s+UPDATE\s+([^\s,\)]+))?\s* + (?:\bON\s+DELETE\s+([^\s,\)]+))?\s* + /imsx"; + $found_fk = false; + if (preg_match(sprintf($pattern, $constraint_name_mdb2), $sql, $tmp)) { + $found_fk = true; + } elseif (preg_match(sprintf($pattern, $constraint_name), $sql, $tmp)) { + $found_fk = true; + } + if ($found_fk) { + $definition['foreign'] = true; + $definition['match'] = 'SIMPLE'; + $definition['onupdate'] = 'NO ACTION'; + $definition['ondelete'] = 'NO ACTION'; + $definition['references']['table'] = $tmp[2]; + $column_names = split(',', $tmp[1]); + $colpos = 1; + foreach ($column_names as $column_name) { + $definition['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + $referenced_cols = split(',', $tmp[3]); + $colpos = 1; + foreach ($referenced_cols as $column_name) { + $definition['references']['fields'][trim($column_name)] = array( + 'position' => $colpos++ + ); + } + if (isset($tmp[4])) { + $definition['match'] = $tmp[4]; + } + if (isset($tmp[5])) { + $definition['onupdate'] = $tmp[5]; + } + if (isset($tmp[6])) { + $definition['ondelete'] = $tmp[6]; + } + return $definition; + } + } + $sql = false; + } + if (!$sql) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + + $sql = strtolower($sql); + $start_pos = strpos($sql, '('); + $end_pos = strrpos($sql, ')'); + $column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1); + $column_names = split(',', $column_names); + + if (!preg_match("/^create unique/", $sql)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + + $definition['unique'] = true; + $count = count($column_names); + for ($i=0; $i<$count; ++$i) { + $column_name = strtok($column_names[$i]," "); + $collation = strtok(" "); + $definition['fields'][$column_name] = array( + 'position' => $i+1 + ); + if (!empty($collation)) { + $definition['fields'][$column_name]['sorting'] = + ($collation=='ASC' ? 'ascending' : 'descending'); + } + } + + if (empty($definition['fields'])) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + $constraint_name . ' is not an existing table constraint', __FUNCTION__); + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $query = "SELECT name as trigger_name, + tbl_name AS table_name, + sql AS trigger_body, + NULL AS trigger_type, + NULL AS trigger_event, + NULL AS trigger_comment, + 1 AS trigger_enabled + FROM sqlite_master + WHERE type='trigger'"; + if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text'); + } else { + $query.= ' AND name='.$db->quote($trigger, 'text'); + } + $types = array( + 'trigger_name' => 'text', + 'table_name' => 'text', + 'trigger_body' => 'text', + 'trigger_type' => 'text', + 'trigger_event' => 'text', + 'trigger_comment' => 'text', + 'trigger_enabled' => 'boolean', + ); + $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); + if (PEAR::isError($def)) { + return $def; + } + if (empty($def)) { + return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'it was not specified an existing trigger', __FUNCTION__); + } + if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) { + $def['trigger_type'] = strtoupper($tmp[1]); + $def['trigger_event'] = strtoupper($tmp[2]); + } + return $def; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table + * + * @param string $result a string containing the name of a table + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::tableInfo() + * @since Method available since Release 1.7.0 + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + return parent::tableInfo($result, $mode); + } + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null, + 'This DBMS can not obtain tableInfo from result sets', __FUNCTION__); + } +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/ibase.php b/lib/Pear/MDB2/Driver/ibase.php new file mode 100644 index 0000000..26e9319 --- /dev/null +++ b/lib/Pear/MDB2/Driver/ibase.php @@ -0,0 +1,1522 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: ibase.php,v 1.219 2008/03/08 14:18:38 quipo Exp $ + +/** + * MDB2 FireBird/InterBase driver + * + * @package MDB2 + * @category Database + * @author Lorenzo Alberton + */ +class MDB2_Driver_ibase extends MDB2_Driver_Common +{ + // {{{ properties + + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => '\\'); + + var $identifier_quoting = array('start' => '', 'end' => '', 'escape' => false); + + var $transaction_id = 0; + + var $query_parameters = array(); + + var $query_parameter_values = array(); + + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'ibase'; + $this->dbsyntax = 'ibase'; + + $this->supported['sequences'] = true; + $this->supported['indexes'] = true; + $this->supported['affected_rows'] = function_exists('ibase_affected_rows'); + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['transactions'] = true; + $this->supported['savepoints'] = true; + $this->supported['current_id'] = true; + $this->supported['limit_queries'] = 'emulated'; + $this->supported['LOBs'] = true; + $this->supported['replace'] = false; + $this->supported['sub_selects'] = true; + $this->supported['triggers'] = true; + $this->supported['auto_increment'] = true; + $this->supported['primary_key'] = true; + $this->supported['result_introspection'] = true; + $this->supported['prepared_statements'] = true; + $this->supported['identifier_quoting'] = false; + $this->supported['pattern_escaping'] = true; + $this->supported['new_link'] = false; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['database_path'] = ''; + $this->options['database_extension'] = '.gdb'; + $this->options['server_version'] = ''; + $this->options['max_identifiers_length'] = 31; + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null) + { + $native_msg = @ibase_errmsg(); + + if (function_exists('ibase_errcode')) { + $native_code = @ibase_errcode(); + } else { + // memo for the interbase php module hackers: we need something similar + // to mysql_errno() to retrieve error codes instead of this ugly hack + if (preg_match('/^([^0-9\-]+)([0-9\-]+)\s+(.*)$/', $native_msg, $m)) { + $native_code = (int)$m[2]; + } else { + $native_code = null; + } + } + if (is_null($error)) { + $error = MDB2_ERROR; + if ($native_code) { + // try to interpret Interbase error code (that's why we need ibase_errno() + // in the interbase module to return the real error code) + switch ($native_code) { + case -204: + if (isset($m[3]) && is_int(strpos($m[3], 'Table unknown'))) { + $errno = MDB2_ERROR_NOSUCHTABLE; + } + break; + default: + static $ecode_map; + if (empty($ecode_map)) { + $ecode_map = array( + -104 => MDB2_ERROR_SYNTAX, + -150 => MDB2_ERROR_ACCESS_VIOLATION, + -151 => MDB2_ERROR_ACCESS_VIOLATION, + -155 => MDB2_ERROR_NOSUCHTABLE, + -157 => MDB2_ERROR_NOSUCHFIELD, + -158 => MDB2_ERROR_VALUE_COUNT_ON_ROW, + -170 => MDB2_ERROR_MISMATCH, + -171 => MDB2_ERROR_MISMATCH, + -172 => MDB2_ERROR_INVALID, + // -204 => // Covers too many errors, need to use regex on msg + -205 => MDB2_ERROR_NOSUCHFIELD, + -206 => MDB2_ERROR_NOSUCHFIELD, + -208 => MDB2_ERROR_INVALID, + -219 => MDB2_ERROR_NOSUCHTABLE, + -297 => MDB2_ERROR_CONSTRAINT, + -303 => MDB2_ERROR_INVALID, + -413 => MDB2_ERROR_INVALID_NUMBER, + -530 => MDB2_ERROR_CONSTRAINT, + -551 => MDB2_ERROR_ACCESS_VIOLATION, + -552 => MDB2_ERROR_ACCESS_VIOLATION, + // -607 => // Covers too many errors, need to use regex on msg + -625 => MDB2_ERROR_CONSTRAINT_NOT_NULL, + -803 => MDB2_ERROR_CONSTRAINT, + -804 => MDB2_ERROR_VALUE_COUNT_ON_ROW, + // -902 => // Covers too many errors, need to use regex on msg + -904 => MDB2_ERROR_CONNECT_FAILED, + -922 => MDB2_ERROR_NOSUCHDB, + -923 => MDB2_ERROR_CONNECT_FAILED, + -924 => MDB2_ERROR_CONNECT_FAILED + ); + } + if (isset($ecode_map[$native_code])) { + $error = $ecode_map[$native_code]; + } + break; + } + } else { + static $error_regexps; + if (!isset($error_regexps)) { + $error_regexps = array( + '/generator .* is not defined/' + => MDB2_ERROR_SYNTAX, // for compat. w ibase_errcode() + '/table.*(not exist|not found|unknown)/i' + => MDB2_ERROR_NOSUCHTABLE, + '/table .* already exists/i' + => MDB2_ERROR_ALREADY_EXISTS, + '/unsuccessful metadata update .* failed attempt to store duplicate value/i' + => MDB2_ERROR_ALREADY_EXISTS, + '/unsuccessful metadata update .* not found/i' + => MDB2_ERROR_NOT_FOUND, + '/validation error for column .* value "\*\*\* null/i' + => MDB2_ERROR_CONSTRAINT_NOT_NULL, + '/violation of [\w ]+ constraint/i' + => MDB2_ERROR_CONSTRAINT, + '/conversion error from string/i' + => MDB2_ERROR_INVALID_NUMBER, + '/no permission for/i' + => MDB2_ERROR_ACCESS_VIOLATION, + '/arithmetic exception, numeric overflow, or string truncation/i' + => MDB2_ERROR_INVALID, + '/feature is not supported/i' + => MDB2_ERROR_NOT_CAPABLE, + ); + } + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $native_msg, $m)) { + $error = $code; + break; + } + } + } + } + return array($error, $native_code, $native_msg); + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Delimited identifiers are a nightmare with InterBase, so they're disabled + * + * @param string $str identifier name to be quoted + * @param bool $check_option check the 'quote_identifier' option + * + * @return string quoted identifier string + * + * @access public + */ + function quoteIdentifier($str, $check_option = false) + { + if ($check_option && !$this->options['quote_identifier']) { + return $str; + } + return strtoupper($str); + } + + // }}} + // {{{ getConnection() + + /** + * Returns a native connection + * + * @return mixed a valid MDB2 connection object, + * or a MDB2 error object on error + * @access public + */ + function getConnection() + { + $result = $this->connect(); + if (PEAR::isError($result)) { + return $result; + } + if ($this->in_transaction) { + return $this->transaction_id; + } + return $this->connection; + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!is_null($savepoint)) { + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'savepoint cannot be released when changes are auto committed', __FUNCTION__); + } + $query = 'SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $result = @ibase_trans(IBASE_DEFAULT, $connection); + if (!$result) { + return $this->raiseError(null, null, null, + 'could not start a transaction', __FUNCTION__); + } + $this->transaction_id = $result; + $this->in_transaction = true; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + $query = 'RELEASE SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + if (!@ibase_commit($this->transaction_id)) { + return $this->raiseError(null, null, null, + 'could not commit a transaction', __FUNCTION__); + } + $this->in_transaction = false; + $this->transaction_id = 0; + return MDB2_OK; + } + + // }}} + // {{{ rollback() + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + $query = 'ROLLBACK TO SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + if ($this->transaction_id && !@ibase_rollback($this->transaction_id)) { + return $this->raiseError(null, null, null, + 'Could not rollback a pending transaction: '.@ibase_errmsg(), __FUNCTION__); + } + $this->in_transaction = false; + $this->transaction_id = 0; + return MDB2_OK; + } + + // }}} + // {{{ setTransactionIsolation() + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level (SQL-92) + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @param array some transaction options: + * 'wait' => 'WAIT' | 'NO WAIT' + * 'rw' => 'READ WRITE' | 'READ ONLY' + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation, $options = array()) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + switch ($isolation) { + case 'READ UNCOMMITTED': + $ibase_isolation = 'READ COMMITTED RECORD_VERSION'; + break; + case 'READ COMMITTED': + $ibase_isolation = 'READ COMMITTED NO RECORD_VERSION'; + break; + case 'REPEATABLE READ': + $ibase_isolation = 'SNAPSHOT'; + break; + case 'SERIALIZABLE': + $ibase_isolation = 'SNAPSHOT TABLE STABILITY'; + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level is not supported: '.$isolation, __FUNCTION__); + } + + if (!empty($options['wait'])) { + switch ($options['wait']) { + case 'WAIT': + case 'NO WAIT': + $wait = $options['wait']; + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'wait option is not supported: '.$options['wait'], __FUNCTION__); + } + } + + if (!empty($options['rw'])) { + switch ($options['rw']) { + case 'READ ONLY': + case 'READ WRITE': + $rw = $options['wait']; + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'wait option is not supported: '.$options['rw'], __FUNCTION__); + } + } + + $query = "SET TRANSACTION $rw $wait ISOLATION LEVEL $ibase_isolation"; + return $this->_doQuery($query, true); + } + + // }}} + // {{{ getDatabaseFile($database_name) + + /** + * Builds the string with path+dbname+extension + * + * @return string full database path+file + * @access protected + */ + function _getDatabaseFile($database_name) + { + if ($database_name == '') { + return $database_name; + } + $ret = $this->options['database_path'] . $database_name; + if (!preg_match('/\.[fg]db$/i', $database_name)) { + $ret .= $this->options['database_extension']; + } + return $ret; + } + + // }}} + // {{{ _doConnect() + + /** + * Does the grunt work of connecting to the database + * + * @return mixed connection resource on success, MDB2 Error Object on failure + * @access protected + */ + function _doConnect($username, $password, $database_name, $persistent = false) + { + if (!PEAR::loadExtension('interbase')) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + $database_file = $this->_getDatabaseFile($database_name); + $dbhost = $this->dsn['hostspec'] ? + ($this->dsn['hostspec'].':'.$database_file) : $database_file; + + $params = array(); + $params[] = $dbhost; + $params[] = !empty($username) ? $username : null; + $params[] = !empty($password) ? $password : null; + $params[] = isset($this->dsn['charset']) ? $this->dsn['charset'] : null; + $params[] = isset($this->dsn['buffers']) ? $this->dsn['buffers'] : null; + $params[] = isset($this->dsn['dialect']) ? $this->dsn['dialect'] : null; + $params[] = isset($this->dsn['role']) ? $this->dsn['role'] : null; + + $connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect'; + $connection = @call_user_func_array($connect_function, $params); + if ($connection <= 0) { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__); + } + + if (empty($this->dsn['disable_iso_date'])) { + if (function_exists('ibase_timefmt')) { + @ibase_timefmt("%Y-%m-%d %H:%M:%S", IBASE_TIMESTAMP); + @ibase_timefmt("%Y-%m-%d", IBASE_DATE); + } else { + @ini_set("ibase.timestampformat", "%Y-%m-%d %H:%M:%S"); + //@ini_set("ibase.timeformat", "%H:%M:%S"); + @ini_set("ibase.dateformat", "%Y-%m-%d"); + } + } + + return $connection; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return true on success, MDB2 Error Object on failure + * @access public + */ + function connect() + { + $database_file = $this->_getDatabaseFile($this->database_name); + if (is_resource($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 + if (MDB2::areEquals($this->connected_dsn, $this->dsn) + && $this->connected_database_name == $database_file + && $this->opened_persistent == $this->options['persistent'] + ) { + return MDB2_OK; + } + $this->disconnect(false); + } + + if (!empty($this->database_name)) { + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->database_name, + $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + $this->connection =& $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = $database_file; + $this->opened_persistent = $this->options['persistent']; + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + $this->supported['limit_queries'] = ($this->dbsyntax == 'firebird') ? true : 'emulated'; + } + return MDB2_OK; + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $database_file = $this->_getDatabaseFile($name); + $result = file_exists($database_file); + return $result; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_resource($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if (!$this->opened_persistent || $force) { + @ibase_close($this->connection); + } + } + return parent::disconnect($force); + } + + // }}} + // {{{ standaloneQuery() + + /** + * execute a query as DBA + * + * @param string $query the SQL query + * @param mixed $types array that contains the types of the columns in + * the result set + * @param boolean $is_manip if the query is a manipulation query + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; + $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; + $connection = $this->_doConnect($user, $pass, $this->database_name, $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $result =& $this->_doQuery($query, $is_manip, $connection); + if (!PEAR::isError($result)) { + $result = $this->_affectedRows($connection, $result); + } + + @mysql_close($connection); + return $result; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->getOption('disable_query')) { + if ($is_manip) { + return 0; + } + return null; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + $result = @ibase_query($connection, $query); + + if ($result === false) { + $err =& $this->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return (function_exists('ibase_affected_rows') ? @ibase_affected_rows($connection) : 0); + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if ($limit > 0 && $this->supports('limit_queries') === true) { + $query = preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i', + "SELECT FIRST $limit SKIP $offset", $query); + } + return $query; + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + $server_info = false; + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } elseif ($this->options['server_version']) { + $server_info = $this->options['server_version']; + } else { + $username = $this->options['DBA_username'] ? $this->options['DBA_username'] : $this->dsn['username']; + $password = $this->options['DBA_password'] ? $this->options['DBA_password'] : $this->dsn['password']; + $ibserv = @ibase_service_attach($this->dsn['hostspec'], $username, $password); + $server_info = @ibase_server_info($ibserv, IBASE_SVC_SERVER_VERSION); + @ibase_service_detach($ibserv); + } + if (!$server_info) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'Requires either "server_version" or "DBA_username"/"DBA_password" option', __FUNCTION__); + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native) { + //WI-V1.5.3.4854 Firebird 1.5 + //WI-T2.1.0.16780 Firebird 2.1 Beta 2 + if (!preg_match('/-[VT]([\d\.]*)/', $server_info, $matches)) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'Could not parse version information:'.$server_info, __FUNCTION__); + } + $tmp = explode('.', $matches[1], 4); + $server_info = array( + 'major' => isset($tmp[0]) ? $tmp[0] : null, + 'minor' => isset($tmp[1]) ? $tmp[1] : null, + 'patch' => isset($tmp[2]) ? $tmp[2] : null, + 'extra' => isset($tmp[3]) ? $tmp[3] : null, + 'native' => $server_info, + ); + } + return $server_info; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * With some database backends, this is emulated. + * prepare() requires a generic query as string like + * 'INSERT INTO numbers VALUES(?,?)' or + * 'INSERT INTO numbers VALUES(:foo,:bar)'. + * The ? and :name and are placeholders which can be set using + * bindParam() and the query can be sent off using the execute() method. + * The allowed format for :name can be set with the 'bindname_format' option. + * + * @param string $query the query to prepare + * @param mixed $types array that contains the types of the placeholders + * @param mixed $result_types array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders + * @return mixed resource handle for the prepared query on success, a MDB2 + * error on failure + * @access public + * @see bindParam, execute + */ + function &prepare($query, $types = null, $result_types = null, $lobs = array()) + { + if ($this->options['emulate_prepared']) { + $obj =& parent::prepare($query, $types, $result_types, $lobs); + return $obj; + } + $is_manip = ($result_types === MDB2_PREPARE_MANIP); + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $placeholder_type_guess = $placeholder_type = null; + $question = '?'; + $colon = ':'; + $positions = array(); + $position = 0; + while ($position < strlen($query)) { + $q_position = strpos($query, $question, $position); + $c_position = strpos($query, $colon, $position); + if ($q_position && $c_position) { + $p_position = min($q_position, $c_position); + } elseif ($q_position) { + $p_position = $q_position; + } elseif ($c_position) { + $p_position = $c_position; + } else { + break; + } + if (is_null($placeholder_type)) { + $placeholder_type_guess = $query[$p_position]; + } + + $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position); + if (PEAR::isError($new_pos)) { + return $new_pos; + } + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + if ($query[$position] == $placeholder_type_guess) { + if (is_null($placeholder_type)) { + $placeholder_type = $query[$p_position]; + $question = $colon = $placeholder_type; + } + if ($placeholder_type == ':') { + $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; + $parameter = preg_replace($regexp, '\\1', $query); + if ($parameter === '') { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'named parameter name must match "bindname_format" option', __FUNCTION__); + return $err; + } + $positions[] = $parameter; + $query = substr_replace($query, '?', $position, strlen($parameter)+1); + } else { + $positions[] = count($positions); + } + $position = $p_position + 1; + } else { + $position = $p_position; + } + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $statement = @ibase_prepare($connection, $query); + if (!$statement) { + $err =& $this->raiseError(null, null, null, + 'Could not create statement', __FUNCTION__); + return $err; + } + + $class_name = 'MDB2_Statement_'.$this->phptype; + $obj = new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)); + return $obj; + } + + // }}} + // {{{ getSequenceName() + + /** + * adds sequence name formatting to a sequence name + * + * @param string $sqn name of the sequence + * @return string formatted sequence name + * @access public + */ + function getSequenceName($sqn) + { + return strtoupper(parent::getSequenceName($sqn)); + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->getSequenceName($seq_name); + $query = 'SELECT GEN_ID('.$sequence_name.', 1) as the_value FROM RDB$DATABASE'; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError('*'); + $result = $this->queryOne($query, 'integer'); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $this->raiseError($result, null, null, + 'on demand sequence could not be created', __FUNCTION__); + } else { + return $this->nextID($seq_name, false); + } + } + } + return $result; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + $seq = $table.(empty($field) ? '' : '_'.$field); + return $this->currID($seq); + } + + // }}} + // {{{ currID() + + /** + * Returns the current id of a sequence + * + * @param string $seq_name name of the sequence + * @return mixed MDB2 Error Object or id + * @access public + */ + function currID($seq_name) + { + $sequence_name = $this->getSequenceName($seq_name); + $query = 'SELECT GEN_ID('.$sequence_name.', 0) as the_value FROM RDB$DATABASE'; + $value = $this->queryOne($query); + if (PEAR::isError($value)) { + return $this->raiseError($value, null, null, + 'Unable to select from ' . $seq_name, __FUNCTION__); + } + if (!is_numeric($value)) { + return $this->raiseError(MDB2_ERROR, null, null, + 'could not find value in sequence table', __FUNCTION__); + } + return $value; + } + + // }}} +} + +/** + * MDB2 FireBird/InterBase result driver + * + * @package MDB2 + * @category Database + * @author Lorenzo Alberton + */ +class MDB2_Result_ibase extends MDB2_Result_Common +{ + // {{{ _skipLimitOffset() + + /** + * Skip the first row of a result set. + * + * @param resource $result + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function _skipLimitOffset() + { + if ($this->db->supports('limit_queries') === true) { + return true; + } + if ($this->limit) { + if ($this->rownum > $this->limit) { + return false; + } + } + if ($this->offset) { + while ($this->offset_count < $this->offset) { + ++$this->offset_count; + if (!is_array(@ibase_fetch_row($this->result))) { + $this->offset_count = $this->offset; + return false; + } + } + } + return true; + } + + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if ($this->result === true) { + //query successfully executed, but without results... + $null = null; + return $null; + } + if (!$this->_skipLimitOffset()) { + $null = null; + return $null; + } + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $row = @ibase_fetch_assoc($this->result); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + $row = @ibase_fetch_row($this->result); + } + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_info = @ibase_field_info($this->result, $column); + $columns[$column_info['alias']] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + * @access public + */ + function numCols() + { + if ($this->result === true) { + //query successfully executed, but without results... + return 0; + } + + if (!is_resource($this->result)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'numCols(): not a valid ibase resource', __FUNCTION__); + } + $cols = @ibase_num_fields($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + return $cols; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with $result. + * + * @return boolean true on success, false if $result is invalid + * @access public + */ + function free() + { + if (is_resource($this->result) && $this->db->connection) { + $free = @ibase_free_result($this->result); + if ($free === false) { + return $this->db->raiseError(null, null, null, + 'Could not free result', __FUNCTION__); + } + } + $this->result = false; + return MDB2_OK; + } + + // }}} +} + +/** + * MDB2 FireBird/InterBase buffered result driver + * + * @package MDB2 + * @category Database + * @author Lorenzo Alberton + */ +class MDB2_BufferedResult_ibase extends MDB2_Result_ibase +{ + // {{{ class vars + + var $buffer; + var $buffer_rownum = - 1; + + // }}} + // {{{ _fillBuffer() + + /** + * Fill the row buffer + * + * @param int $rownum row number upto which the buffer should be filled + * if the row number is null all rows are ready into the buffer + * @return boolean true on success, false on failure + * @access protected + */ + function _fillBuffer($rownum = null) + { + if (isset($this->buffer) && is_array($this->buffer)) { + if (is_null($rownum)) { + if (!end($this->buffer)) { + return false; + } + } elseif (isset($this->buffer[$rownum])) { + return (bool) $this->buffer[$rownum]; + } + } + + if (!$this->_skipLimitOffset()) { + return false; + } + + $buffer = true; + while ((is_null($rownum) || $this->buffer_rownum < $rownum) + && (!$this->limit || $this->buffer_rownum < $this->limit) + && ($buffer = @ibase_fetch_row($this->result)) + ) { + ++$this->buffer_rownum; + $this->buffer[$this->buffer_rownum] = $buffer; + } + + if (!$buffer) { + ++$this->buffer_rownum; + $this->buffer[$this->buffer_rownum] = false; + return false; + } elseif ($this->limit && $this->buffer_rownum >= $this->limit) { + ++$this->buffer_rownum; + $this->buffer[$this->buffer_rownum] = false; + } + return true; + } + + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if ($this->result === true || is_null($this->result)) { + //query successfully executed, but without results... + $null = null; + return $null; + } + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + $target_rownum = $this->rownum + 1; + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if (!$this->_fillBuffer($target_rownum)) { + $null = null; + return $null; + } + $row = $this->buffer[$target_rownum]; + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $column_names = $this->getColumnNames(); + foreach ($column_names as $name => $i) { + $column_names[$name] = $row[$i]; + } + $row = $column_names; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return true; + } + if ($this->_fillBuffer($this->rownum + 1)) { + return true; + } + return false; + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + $this->_fillBuffer(); + return $this->buffer_rownum; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with $result. + * + * @return boolean true on success, false if $result is invalid + * @access public + */ + function free() + { + $this->buffer = null; + $this->buffer_rownum = null; + return parent::free(); + } + + // }}} +} + +/** + * MDB2 FireBird/InterBase statement driver + * + * @package MDB2 + * @category Database + * @author Lorenzo Alberton + */ +class MDB2_Statement_ibase extends MDB2_Statement_Common +{ + // {{{ _execute() + + /** + * Execute a prepared query statement helper method. + * + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function &_execute($result_class = true, $result_wrap_class = false) + { + if (is_null($this->statement)) { + $result =& parent::_execute($result_class, $result_wrap_class); + return $result; + } + $this->db->last_query = $this->query; + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values)); + if ($this->db->getOption('disable_query')) { + $result = $this->is_manip ? 0 : null; + return $result; + } + + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $parameters = array(0 => $this->statement); + foreach ($this->positions as $parameter) { + if (!array_key_exists($parameter, $this->values)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $value = $this->values[$parameter]; + $type = !empty($this->types[$parameter]) ? $this->types[$parameter] : null; + $quoted = $this->db->quote($value, $type, false); + if (PEAR::isError($quoted)) { + return $quoted; + } + $parameters[] = $quoted; + } + + $result = @call_user_func_array('ibase_execute', $parameters); + if ($result === false) { + $err =& $this->db->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + if ($this->is_manip) { + $affected_rows = $this->db->_affectedRows($connection); + return $affected_rows; + } + + $result =& $this->db->_wrapResult($result, $this->result_types, + $result_class, $result_wrap_class, $this->limit, $this->offset); + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + + // }}} + // {{{ free() + + /** + * Release resources allocated for the specified prepared query. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function free() + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + $result = MDB2_OK; + + if (!is_null($this->statement) && !@ibase_free_query($this->statement)) { + $result = $this->db->raiseError(null, null, null, + 'Could not free statement', __FUNCTION__); + } + + parent::free(); + return $result; + } +} +?> diff --git a/lib/Pear/MDB2/Driver/mssql.php b/lib/Pear/MDB2/Driver/mssql.php new file mode 100644 index 0000000..a16e33c --- /dev/null +++ b/lib/Pear/MDB2/Driver/mssql.php @@ -0,0 +1,1122 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mssql.php,v 1.174 2008/03/08 14:18:39 quipo Exp $ +// +// {{{ Class MDB2_Driver_mssql +/** + * MDB2 MSSQL Server driver + * + * @package MDB2 + * @category Database + * @author Frank M. Kromann + */ +class MDB2_Driver_mssql extends MDB2_Driver_Common +{ + // {{{ properties + + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => false); + + var $identifier_quoting = array('start' => '[', 'end' => ']', 'escape' => ']'); + + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'mssql'; + $this->dbsyntax = 'mssql'; + + $this->supported['sequences'] = 'emulated'; + $this->supported['indexes'] = true; + $this->supported['affected_rows'] = true; + $this->supported['transactions'] = true; + $this->supported['savepoints'] = false; + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['current_id'] = 'emulated'; + $this->supported['limit_queries'] = 'emulated'; + $this->supported['LOBs'] = true; + $this->supported['replace'] = 'emulated'; + $this->supported['sub_selects'] = true; + $this->supported['triggers'] = true; + $this->supported['auto_increment'] = true; + $this->supported['primary_key'] = true; + $this->supported['result_introspection'] = true; + $this->supported['prepared_statements'] = 'emulated'; + $this->supported['pattern_escaping'] = true; + $this->supported['new_link'] = true; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['database_device'] = false; + $this->options['database_size'] = false; + $this->options['max_identifiers_length'] = 128; // MS Access: 64 + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null, $connection = null) + { + if (is_null($connection)) { + $connection = $this->connection; + } + + $native_code = null; + if ($connection) { + $result = @mssql_query('select @@ERROR as ErrorCode', $connection); + if ($result) { + $native_code = @mssql_result($result, 0, 0); + @mssql_free_result($result); + } + } + $native_msg = @mssql_get_last_message(); + if (is_null($error)) { + static $ecode_map; + if (empty($ecode_map)) { + $ecode_map = array( + 102 => MDB2_ERROR_SYNTAX, + 110 => MDB2_ERROR_VALUE_COUNT_ON_ROW, + 155 => MDB2_ERROR_NOSUCHFIELD, + 156 => MDB2_ERROR_SYNTAX, + 170 => MDB2_ERROR_SYNTAX, + 207 => MDB2_ERROR_NOSUCHFIELD, + 208 => MDB2_ERROR_NOSUCHTABLE, + 245 => MDB2_ERROR_INVALID_NUMBER, + 319 => MDB2_ERROR_SYNTAX, + 321 => MDB2_ERROR_NOSUCHFIELD, + 325 => MDB2_ERROR_SYNTAX, + 336 => MDB2_ERROR_SYNTAX, + 515 => MDB2_ERROR_CONSTRAINT_NOT_NULL, + 547 => MDB2_ERROR_CONSTRAINT, + 911 => MDB2_ERROR_NOT_FOUND, + 1018 => MDB2_ERROR_SYNTAX, + 1035 => MDB2_ERROR_SYNTAX, + 1801 => MDB2_ERROR_ALREADY_EXISTS, + 1913 => MDB2_ERROR_ALREADY_EXISTS, + 2209 => MDB2_ERROR_SYNTAX, + 2223 => MDB2_ERROR_SYNTAX, + 2248 => MDB2_ERROR_SYNTAX, + 2256 => MDB2_ERROR_SYNTAX, + 2257 => MDB2_ERROR_SYNTAX, + 2627 => MDB2_ERROR_CONSTRAINT, + 2714 => MDB2_ERROR_ALREADY_EXISTS, + 3607 => MDB2_ERROR_DIVZERO, + 3701 => MDB2_ERROR_NOSUCHTABLE, + 7630 => MDB2_ERROR_SYNTAX, + 8134 => MDB2_ERROR_DIVZERO, + 9303 => MDB2_ERROR_SYNTAX, + 9317 => MDB2_ERROR_SYNTAX, + 9318 => MDB2_ERROR_SYNTAX, + 9331 => MDB2_ERROR_SYNTAX, + 9332 => MDB2_ERROR_SYNTAX, + 15253 => MDB2_ERROR_SYNTAX, + ); + } + if (isset($ecode_map[$native_code])) { + if ($native_code == 3701 + && preg_match('/Cannot drop the index/i', $native_msg) + ) { + $error = MDB2_ERROR_NOT_FOUND; + } else { + $error = $ecode_map[$native_code]; + } + } + } + return array($error, $native_code, $native_msg); + } + + // }}} + // {{{ function escapePattern($text) + + /** + * Quotes pattern (% and _) characters in a string) + * + * @param string the input string to quote + * + * @return string quoted string + * + * @access public + */ + function escapePattern($text) + { + $text = str_replace("[", "[ [ ]", $text); + foreach ($this->wildcards as $wildcard) { + $text = str_replace($wildcard, '[' . $wildcard . ']', $text); + } + return $text; + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!is_null($savepoint)) { + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'savepoint cannot be released when changes are auto committed', __FUNCTION__); + } + $query = 'SAVE TRANSACTION '.$savepoint; + return $this->_doQuery($query, true); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + if (!$this->destructor_registered && $this->opened_persistent) { + $this->destructor_registered = true; + register_shutdown_function('MDB2_closeOpenTransactions'); + } + $result =& $this->_doQuery('BEGIN TRANSACTION', true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = true; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + return MDB2_OK; + } + + $result =& $this->_doQuery('COMMIT TRANSACTION', true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ rollback() + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + $query = 'ROLLBACK TRANSACTION '.$savepoint; + return $this->_doQuery($query, true); + } + + $result =& $this->_doQuery('ROLLBACK TRANSACTION', true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ _doConnect() + + /** + * do the grunt work of the connect + * + * @return connection on success or MDB2 Error Object on failure + * @access protected + */ + function _doConnect($username, $password, $persistent = false) + { + if (!PEAR::loadExtension($this->phptype) && !PEAR::loadExtension('sybase_ct')) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + $params = array( + $this->dsn['hostspec'] ? $this->dsn['hostspec'] : 'localhost', + $username ? $username : null, + $password ? $password : null, + ); + if ($this->dsn['port']) { + $params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port']; + } + if (!$persistent) { + if (isset($this->dsn['new_link']) + && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) + ) { + $params[] = true; + } else { + $params[] = false; + } + } + + $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect'; + + $connection = @call_user_func_array($connect_function, $params); + if ($connection <= 0) { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__, __FUNCTION__); + } + + @mssql_query('SET ANSI_NULL_DFLT_ON ON', $connection); + + if (!empty($this->dsn['charset'])) { + $result = $this->setCharset($this->dsn['charset'], $connection); + if (PEAR::isError($result)) { + return $result; + } + } + + if ((bool)ini_get('mssql.datetimeconvert')) { + @ini_set('mssql.datetimeconvert', '0'); + } + + if (empty($this->dsn['disable_iso_date'])) { + @mssql_query('SET DATEFORMAT ymd', $connection); + } + + return $connection; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return true on success, MDB2 Error Object on failure + */ + function connect() + { + if (is_resource($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 + if (MDB2::areEquals($this->connected_dsn, $this->dsn) + && $this->opened_persistent == $this->options['persistent'] + ) { + return MDB2_OK; + } + $this->disconnect(false); + } + + $connection = $this->_doConnect( + $this->dsn['username'], + $this->dsn['password'], + $this->options['persistent'] + ); + if (PEAR::isError($connection)) { + return $connection; + } + + $this->connection = $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = ''; + $this->opened_persistent = $this->options['persistent']; + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + + if ($this->database_name) { + if ($this->database_name != $this->connected_database_name) { + if (!@mssql_select_db($this->database_name, $connection)) { + $err = $this->raiseError(null, null, null, + 'Could not select the database: '.$this->database_name, __FUNCTION__); + return $err; + } + $this->connected_database_name = $this->database_name; + } + } + + return MDB2_OK; + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $result = @mssql_select_db($name, $connection); + $errorInfo = $this->errorInfo(null, $connection); + @mssql_close($connection); + if (!$result) { + if ($errorInfo[0] != MDB2_ERROR_NOT_FOUND) { + exit; + $result = $this->raiseError($errorInfo[0], null, null, $errorInfo[2], __FUNCTION__); + return $result; + } + $result = false; + } + + return $result; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_resource($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if (!$this->opened_persistent || $force) { + @mssql_close($this->connection); + } + } + return parent::disconnect($force); + } + + // }}} + // {{{ standaloneQuery() + + /** + * execute a query as DBA + * + * @param string $query the SQL query + * @param mixed $types array that contains the types of the columns in + * the result set + * @param boolean $is_manip if the query is a manipulation query + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; + $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; + $connection = $this->_doConnect($user, $pass, $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); + if (!PEAR::isError($result)) { + $result = $this->_affectedRows($connection, $result); + } + + @mssql_close($connection); + return $result; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->options['disable_query']) { + $result = $is_manip ? 0 : null; + return $result; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + if (is_null($database_name)) { + $database_name = $this->database_name; + } + + if ($database_name) { + if ($database_name != $this->connected_database_name) { + if (!@mssql_select_db($database_name, $connection)) { + $err = $this->raiseError(null, null, null, + 'Could not select the database: '.$database_name, __FUNCTION__); + return $err; + } + $this->connected_database_name = $database_name; + } + } + + $result = @mssql_query($query, $connection); + if (!$result) { + $err =& $this->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return @mssql_rows_affected($connection); + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if ($limit > 0) { + $fetch = $offset + $limit; + if (!$is_manip) { + return preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i', + "\\1SELECT\\2 TOP $fetch", $query); + } + } + return $query; + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } else { + $query = 'SELECT @@VERSION'; + $server_info = $this->queryOne($query, 'text'); + if (PEAR::isError($server_info)) { + return $server_info; + } + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native && !PEAR::isError($server_info)) { + if (preg_match('/(\d+)\.(\d+)\.(\d+)/', $server_info, $tmp)) { + $server_info = array( + 'major' => $tmp[1], + 'minor' => $tmp[2], + 'patch' => $tmp[3], + 'extra' => null, + 'native' => $server_info, + ); + } else { + $server_info = array( + 'major' => null, + 'minor' => null, + 'patch' => null, + 'extra' => null, + 'native' => $server_info, + ); + } + } + return $server_info; + } + + // }}} + // {{{ _checkSequence + + /** + * Checks if there's a sequence that exists. + * + * @param string $seq_name The sequence name to verify. + * @return bool $tableExists The value if the table exists or not + * @access private + */ + function _checkSequence($seq_name) + { + $query = "SELECT * FROM $seq_name"; + $tableExists =& $this->_doQuery($query, true); + if (PEAR::isError($tableExists)) { + if ($tableExists->getCode() == MDB2_ERROR_NOSUCHTABLE) { + return false; + } + //return $tableExists; + return false; + } + return mssql_result($tableExists, 0, 0); + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError(MDB2_ERROR_NOSUCHTABLE); + + $seq_val = $this->_checkSequence($sequence_name); + + if ($seq_val) { + $query = "SET IDENTITY_INSERT $sequence_name OFF ". + "INSERT INTO $sequence_name DEFAULT VALUES"; + } else { + $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (0)"; + } + $result =& $this->_doQuery($query, true); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand && !$this->_checkSequence($sequence_name)) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $this->raiseError($result, null, null, + 'on demand sequence '.$seq_name.' could not be created', __FUNCTION__); + } else { + /** + * Little off-by-one problem with the sequence emulation + * here being fixed, that instead of re-calling nextID + * and forcing an increment by one, we simply check if it + * exists, then we get the last inserted id if it does. + * + * In theory, $seq_name should be created otherwise there would + * have been an error thrown somewhere up there.. + * + * @todo confirm + */ + if ($this->_checkSequence($seq_name)) { + return $this->lastInsertID($seq_name); + } + + return $this->nextID($seq_name, false); + } + } + return $result; + } + $value = $this->lastInsertID($sequence_name); + if (is_numeric($value)) { + $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value"; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name; + } + } + return $value; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + $server_info = $this->getServerVersion(); + if (is_array($server_info) && !is_null($server_info['major']) + && $server_info['major'] >= 8 + ) { + $query = "SELECT IDENT_CURRENT('$table')"; + } else { + $query = "SELECT @@IDENTITY"; + if (!is_null($table)) { + $query .= ' FROM '.$this->quoteIdentifier($table, true); + } + } + + return $this->queryOne($query, 'integer'); + } + + // }}} +} + +// }}} +// {{{ Class MDB2_Result_mssql + +/** + * MDB2 MSSQL Server result driver + * + * @package MDB2 + * @category Database + * @author Frank M. Kromann + */ +class MDB2_Result_mssql extends MDB2_Result_Common +{ + // {{{ _skipLimitOffset() + + /** + * Skip the first row of a result set. + * + * @param resource $result + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access protected + */ + function _skipLimitOffset() + { + if ($this->limit) { + if ($this->rownum >= $this->limit) { + return false; + } + } + if ($this->offset) { + while ($this->offset_count < $this->offset) { + ++$this->offset_count; + if (!is_array(@mssql_fetch_row($this->result))) { + $this->offset_count = $this->limit; + return false; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if (!$this->_skipLimitOffset()) { + $null = null; + return $null; + } + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $row = @mssql_fetch_assoc($this->result); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + $row = @mssql_fetch_row($this->result); + } + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_name = @mssql_field_name($this->result, $column); + $columns[$column_name] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + * @access public + */ + function numCols() + { + $cols = @mssql_num_fields($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + return $cols; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal result pointer to the next available result + * + * @return true on success, false if there is no more result set or an error object on failure + * @access public + */ + function nextResult() + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return false; + } + return @mssql_next_result($this->result); + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with $result. + * + * @return boolean true on success, false if $result is invalid + * @access public + */ + function free() + { + if (is_resource($this->result) && $this->db->connection) { + $free = @mssql_free_result($this->result); + if ($free === false) { + return $this->db->raiseError(null, null, null, + 'Could not free result', __FUNCTION__); + } + } + $this->result = false; + return MDB2_OK; + } + + // }}} +} + +// }}} +// {{{ class MDB2_BufferedResult_mssql + +/** + * MDB2 MSSQL Server buffered result driver + * + * @package MDB2 + * @category Database + * @author Frank M. Kromann + */ +class MDB2_BufferedResult_mssql extends MDB2_Result_mssql +{ + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if ($this->rownum != ($rownum - 1) && !@mssql_data_seek($this->result, $rownum)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return MDB2_OK; + } + return $this->db->raiseError(MDB2_ERROR_INVALID, null, null, + 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + $numrows = $this->numRows(); + if (PEAR::isError($numrows)) { + return $numrows; + } + return $this->rownum < ($numrows - 1); + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + $rows = @mssql_num_rows($this->result); + if (is_null($rows)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + return $this->db->raiseError(null, null, null, + 'Could not get row count', __FUNCTION__); + } + if ($this->limit) { + $rows -= $this->limit -1 + $this->offset; + if ($rows < 0) { + $rows = 0; + } + } + return $rows; + } +} + +// }}} +// {{{ MDB2_Statement_mssql + +/** + * MDB2 MSSQL Server statement driver + * + * @package MDB2 + * @category Database + * @author Frank M. Kromann + */ +class MDB2_Statement_mssql extends MDB2_Statement_Common +{ + +} + +// }}} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/mysql.php b/lib/Pear/MDB2/Driver/mysql.php new file mode 100644 index 0000000..96210e4 --- /dev/null +++ b/lib/Pear/MDB2/Driver/mysql.php @@ -0,0 +1,1685 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.208 2008/03/13 03:31:55 afz Exp $ +// + +/** + * MDB2 MySQL driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_mysql extends MDB2_Driver_Common +{ + // {{{ properties + + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => '\\', 'escape_pattern' => '\\'); + + var $identifier_quoting = array('start' => '`', 'end' => '`', 'escape' => '`'); + + var $sql_comments = array( + array('start' => '-- ', 'end' => "\n", 'escape' => false), + array('start' => '#', 'end' => "\n", 'escape' => false), + array('start' => '/*', 'end' => '*/', 'escape' => false), + ); + + var $server_capabilities_checked = false; + + var $start_transaction = false; + + var $varchar_max_length = 255; + + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'mysql'; + $this->dbsyntax = 'mysql'; + + $this->supported['sequences'] = 'emulated'; + $this->supported['indexes'] = true; + $this->supported['affected_rows'] = true; + $this->supported['transactions'] = false; + $this->supported['savepoints'] = false; + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['current_id'] = 'emulated'; + $this->supported['limit_queries'] = true; + $this->supported['LOBs'] = true; + $this->supported['replace'] = true; + $this->supported['sub_selects'] = 'emulated'; + $this->supported['triggers'] = false; + $this->supported['auto_increment'] = true; + $this->supported['primary_key'] = true; + $this->supported['result_introspection'] = true; + $this->supported['prepared_statements'] = 'emulated'; + $this->supported['identifier_quoting'] = true; + $this->supported['pattern_escaping'] = true; + $this->supported['new_link'] = true; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['default_table_type'] = ''; + $this->options['max_identifiers_length'] = 64; + + $this->_reCheckSupportedOptions(); + } + + // }}} + // {{{ _reCheckSupportedOptions() + + /** + * If the user changes certain options, other capabilities may depend + * on the new settings, so we need to check them (again). + * + * @access private + */ + function _reCheckSupportedOptions() + { + $this->supported['transactions'] = $this->options['use_transactions']; + $this->supported['savepoints'] = $this->options['use_transactions']; + if ($this->options['default_table_type']) { + switch (strtoupper($this->options['default_table_type'])) { + case 'BLACKHOLE': + case 'MEMORY': + case 'ARCHIVE': + case 'CSV': + case 'HEAP': + case 'ISAM': + case 'MERGE': + case 'MRG_ISAM': + case 'ISAM': + case 'MRG_MYISAM': + case 'MYISAM': + $this->supported['savepoints'] = false; + $this->supported['transactions'] = false; + $this->warnings[] = $this->options['default_table_type'] . + ' is not a supported default table type'; + break; + } + } + } + + // }}} + // {{{ function setOption($option, $value) + + /** + * set the option for the db class + * + * @param string option name + * @param mixed value for the option + * + * @return mixed MDB2_OK or MDB2 Error Object + * + * @access public + */ + function setOption($option, $value) + { + $res = parent::setOption($option, $value); + $this->_reCheckSupportedOptions(); + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null) + { + if ($this->connection) { + $native_code = @mysql_errno($this->connection); + $native_msg = @mysql_error($this->connection); + } else { + $native_code = @mysql_errno(); + $native_msg = @mysql_error(); + } + if (is_null($error)) { + static $ecode_map; + if (empty($ecode_map)) { + $ecode_map = array( + 1000 => MDB2_ERROR_INVALID, //hashchk + 1001 => MDB2_ERROR_INVALID, //isamchk + 1004 => MDB2_ERROR_CANNOT_CREATE, + 1005 => MDB2_ERROR_CANNOT_CREATE, + 1006 => MDB2_ERROR_CANNOT_CREATE, + 1007 => MDB2_ERROR_ALREADY_EXISTS, + 1008 => MDB2_ERROR_CANNOT_DROP, + 1009 => MDB2_ERROR_CANNOT_DROP, + 1010 => MDB2_ERROR_CANNOT_DROP, + 1011 => MDB2_ERROR_CANNOT_DELETE, + 1022 => MDB2_ERROR_ALREADY_EXISTS, + 1029 => MDB2_ERROR_NOT_FOUND, + 1032 => MDB2_ERROR_NOT_FOUND, + 1044 => MDB2_ERROR_ACCESS_VIOLATION, + 1045 => MDB2_ERROR_ACCESS_VIOLATION, + 1046 => MDB2_ERROR_NODBSELECTED, + 1048 => MDB2_ERROR_CONSTRAINT, + 1049 => MDB2_ERROR_NOSUCHDB, + 1050 => MDB2_ERROR_ALREADY_EXISTS, + 1051 => MDB2_ERROR_NOSUCHTABLE, + 1054 => MDB2_ERROR_NOSUCHFIELD, + 1060 => MDB2_ERROR_ALREADY_EXISTS, + 1061 => MDB2_ERROR_ALREADY_EXISTS, + 1062 => MDB2_ERROR_ALREADY_EXISTS, + 1064 => MDB2_ERROR_SYNTAX, + 1067 => MDB2_ERROR_INVALID, + 1072 => MDB2_ERROR_NOT_FOUND, + 1086 => MDB2_ERROR_ALREADY_EXISTS, + 1091 => MDB2_ERROR_NOT_FOUND, + 1100 => MDB2_ERROR_NOT_LOCKED, + 1109 => MDB2_ERROR_NOT_FOUND, + 1125 => MDB2_ERROR_ALREADY_EXISTS, + 1136 => MDB2_ERROR_VALUE_COUNT_ON_ROW, + 1138 => MDB2_ERROR_INVALID, + 1142 => MDB2_ERROR_ACCESS_VIOLATION, + 1143 => MDB2_ERROR_ACCESS_VIOLATION, + 1146 => MDB2_ERROR_NOSUCHTABLE, + 1149 => MDB2_ERROR_SYNTAX, + 1169 => MDB2_ERROR_CONSTRAINT, + 1176 => MDB2_ERROR_NOT_FOUND, + 1177 => MDB2_ERROR_NOSUCHTABLE, + 1213 => MDB2_ERROR_DEADLOCK, + 1216 => MDB2_ERROR_CONSTRAINT, + 1217 => MDB2_ERROR_CONSTRAINT, + 1227 => MDB2_ERROR_ACCESS_VIOLATION, + 1235 => MDB2_ERROR_CANNOT_CREATE, + 1299 => MDB2_ERROR_INVALID_DATE, + 1300 => MDB2_ERROR_INVALID, + 1304 => MDB2_ERROR_ALREADY_EXISTS, + 1305 => MDB2_ERROR_NOT_FOUND, + 1306 => MDB2_ERROR_CANNOT_DROP, + 1307 => MDB2_ERROR_CANNOT_CREATE, + 1334 => MDB2_ERROR_CANNOT_ALTER, + 1339 => MDB2_ERROR_NOT_FOUND, + 1356 => MDB2_ERROR_INVALID, + 1359 => MDB2_ERROR_ALREADY_EXISTS, + 1360 => MDB2_ERROR_NOT_FOUND, + 1363 => MDB2_ERROR_NOT_FOUND, + 1365 => MDB2_ERROR_DIVZERO, + 1451 => MDB2_ERROR_CONSTRAINT, + 1452 => MDB2_ERROR_CONSTRAINT, + 1542 => MDB2_ERROR_CANNOT_DROP, + 1546 => MDB2_ERROR_CONSTRAINT, + 1582 => MDB2_ERROR_CONSTRAINT, + 2003 => MDB2_ERROR_CONNECT_FAILED, + 2019 => MDB2_ERROR_INVALID, + ); + } + if ($this->options['portability'] & MDB2_PORTABILITY_ERRORS) { + $ecode_map[1022] = MDB2_ERROR_CONSTRAINT; + $ecode_map[1048] = MDB2_ERROR_CONSTRAINT_NOT_NULL; + $ecode_map[1062] = MDB2_ERROR_CONSTRAINT; + } else { + // Doing this in case mode changes during runtime. + $ecode_map[1022] = MDB2_ERROR_ALREADY_EXISTS; + $ecode_map[1048] = MDB2_ERROR_CONSTRAINT; + $ecode_map[1062] = MDB2_ERROR_ALREADY_EXISTS; + } + if (isset($ecode_map[$native_code])) { + $error = $ecode_map[$native_code]; + } + } + return array($error, $native_code, $native_msg); + } + + // }}} + // {{{ escape() + + /** + * Quotes a string so it can be safely used in a query. It will quote + * the text so it can safely be used within a query. + * + * @param string the input string to quote + * @param bool escape wildcards + * + * @return string quoted string + * + * @access public + */ + function escape($text, $escape_wildcards = false) + { + if ($escape_wildcards) { + $text = $this->escapePattern($text); + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $text = @mysql_real_escape_string($text, $connection); + return $text; + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + $this->_getServerCapabilities(); + if (!is_null($savepoint)) { + if (!$this->supports('savepoints')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'savepoint cannot be released when changes are auto committed', __FUNCTION__); + } + $query = 'SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + if (!$this->destructor_registered && $this->opened_persistent) { + $this->destructor_registered = true; + register_shutdown_function('MDB2_closeOpenTransactions'); + } + $query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 1'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = true; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + if (!$this->supports('savepoints')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + $server_info = $this->getServerVersion(); + if (version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) { + return MDB2_OK; + } + $query = 'RELEASE SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + if (!$this->supports('transactions')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'transactions are not supported', __FUNCTION__); + } + + $result =& $this->_doQuery('COMMIT', true); + if (PEAR::isError($result)) { + return $result; + } + if (!$this->start_transaction) { + $query = 'SET AUTOCOMMIT = 0'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ rollback() + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + if (!$this->supports('savepoints')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + $query = 'ROLLBACK TO SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + $query = 'ROLLBACK'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + if (!$this->start_transaction) { + $query = 'SET AUTOCOMMIT = 0'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ function setTransactionIsolation() + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + if (!$this->supports('transactions')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'transactions are not supported', __FUNCTION__); + } + switch ($isolation) { + case 'READ UNCOMMITTED': + case 'READ COMMITTED': + case 'REPEATABLE READ': + case 'SERIALIZABLE': + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level is not supported: '.$isolation, __FUNCTION__); + } + + $query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation"; + return $this->_doQuery($query, true); + } + + // }}} + // {{{ _doConnect() + + /** + * do the grunt work of the connect + * + * @return connection on success or MDB2 Error Object on failure + * @access protected + */ + function _doConnect($username, $password, $persistent = false) + { + if (!PEAR::loadExtension($this->phptype)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + $params = array(); + if ($this->dsn['protocol'] && $this->dsn['protocol'] == 'unix') { + $params[0] = ':' . $this->dsn['socket']; + } else { + $params[0] = $this->dsn['hostspec'] ? $this->dsn['hostspec'] + : 'localhost'; + if ($this->dsn['port']) { + $params[0].= ':' . $this->dsn['port']; + } + } + $params[] = $username ? $username : null; + $params[] = $password ? $password : null; + if (!$persistent) { + if (isset($this->dsn['new_link']) + && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) + ) { + $params[] = true; + } else { + $params[] = false; + } + } + if (version_compare(phpversion(), '4.3.0', '>=')) { + $params[] = isset($this->dsn['client_flags']) + ? $this->dsn['client_flags'] : null; + } + $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; + + $connection = @call_user_func_array($connect_function, $params); + if (!$connection) { + if (($err = @mysql_error()) != '') { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + $err, __FUNCTION__); + } else { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__); + } + } + + if (!empty($this->dsn['charset'])) { + $result = $this->setCharset($this->dsn['charset'], $connection); + if (PEAR::isError($result)) { + $this->disconnect(false); + return $result; + } + } + + return $connection; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return MDB2_OK on success, MDB2 Error Object on failure + * @access public + */ + function connect() + { + if (is_resource($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 + if (MDB2::areEquals($this->connected_dsn, $this->dsn) + && $this->opened_persistent == $this->options['persistent'] + ) { + return MDB2_OK; + } + $this->disconnect(false); + } + + $connection = $this->_doConnect( + $this->dsn['username'], + $this->dsn['password'], + $this->options['persistent'] + ); + if (PEAR::isError($connection)) { + return $connection; + } + + $this->connection = $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = ''; + $this->opened_persistent = $this->options['persistent']; + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + + if ($this->database_name) { + if ($this->database_name != $this->connected_database_name) { + if (!@mysql_select_db($this->database_name, $connection)) { + $err = $this->raiseError(null, null, null, + 'Could not select the database: '.$this->database_name, __FUNCTION__); + return $err; + } + $this->connected_database_name = $this->database_name; + } + } + + $this->_getServerCapabilities(); + + return MDB2_OK; + } + + // }}} + // {{{ setCharset() + + /** + * Set the charset on the current connection + * + * @param string charset (or array(charset, collation)) + * @param resource connection handle + * + * @return true on success, MDB2 Error Object on failure + */ + function setCharset($charset, $connection = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + $collation = null; + if (is_array($charset) && 2 == count($charset)) { + $collation = array_pop($charset); + $charset = array_pop($charset); + } + $query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'"; + if (!is_null($collation)) { + $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; + } + return $this->_doQuery($query, true, $connection); + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $result = @mysql_select_db($name, $connection); + @mysql_close($connection); + + return $result; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_resource($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if (!$this->opened_persistent || $force) { + @mysql_close($this->connection); + } + } + return parent::disconnect($force); + } + + // }}} + // {{{ standaloneQuery() + + /** + * execute a query as DBA + * + * @param string $query the SQL query + * @param mixed $types array that contains the types of the columns in + * the result set + * @param boolean $is_manip if the query is a manipulation query + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; + $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; + $connection = $this->_doConnect($user, $pass, $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); + if (!PEAR::isError($result)) { + $result = $this->_affectedRows($connection, $result); + } + + @mysql_close($connection); + return $result; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->options['disable_query']) { + $result = $is_manip ? 0 : null; + return $result; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + if (is_null($database_name)) { + $database_name = $this->database_name; + } + + if ($database_name) { + if ($database_name != $this->connected_database_name) { + if (!@mysql_select_db($database_name, $connection)) { + $err = $this->raiseError(null, null, null, + 'Could not select the database: '.$database_name, __FUNCTION__); + return $err; + } + $this->connected_database_name = $database_name; + } + } + + $function = $this->options['result_buffering'] + ? 'mysql_query' : 'mysql_unbuffered_query'; + $result = @$function($query, $connection); + if (!$result) { + $err =& $this->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return @mysql_affected_rows($connection); + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) { + // "DELETE FROM table" gives 0 affected rows in MySQL. + // This little hack lets you know how many rows were deleted. + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { + $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', + 'DELETE FROM \1 WHERE 1=1', $query); + } + } + if ($limit > 0 + && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query) + ) { + $query = rtrim($query); + if (substr($query, -1) == ';') { + $query = substr($query, 0, -1); + } + + // LIMIT doesn't always come last in the query + // @see http://dev.mysql.com/doc/refman/5.0/en/select.html + $after = ''; + if (preg_match('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', $query, $matches)) { + $after = $matches[0]; + $query = preg_replace('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', '', $query); + } elseif (preg_match('/(\s+FOR\s+UPDATE\s*)$/i', $query, $matches)) { + $after = $matches[0]; + $query = preg_replace('/(\s+FOR\s+UPDATE\s*)$/im', '', $query); + } elseif (preg_match('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', $query, $matches)) { + $after = $matches[0]; + $query = preg_replace('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', '', $query); + } + + if ($is_manip) { + return $query . " LIMIT $limit" . $after; + } else { + return $query . " LIMIT $offset, $limit" . $after; + } + } + return $query; + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } else { + $server_info = @mysql_get_server_info($connection); + } + if (!$server_info) { + return $this->raiseError(null, null, null, + 'Could not get server information', __FUNCTION__); + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native) { + $tmp = explode('.', $server_info, 3); + if (isset($tmp[2]) && strpos($tmp[2], '-')) { + $tmp2 = explode('-', @$tmp[2], 2); + } else { + $tmp2[0] = isset($tmp[2]) ? $tmp[2] : null; + $tmp2[1] = null; + } + $server_info = array( + 'major' => isset($tmp[0]) ? $tmp[0] : null, + 'minor' => isset($tmp[1]) ? $tmp[1] : null, + 'patch' => $tmp2[0], + 'extra' => $tmp2[1], + 'native' => $server_info, + ); + } + return $server_info; + } + + // }}} + // {{{ _getServerCapabilities() + + /** + * Fetch some information about the server capabilities + * (transactions, subselects, prepared statements, etc). + * + * @access private + */ + function _getServerCapabilities() + { + if (!$this->server_capabilities_checked) { + $this->server_capabilities_checked = true; + + //set defaults + $this->supported['sub_selects'] = 'emulated'; + $this->supported['prepared_statements'] = 'emulated'; + $this->supported['triggers'] = false; + $this->start_transaction = false; + $this->varchar_max_length = 255; + + $server_info = $this->getServerVersion(); + if (is_array($server_info)) { + $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch']; + + if (!version_compare($server_version, '4.1.0', '<')) { + $this->supported['sub_selects'] = true; + $this->supported['prepared_statements'] = true; + } + + // SAVEPOINTs were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB) + if (version_compare($server_version, '4.1.0', '>=')) { + if (version_compare($server_version, '4.1.1', '<')) { + $this->supported['savepoints'] = false; + } + } elseif (version_compare($server_version, '4.0.14', '<')) { + $this->supported['savepoints'] = false; + } + + if (!version_compare($server_version, '4.0.11', '<')) { + $this->start_transaction = true; + } + + if (!version_compare($server_version, '5.0.3', '<')) { + $this->varchar_max_length = 65532; + } + + if (!version_compare($server_version, '5.0.2', '<')) { + $this->supported['triggers'] = true; + } + } + } + } + + // }}} + // {{{ function _skipUserDefinedVariable($query, $position) + + /** + * Utility method, used by prepare() to avoid misinterpreting MySQL user + * defined variables (SELECT @x:=5) for placeholders. + * Check if the placeholder is a false positive, i.e. if it is an user defined + * variable instead. If so, skip it and advance the position, otherwise + * return the current position, which is valid + * + * @param string $query + * @param integer $position current string cursor position + * @return integer $new_position + * @access protected + */ + function _skipUserDefinedVariable($query, $position) + { + $found = strpos(strrev(substr($query, 0, $position)), '@'); + if ($found === false) { + return $position; + } + $pos = strlen($query) - strlen(substr($query, $position)) - $found - 1; + $substring = substr($query, $pos, $position - $pos + 2); + if (preg_match('/^@\w+\s*:=$/', $substring)) { + return $position + 1; //found an user defined variable: skip it + } + return $position; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * With some database backends, this is emulated. + * prepare() requires a generic query as string like + * 'INSERT INTO numbers VALUES(?,?)' or + * 'INSERT INTO numbers VALUES(:foo,:bar)'. + * The ? and :name and are placeholders which can be set using + * bindParam() and the query can be sent off using the execute() method. + * The allowed format for :name can be set with the 'bindname_format' option. + * + * @param string $query the query to prepare + * @param mixed $types array that contains the types of the placeholders + * @param mixed $result_types array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders + * @return mixed resource handle for the prepared query on success, a MDB2 + * error on failure + * @access public + * @see bindParam, execute + */ + function &prepare($query, $types = null, $result_types = null, $lobs = array()) + { + if ($this->options['emulate_prepared'] + || $this->supported['prepared_statements'] !== true + ) { + $obj =& parent::prepare($query, $types, $result_types, $lobs); + return $obj; + } + $is_manip = ($result_types === MDB2_PREPARE_MANIP); + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $placeholder_type_guess = $placeholder_type = null; + $question = '?'; + $colon = ':'; + $positions = array(); + $position = 0; + while ($position < strlen($query)) { + $q_position = strpos($query, $question, $position); + $c_position = strpos($query, $colon, $position); + if ($q_position && $c_position) { + $p_position = min($q_position, $c_position); + } elseif ($q_position) { + $p_position = $q_position; + } elseif ($c_position) { + $p_position = $c_position; + } else { + break; + } + if (is_null($placeholder_type)) { + $placeholder_type_guess = $query[$p_position]; + } + + $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position); + if (PEAR::isError($new_pos)) { + return $new_pos; + } + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + //make sure this is not part of an user defined variable + $new_pos = $this->_skipUserDefinedVariable($query, $position); + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + if ($query[$position] == $placeholder_type_guess) { + if (is_null($placeholder_type)) { + $placeholder_type = $query[$p_position]; + $question = $colon = $placeholder_type; + } + if ($placeholder_type == ':') { + $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; + $parameter = preg_replace($regexp, '\\1', $query); + if ($parameter === '') { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'named parameter name must match "bindname_format" option', __FUNCTION__); + return $err; + } + $positions[$p_position] = $parameter; + $query = substr_replace($query, '?', $position, strlen($parameter)+1); + } else { + $positions[$p_position] = count($positions); + } + $position = $p_position + 1; + } else { + $position = $p_position; + } + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + static $prep_statement_counter = 1; + $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); + $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); + $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text'); + $statement =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($statement)) { + return $statement; + } + + $class_name = 'MDB2_Statement_'.$this->phptype; + $obj = new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)); + return $obj; + } + + // }}} + // {{{ replace() + + /** + * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT + * query, except that if there is already a row in the table with the same + * key field values, the REPLACE query just updates its values instead of + * inserting a new row. + * + * The REPLACE type of query does not make part of the SQL standards. Since + * practically only MySQL implements it natively, this type of query is + * emulated through this method for other DBMS using standard types of + * queries inside a transaction to assure the atomicity of the operation. + * + * @access public + * + * @param string $table name of the table on which the REPLACE query will + * be executed. + * @param array $fields associative array that describes the fields and the + * values that will be inserted or updated in the specified table. The + * indexes of the array are the names of all the fields of the table. The + * values of the array are also associative arrays that describe the + * values and other properties of the table fields. + * + * Here follows a list of field properties that need to be specified: + * + * value: + * Value to be assigned to the specified field. This value may be + * of specified in database independent type format as this + * function can perform the necessary datatype conversions. + * + * Default: + * this property is required unless the Null property + * is set to 1. + * + * type + * Name of the type of the field. Currently, all types Metabase + * are supported except for clob and blob. + * + * Default: no type conversion + * + * null + * Boolean property that indicates that the value for this field + * should be set to null. + * + * The default value for fields missing in INSERT queries may be + * specified the definition of a table. Often, the default value + * is already null, but since the REPLACE may be emulated using + * an UPDATE query, make sure that all fields of the table are + * listed in this function argument array. + * + * Default: 0 + * + * key + * Boolean property that indicates that this field should be + * handled as a primary key or at least as part of the compound + * unique index of the table that will determine the row that will + * updated if it exists or inserted a new row otherwise. + * + * This function will fail if no key field is specified or if the + * value of a key field is set to null because fields that are + * part of unique index they may not be null. + * + * Default: 0 + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function replace($table, $fields) + { + $count = count($fields); + $query = $values = ''; + $keys = $colnum = 0; + for (reset($fields); $colnum < $count; next($fields), $colnum++) { + $name = key($fields); + if ($colnum > 0) { + $query .= ','; + $values.= ','; + } + $query.= $this->quoteIdentifier($name, true); + if (isset($fields[$name]['null']) && $fields[$name]['null']) { + $value = 'NULL'; + } else { + $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null; + $value = $this->quote($fields[$name]['value'], $type); + if (PEAR::isError($value)) { + return $value; + } + } + $values.= $value; + if (isset($fields[$name]['key']) && $fields[$name]['key']) { + if ($value === 'NULL') { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'key value '.$name.' may not be NULL', __FUNCTION__); + } + $keys++; + } + } + if ($keys == 0) { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'not specified which fields are keys', __FUNCTION__); + } + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $table = $this->quoteIdentifier($table, true); + $query = "REPLACE INTO $table ($query) VALUES ($values)"; + $result =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($result)) { + return $result; + } + return $this->_affectedRows($connection, $result); + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); + $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError(MDB2_ERROR_NOSUCHTABLE); + $result =& $this->_doQuery($query, true); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $this->raiseError($result, null, null, + 'on demand sequence '.$seq_name.' could not be created', __FUNCTION__); + } else { + return $this->nextID($seq_name, false); + } + } + return $result; + } + $value = $this->lastInsertID(); + if (is_numeric($value)) { + $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value"; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name; + } + } + return $value; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + // not using mysql_insert_id() due to http://pear.php.net/bugs/bug.php?id=8051 + return $this->queryOne('SELECT LAST_INSERT_ID()', 'integer'); + } + + // }}} + // {{{ currID() + + /** + * Returns the current id of a sequence + * + * @param string $seq_name name of the sequence + * @return mixed MDB2 Error Object or id + * @access public + */ + function currID($seq_name) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); + $query = "SELECT MAX($seqcol_name) FROM $sequence_name"; + return $this->queryOne($query, 'integer'); + } +} + +/** + * MDB2 MySQL result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Result_mysql extends MDB2_Result_Common +{ + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $row = @mysql_fetch_assoc($this->result); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + $row = @mysql_fetch_row($this->result); + } + + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_name = @mysql_field_name($this->result, $column); + $columns[$column_name] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + * @access public + */ + function numCols() + { + $cols = @mysql_num_fields($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + return $cols; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with result. + * + * @return boolean true on success, false if result is invalid + * @access public + */ + function free() + { + if (is_resource($this->result) && $this->db->connection) { + $free = @mysql_free_result($this->result); + if ($free === false) { + return $this->db->raiseError(null, null, null, + 'Could not free result', __FUNCTION__); + } + } + $this->result = false; + return MDB2_OK; + } +} + +/** + * MDB2 MySQL buffered result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_BufferedResult_mysql extends MDB2_Result_mysql +{ + // }}} + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if ($this->rownum != ($rownum - 1) && !@mysql_data_seek($this->result, $rownum)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return MDB2_OK; + } + return $this->db->raiseError(MDB2_ERROR_INVALID, null, null, + 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + $numrows = $this->numRows(); + if (PEAR::isError($numrows)) { + return $numrows; + } + return $this->rownum < ($numrows - 1); + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + $rows = @mysql_num_rows($this->result); + if (false === $rows) { + if (false === $this->result) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + return $this->db->raiseError(null, null, null, + 'Could not get row count', __FUNCTION__); + } + return $rows; + } +} + +/** + * MDB2 MySQL statement driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Statement_mysql extends MDB2_Statement_Common +{ + // {{{ _execute() + + /** + * Execute a prepared query statement helper method. + * + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function &_execute($result_class = true, $result_wrap_class = false) + { + if (is_null($this->statement)) { + $result =& parent::_execute($result_class, $result_wrap_class); + return $result; + } + $this->db->last_query = $this->query; + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values)); + if ($this->db->getOption('disable_query')) { + $result = $this->is_manip ? 0 : null; + return $result; + } + + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $query = 'EXECUTE '.$this->statement; + if (!empty($this->positions)) { + $parameters = array(); + foreach ($this->positions as $parameter) { + if (!array_key_exists($parameter, $this->values)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $value = $this->values[$parameter]; + $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null; + if (is_resource($value) || $type == 'clob' || $type == 'blob' && $this->db->options['lob_allow_url_include']) { + if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { + if ($match[1] == 'file://') { + $value = $match[2]; + } + $value = @fopen($value, 'r'); + $close = true; + } + if (is_resource($value)) { + $data = ''; + while (!@feof($value)) { + $data.= @fread($value, $this->db->options['lob_buffer_length']); + } + if ($close) { + @fclose($value); + } + $value = $data; + } + } + $quoted = $this->db->quote($value, $type); + if (PEAR::isError($quoted)) { + return $quoted; + } + $param_query = 'SET @'.$parameter.' = '.$quoted; + $result = $this->db->_doQuery($param_query, true, $connection); + if (PEAR::isError($result)) { + return $result; + } + } + $query.= ' USING @'.implode(', @', array_values($this->positions)); + } + + $result = $this->db->_doQuery($query, $this->is_manip, $connection); + if (PEAR::isError($result)) { + return $result; + } + + if ($this->is_manip) { + $affected_rows = $this->db->_affectedRows($connection, $result); + return $affected_rows; + } + + $result =& $this->db->_wrapResult($result, $this->result_types, + $result_class, $result_wrap_class, $this->limit, $this->offset); + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ free() + + /** + * Release resources allocated for the specified prepared query. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function free() + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + $result = MDB2_OK; + + if (!is_null($this->statement)) { + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $query = 'DEALLOCATE PREPARE '.$this->statement; + $result = $this->db->_doQuery($query, true, $connection); + } + + parent::free(); + return $result; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/mysqli.php b/lib/Pear/MDB2/Driver/mysqli.php new file mode 100644 index 0000000..3f8f961 --- /dev/null +++ b/lib/Pear/MDB2/Driver/mysqli.php @@ -0,0 +1,1841 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysqli.php,v 1.188 2008/03/13 03:31:55 afz Exp $ +// + +/** + * MDB2 MySQLi driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_mysqli extends MDB2_Driver_Common +{ + // {{{ properties + + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => '\\', 'escape_pattern' => '\\'); + + var $identifier_quoting = array('start' => '`', 'end' => '`', 'escape' => '`'); + + var $sql_comments = array( + array('start' => '-- ', 'end' => "\n", 'escape' => false), + array('start' => '#', 'end' => "\n", 'escape' => false), + array('start' => '/*', 'end' => '*/', 'escape' => false), + ); + + var $server_capabilities_checked = false; + + var $start_transaction = false; + + var $varchar_max_length = 255; + + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'mysqli'; + $this->dbsyntax = 'mysql'; + + $this->supported['sequences'] = 'emulated'; + $this->supported['indexes'] = true; + $this->supported['affected_rows'] = true; + $this->supported['transactions'] = false; + $this->supported['savepoints'] = false; + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['current_id'] = 'emulated'; + $this->supported['limit_queries'] = true; + $this->supported['LOBs'] = true; + $this->supported['replace'] = true; + $this->supported['sub_selects'] = 'emulated'; + $this->supported['triggers'] = false; + $this->supported['auto_increment'] = true; + $this->supported['primary_key'] = true; + $this->supported['result_introspection'] = true; + $this->supported['prepared_statements'] = 'emulated'; + $this->supported['identifier_quoting'] = true; + $this->supported['pattern_escaping'] = true; + $this->supported['new_link'] = true; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['default_table_type'] = ''; + $this->options['multi_query'] = false; + $this->options['max_identifiers_length'] = 64; + + $this->_reCheckSupportedOptions(); + } + + // }}} + // {{{ _reCheckSupportedOptions() + + /** + * If the user changes certain options, other capabilities may depend + * on the new settings, so we need to check them (again). + * + * @access private + */ + function _reCheckSupportedOptions() + { + $this->supported['transactions'] = $this->options['use_transactions']; + $this->supported['savepoints'] = $this->options['use_transactions']; + if ($this->options['default_table_type']) { + switch (strtoupper($this->options['default_table_type'])) { + case 'BLACKHOLE': + case 'MEMORY': + case 'ARCHIVE': + case 'CSV': + case 'HEAP': + case 'ISAM': + case 'MERGE': + case 'MRG_ISAM': + case 'ISAM': + case 'MRG_MYISAM': + case 'MYISAM': + $this->supported['savepoints'] = false; + $this->supported['transactions'] = false; + $this->warnings[] = $this->options['default_table_type'] . + ' is not a supported default table type'; + break; + } + } + } + + // }}} + // {{{ function setOption($option, $value) + + /** + * set the option for the db class + * + * @param string option name + * @param mixed value for the option + * + * @return mixed MDB2_OK or MDB2 Error Object + * + * @access public + */ + function setOption($option, $value) + { + $res = parent::setOption($option, $value); + $this->_reCheckSupportedOptions(); + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null) + { + if ($this->connection) { + $native_code = @mysqli_errno($this->connection); + $native_msg = @mysqli_error($this->connection); + } else { + $native_code = @mysqli_connect_errno(); + $native_msg = @mysqli_connect_error(); + } + if (is_null($error)) { + static $ecode_map; + if (empty($ecode_map)) { + $ecode_map = array( + 1000 => MDB2_ERROR_INVALID, //hashchk + 1001 => MDB2_ERROR_INVALID, //isamchk + 1004 => MDB2_ERROR_CANNOT_CREATE, + 1005 => MDB2_ERROR_CANNOT_CREATE, + 1006 => MDB2_ERROR_CANNOT_CREATE, + 1007 => MDB2_ERROR_ALREADY_EXISTS, + 1008 => MDB2_ERROR_CANNOT_DROP, + 1009 => MDB2_ERROR_CANNOT_DROP, + 1010 => MDB2_ERROR_CANNOT_DROP, + 1011 => MDB2_ERROR_CANNOT_DELETE, + 1022 => MDB2_ERROR_ALREADY_EXISTS, + 1029 => MDB2_ERROR_NOT_FOUND, + 1032 => MDB2_ERROR_NOT_FOUND, + 1044 => MDB2_ERROR_ACCESS_VIOLATION, + 1045 => MDB2_ERROR_ACCESS_VIOLATION, + 1046 => MDB2_ERROR_NODBSELECTED, + 1048 => MDB2_ERROR_CONSTRAINT, + 1049 => MDB2_ERROR_NOSUCHDB, + 1050 => MDB2_ERROR_ALREADY_EXISTS, + 1051 => MDB2_ERROR_NOSUCHTABLE, + 1054 => MDB2_ERROR_NOSUCHFIELD, + 1060 => MDB2_ERROR_ALREADY_EXISTS, + 1061 => MDB2_ERROR_ALREADY_EXISTS, + 1062 => MDB2_ERROR_ALREADY_EXISTS, + 1064 => MDB2_ERROR_SYNTAX, + 1067 => MDB2_ERROR_INVALID, + 1072 => MDB2_ERROR_NOT_FOUND, + 1086 => MDB2_ERROR_ALREADY_EXISTS, + 1091 => MDB2_ERROR_NOT_FOUND, + 1100 => MDB2_ERROR_NOT_LOCKED, + 1109 => MDB2_ERROR_NOT_FOUND, + 1125 => MDB2_ERROR_ALREADY_EXISTS, + 1136 => MDB2_ERROR_VALUE_COUNT_ON_ROW, + 1138 => MDB2_ERROR_INVALID, + 1142 => MDB2_ERROR_ACCESS_VIOLATION, + 1143 => MDB2_ERROR_ACCESS_VIOLATION, + 1146 => MDB2_ERROR_NOSUCHTABLE, + 1149 => MDB2_ERROR_SYNTAX, + 1169 => MDB2_ERROR_CONSTRAINT, + 1176 => MDB2_ERROR_NOT_FOUND, + 1177 => MDB2_ERROR_NOSUCHTABLE, + 1213 => MDB2_ERROR_DEADLOCK, + 1216 => MDB2_ERROR_CONSTRAINT, + 1217 => MDB2_ERROR_CONSTRAINT, + 1227 => MDB2_ERROR_ACCESS_VIOLATION, + 1235 => MDB2_ERROR_CANNOT_CREATE, + 1299 => MDB2_ERROR_INVALID_DATE, + 1300 => MDB2_ERROR_INVALID, + 1304 => MDB2_ERROR_ALREADY_EXISTS, + 1305 => MDB2_ERROR_NOT_FOUND, + 1306 => MDB2_ERROR_CANNOT_DROP, + 1307 => MDB2_ERROR_CANNOT_CREATE, + 1334 => MDB2_ERROR_CANNOT_ALTER, + 1339 => MDB2_ERROR_NOT_FOUND, + 1356 => MDB2_ERROR_INVALID, + 1359 => MDB2_ERROR_ALREADY_EXISTS, + 1360 => MDB2_ERROR_NOT_FOUND, + 1363 => MDB2_ERROR_NOT_FOUND, + 1365 => MDB2_ERROR_DIVZERO, + 1451 => MDB2_ERROR_CONSTRAINT, + 1452 => MDB2_ERROR_CONSTRAINT, + 1542 => MDB2_ERROR_CANNOT_DROP, + 1546 => MDB2_ERROR_CONSTRAINT, + 1582 => MDB2_ERROR_CONSTRAINT, + 2003 => MDB2_ERROR_CONNECT_FAILED, + 2019 => MDB2_ERROR_INVALID, + ); + } + if ($this->options['portability'] & MDB2_PORTABILITY_ERRORS) { + $ecode_map[1022] = MDB2_ERROR_CONSTRAINT; + $ecode_map[1048] = MDB2_ERROR_CONSTRAINT_NOT_NULL; + $ecode_map[1062] = MDB2_ERROR_CONSTRAINT; + } else { + // Doing this in case mode changes during runtime. + $ecode_map[1022] = MDB2_ERROR_ALREADY_EXISTS; + $ecode_map[1048] = MDB2_ERROR_CONSTRAINT; + $ecode_map[1062] = MDB2_ERROR_ALREADY_EXISTS; + } + if (isset($ecode_map[$native_code])) { + $error = $ecode_map[$native_code]; + } + } + return array($error, $native_code, $native_msg); + } + + // }}} + // {{{ escape() + + /** + * Quotes a string so it can be safely used in a query. It will quote + * the text so it can safely be used within a query. + * + * @param string the input string to quote + * @param bool escape wildcards + * + * @return string quoted string + * + * @access public + */ + function escape($text, $escape_wildcards = false) + { + if ($escape_wildcards) { + $text = $this->escapePattern($text); + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $text = @mysqli_real_escape_string($connection, $text); + return $text; + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + $this->_getServerCapabilities(); + if (!is_null($savepoint)) { + if (!$this->supports('savepoints')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'savepoint cannot be released when changes are auto committed', __FUNCTION__); + } + $query = 'SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + $query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 1'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = true; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + if (!$this->supports('savepoints')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + $server_info = $this->getServerVersion(); + if (version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) { + return MDB2_OK; + } + $query = 'RELEASE SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + if (!$this->supports('transactions')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'transactions are not supported', __FUNCTION__); + } + + $result =& $this->_doQuery('COMMIT', true); + if (PEAR::isError($result)) { + return $result; + } + if (!$this->start_transaction) { + $query = 'SET AUTOCOMMIT = 0'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ rollback() + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + if (!$this->supports('savepoints')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + $query = 'ROLLBACK TO SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + $query = 'ROLLBACK'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + if (!$this->start_transaction) { + $query = 'SET AUTOCOMMIT = 0'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ function setTransactionIsolation() + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + if (!$this->supports('transactions')) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'transactions are not supported', __FUNCTION__); + } + switch ($isolation) { + case 'READ UNCOMMITTED': + case 'READ COMMITTED': + case 'REPEATABLE READ': + case 'SERIALIZABLE': + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level is not supported: '.$isolation, __FUNCTION__); + } + + $query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation"; + return $this->_doQuery($query, true); + } + + // }}} + // {{{ _doConnect() + + /** + * do the grunt work of the connect + * + * @return connection on success or MDB2 Error Object on failure + * @access protected + */ + function _doConnect($username, $password, $persistent = false) + { + if (!PEAR::loadExtension($this->phptype)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + $connection = @mysqli_init(); + if (!empty($this->dsn['charset']) && defined('MYSQLI_SET_CHARSET_NAME')) { + @mysqli_options($connection, MYSQLI_SET_CHARSET_NAME, $this->dsn['charset']); + } + + if ($this->options['ssl']) { + @mysqli_ssl_set( + $connection, + empty($this->dsn['key']) ? null : $this->dsn['key'], + empty($this->dsn['cert']) ? null : $this->dsn['cert'], + empty($this->dsn['ca']) ? null : $this->dsn['ca'], + empty($this->dsn['capath']) ? null : $this->dsn['capath'], + empty($this->dsn['cipher']) ? null : $this->dsn['cipher'] + ); + } + + if (!@mysqli_real_connect( + $connection, + $this->dsn['hostspec'], + $username, + $password, + $this->database_name, + $this->dsn['port'], + $this->dsn['socket'] + )) { + if (($err = @mysqli_connect_error()) != '') { + return $this->raiseError(null, + null, null, $err, __FUNCTION__); + } else { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__); + } + } + + if (!empty($this->dsn['charset']) && !defined('MYSQLI_SET_CHARSET_NAME')) { + $result = $this->setCharset($this->dsn['charset'], $connection); + if (PEAR::isError($result)) { + return $result; + } + } + + return $connection; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return true on success, MDB2 Error Object on failure + */ + function connect() + { + if (is_object($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0) { + if (MDB2::areEquals($this->connected_dsn, $this->dsn)) { + return MDB2_OK; + } + $this->connection = 0; + } + + $connection = $this->_doConnect( + $this->dsn['username'], + $this->dsn['password'] + ); + if (PEAR::isError($connection)) { + return $connection; + } + + $this->connection = $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = $this->database_name; + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + + $this->_getServerCapabilities(); + + return MDB2_OK; + } + + // }}} + // {{{ setCharset() + + /** + * Set the charset on the current connection + * + * @param string charset (or array(charset, collation)) + * @param resource connection handle + * + * @return true on success, MDB2 Error Object on failure + */ + function setCharset($charset, $connection = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + $collation = null; + if (is_array($charset) && 2 == count($charset)) { + $collation = array_pop($charset); + $charset = array_pop($charset); + } + $client_info = mysqli_get_client_version(); + if (OS_WINDOWS && ((40111 > $client_info) || + ((50000 <= $client_info) && (50006 > $client_info))) + ) { + $query = "SET NAMES '".mysqli_real_escape_string($connection, $charset)."'"; + if (!is_null($collation)) { + $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; + } + return $this->_doQuery($query, true, $connection); + } + if (!$result = mysqli_set_charset($connection, $charset)) { + $err =& $this->raiseError(null, null, null, + 'Could not set client character set', __FUNCTION__); + return $err; + } + return $result; + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password']); + if (PEAR::isError($connection)) { + return $connection; + } + + $result = @mysqli_select_db($connection, $name); + @mysqli_close($connection); + + return $result; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_object($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if ($force) { + @mysqli_close($this->connection); + } + } + return parent::disconnect($force); + } + + // }}} + // {{{ standaloneQuery() + + /** + * execute a query as DBA + * + * @param string $query the SQL query + * @param mixed $types array that contains the types of the columns in + * the result set + * @param boolean $is_manip if the query is a manipulation query + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; + $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; + $connection = $this->_doConnect($user, $pass); + if (PEAR::isError($connection)) { + return $connection; + } + + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); + if (!PEAR::isError($result)) { + $result = $this->_affectedRows($connection, $result); + } + + @mysqli_close($connection); + return $result; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->options['disable_query']) { + $result = $is_manip ? 0 : null; + return $result; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + if (is_null($database_name)) { + $database_name = $this->database_name; + } + + if ($database_name) { + if ($database_name != $this->connected_database_name) { + if (!@mysqli_select_db($connection, $database_name)) { + $err = $this->raiseError(null, null, null, + 'Could not select the database: '.$database_name, __FUNCTION__); + return $err; + } + $this->connected_database_name = $database_name; + } + } + + if ($this->options['multi_query']) { + $result = mysqli_multi_query($connection, $query); + } else { + $resultmode = $this->options['result_buffering'] ? MYSQLI_USE_RESULT : MYSQLI_USE_RESULT; + $result = mysqli_query($connection, $query); + } + + if (!$result) { + $err =& $this->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + if ($this->options['multi_query']) { + if ($this->options['result_buffering']) { + if (!($result = @mysqli_store_result($connection))) { + $err =& $this->raiseError(null, null, null, + 'Could not get the first result from a multi query', __FUNCTION__); + return $err; + } + } elseif (!($result = @mysqli_use_result($connection))) { + $err =& $this->raiseError(null, null, null, + 'Could not get the first result from a multi query', __FUNCTION__); + return $err; + } + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return @mysqli_affected_rows($connection); + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) { + // "DELETE FROM table" gives 0 affected rows in MySQL. + // This little hack lets you know how many rows were deleted. + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { + $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', + 'DELETE FROM \1 WHERE 1=1', $query); + } + } + if ($limit > 0 + && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query) + ) { + $query = rtrim($query); + if (substr($query, -1) == ';') { + $query = substr($query, 0, -1); + } + + // LIMIT doesn't always come last in the query + // @see http://dev.mysql.com/doc/refman/5.0/en/select.html + $after = ''; + if (preg_match('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', $query, $matches)) { + $after = $matches[0]; + $query = preg_replace('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', '', $query); + } elseif (preg_match('/(\s+FOR\s+UPDATE\s*)$/i', $query, $matches)) { + $after = $matches[0]; + $query = preg_replace('/(\s+FOR\s+UPDATE\s*)$/im', '', $query); + } elseif (preg_match('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', $query, $matches)) { + $after = $matches[0]; + $query = preg_replace('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', '', $query); + } + + if ($is_manip) { + return $query . " LIMIT $limit" . $after; + } else { + return $query . " LIMIT $offset, $limit" . $after; + } + } + return $query; + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } else { + $server_info = @mysqli_get_server_info($connection); + } + if (!$server_info) { + return $this->raiseError(null, null, null, + 'Could not get server information', __FUNCTION__); + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native) { + $tmp = explode('.', $server_info, 3); + if (isset($tmp[2]) && strpos($tmp[2], '-')) { + $tmp2 = explode('-', @$tmp[2], 2); + } else { + $tmp2[0] = isset($tmp[2]) ? $tmp[2] : null; + $tmp2[1] = null; + } + $server_info = array( + 'major' => isset($tmp[0]) ? $tmp[0] : null, + 'minor' => isset($tmp[1]) ? $tmp[1] : null, + 'patch' => $tmp2[0], + 'extra' => $tmp2[1], + 'native' => $server_info, + ); + } + return $server_info; + } + + // }}} + // {{{ _getServerCapabilities() + + /** + * Fetch some information about the server capabilities + * (transactions, subselects, prepared statements, etc). + * + * @access private + */ + function _getServerCapabilities() + { + if (!$this->server_capabilities_checked) { + $this->server_capabilities_checked = true; + + //set defaults + $this->supported['sub_selects'] = 'emulated'; + $this->supported['prepared_statements'] = 'emulated'; + $this->supported['triggers'] = false; + $this->start_transaction = false; + $this->varchar_max_length = 255; + + $server_info = $this->getServerVersion(); + if (is_array($server_info)) { + $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch']; + + if (!version_compare($server_version, '4.1.0', '<')) { + $this->supported['sub_selects'] = true; + $this->supported['prepared_statements'] = true; + } + + // SAVEPOINTS were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB) + if (version_compare($server_version, '4.1.0', '>=')) { + if (version_compare($server_version, '4.1.1', '<')) { + $this->supported['savepoints'] = false; + } + } elseif (version_compare($server_version, '4.0.14', '<')) { + $this->supported['savepoints'] = false; + } + + if (!version_compare($server_version, '4.0.11', '<')) { + $this->start_transaction = true; + } + + if (!version_compare($server_version, '5.0.3', '<')) { + $this->varchar_max_length = 65532; + } + + if (!version_compare($server_version, '5.0.2', '<')) { + $this->supported['triggers'] = true; + } + } + } + } + + // }}} + // {{{ function _skipUserDefinedVariable($query, $position) + + /** + * Utility method, used by prepare() to avoid misinterpreting MySQL user + * defined variables (SELECT @x:=5) for placeholders. + * Check if the placeholder is a false positive, i.e. if it is an user defined + * variable instead. If so, skip it and advance the position, otherwise + * return the current position, which is valid + * + * @param string $query + * @param integer $position current string cursor position + * @return integer $new_position + * @access protected + */ + function _skipUserDefinedVariable($query, $position) + { + $found = strpos(strrev(substr($query, 0, $position)), '@'); + if ($found === false) { + return $position; + } + $pos = strlen($query) - strlen(substr($query, $position)) - $found - 1; + $substring = substr($query, $pos, $position - $pos + 2); + if (preg_match('/^@\w+\s*:=$/', $substring)) { + return $position + 1; //found an user defined variable: skip it + } + return $position; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * With some database backends, this is emulated. + * prepare() requires a generic query as string like + * 'INSERT INTO numbers VALUES(?,?)' or + * 'INSERT INTO numbers VALUES(:foo,:bar)'. + * The ? and :name and are placeholders which can be set using + * bindParam() and the query can be sent off using the execute() method. + * The allowed format for :name can be set with the 'bindname_format' option. + * + * @param string $query the query to prepare + * @param mixed $types array that contains the types of the placeholders + * @param mixed $result_types array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders + * @return mixed resource handle for the prepared query on success, a MDB2 + * error on failure + * @access public + * @see bindParam, execute + */ + function &prepare($query, $types = null, $result_types = null, $lobs = array()) + { + if ($this->options['emulate_prepared'] + || $this->supported['prepared_statements'] !== true + ) { + $obj =& parent::prepare($query, $types, $result_types, $lobs); + return $obj; + } + $is_manip = ($result_types === MDB2_PREPARE_MANIP); + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $placeholder_type_guess = $placeholder_type = null; + $question = '?'; + $colon = ':'; + $positions = array(); + $position = 0; + while ($position < strlen($query)) { + $q_position = strpos($query, $question, $position); + $c_position = strpos($query, $colon, $position); + if ($q_position && $c_position) { + $p_position = min($q_position, $c_position); + } elseif ($q_position) { + $p_position = $q_position; + } elseif ($c_position) { + $p_position = $c_position; + } else { + break; + } + if (is_null($placeholder_type)) { + $placeholder_type_guess = $query[$p_position]; + } + + $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position); + if (PEAR::isError($new_pos)) { + return $new_pos; + } + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + //make sure this is not part of an user defined variable + $new_pos = $this->_skipUserDefinedVariable($query, $position); + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + if ($query[$position] == $placeholder_type_guess) { + if (is_null($placeholder_type)) { + $placeholder_type = $query[$p_position]; + $question = $colon = $placeholder_type; + } + if ($placeholder_type == ':') { + $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; + $parameter = preg_replace($regexp, '\\1', $query); + if ($parameter === '') { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'named parameter name must match "bindname_format" option', __FUNCTION__); + return $err; + } + $positions[$p_position] = $parameter; + $query = substr_replace($query, '?', $position, strlen($parameter)+1); + } else { + $positions[$p_position] = count($positions); + } + $position = $p_position + 1; + } else { + $position = $p_position; + } + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + if (!$is_manip) { + static $prep_statement_counter = 1; + $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); + $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); + $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text'); + + $statement =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($statement)) { + return $statement; + } + $statement = $statement_name; + } else { + $statement = @mysqli_prepare($connection, $query); + if (!$statement) { + $err =& $this->raiseError(null, null, null, + 'Unable to create prepared statement handle', __FUNCTION__); + return $err; + } + } + + $class_name = 'MDB2_Statement_'.$this->phptype; + $obj = new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)); + return $obj; + } + + // }}} + // {{{ replace() + + /** + * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT + * query, except that if there is already a row in the table with the same + * key field values, the REPLACE query just updates its values instead of + * inserting a new row. + * + * The REPLACE type of query does not make part of the SQL standards. Since + * practically only MySQL implements it natively, this type of query is + * emulated through this method for other DBMS using standard types of + * queries inside a transaction to assure the atomicity of the operation. + * + * @access public + * + * @param string $table name of the table on which the REPLACE query will + * be executed. + * @param array $fields associative array that describes the fields and the + * values that will be inserted or updated in the specified table. The + * indexes of the array are the names of all the fields of the table. The + * values of the array are also associative arrays that describe the + * values and other properties of the table fields. + * + * Here follows a list of field properties that need to be specified: + * + * value: + * Value to be assigned to the specified field. This value may be + * of specified in database independent type format as this + * function can perform the necessary datatype conversions. + * + * Default: + * this property is required unless the Null property + * is set to 1. + * + * type + * Name of the type of the field. Currently, all types Metabase + * are supported except for clob and blob. + * + * Default: no type conversion + * + * null + * Boolean property that indicates that the value for this field + * should be set to null. + * + * The default value for fields missing in INSERT queries may be + * specified the definition of a table. Often, the default value + * is already null, but since the REPLACE may be emulated using + * an UPDATE query, make sure that all fields of the table are + * listed in this function argument array. + * + * Default: 0 + * + * key + * Boolean property that indicates that this field should be + * handled as a primary key or at least as part of the compound + * unique index of the table that will determine the row that will + * updated if it exists or inserted a new row otherwise. + * + * This function will fail if no key field is specified or if the + * value of a key field is set to null because fields that are + * part of unique index they may not be null. + * + * Default: 0 + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function replace($table, $fields) + { + $count = count($fields); + $query = $values = ''; + $keys = $colnum = 0; + for (reset($fields); $colnum < $count; next($fields), $colnum++) { + $name = key($fields); + if ($colnum > 0) { + $query .= ','; + $values.= ','; + } + $query.= $this->quoteIdentifier($name, true); + if (isset($fields[$name]['null']) && $fields[$name]['null']) { + $value = 'NULL'; + } else { + $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null; + $value = $this->quote($fields[$name]['value'], $type); + if (PEAR::isError($value)) { + return $value; + } + } + $values.= $value; + if (isset($fields[$name]['key']) && $fields[$name]['key']) { + if ($value === 'NULL') { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'key value '.$name.' may not be NULL', __FUNCTION__); + } + $keys++; + } + } + if ($keys == 0) { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'not specified which fields are keys', __FUNCTION__); + } + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $table = $this->quoteIdentifier($table, true); + $query = "REPLACE INTO $table ($query) VALUES ($values)"; + $result =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($result)) { + return $result; + } + return $this->_affectedRows($connection, $result); + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); + $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError(MDB2_ERROR_NOSUCHTABLE); + $result =& $this->_doQuery($query, true); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $this->raiseError($result, null, null, + 'on demand sequence '.$seq_name.' could not be created', __FUNCTION__); + } else { + return $this->nextID($seq_name, false); + } + } + return $result; + } + $value = $this->lastInsertID(); + if (is_numeric($value)) { + $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value"; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name; + } + } + return $value; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + // not using mysql_insert_id() due to http://pear.php.net/bugs/bug.php?id=8051 + return $this->queryOne('SELECT LAST_INSERT_ID()', 'integer'); + } + + // }}} + // {{{ currID() + + /** + * Returns the current id of a sequence + * + * @param string $seq_name name of the sequence + * @return mixed MDB2 Error Object or id + * @access public + */ + function currID($seq_name) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); + $query = "SELECT MAX($seqcol_name) FROM $sequence_name"; + return $this->queryOne($query, 'integer'); + } +} + +/** + * MDB2 MySQLi result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Result_mysqli extends MDB2_Result_Common +{ + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $row = @mysqli_fetch_assoc($this->result); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + $row = @mysqli_fetch_row($this->result); + } + + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_info = @mysqli_fetch_field_direct($this->result, $column); + $columns[$column_info->name] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + * @access public + */ + function numCols() + { + $cols = @mysqli_num_fields($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + return $cols; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal result pointer to the next available result + * + * @return true on success, false if there is no more result set or an error object on failure + * @access public + */ + function nextResult() + { + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + if (!@mysqli_more_results($connection)) { + return false; + } + if (!@mysqli_next_result($connection)) { + return false; + } + if (!($this->result = @mysqli_use_result($connection))) { + return false; + } + return MDB2_OK; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with result. + * + * @return boolean true on success, false if result is invalid + * @access public + */ + function free() + { + if (is_object($this->result) && $this->db->connection) { + $free = @mysqli_free_result($this->result); + if ($free === false) { + return $this->db->raiseError(null, null, null, + 'Could not free result', __FUNCTION__); + } + } + $this->result = false; + return MDB2_OK; + } +} + +/** + * MDB2 MySQLi buffered result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_BufferedResult_mysqli extends MDB2_Result_mysqli +{ + // }}} + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if ($this->rownum != ($rownum - 1) && !@mysqli_data_seek($this->result, $rownum)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return MDB2_OK; + } + return $this->db->raiseError(MDB2_ERROR_INVALID, null, null, + 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + $numrows = $this->numRows(); + if (PEAR::isError($numrows)) { + return $numrows; + } + return $this->rownum < ($numrows - 1); + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + $rows = @mysqli_num_rows($this->result); + if (is_null($rows)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + return $this->db->raiseError(null, null, null, + 'Could not get row count', __FUNCTION__); + } + return $rows; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal result pointer to the next available result + * + * @param a valid result resource + * @return true on success, false if there is no more result set or an error object on failure + * @access public + */ + function nextResult() + { + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + if (!@mysqli_more_results($connection)) { + return false; + } + if (!@mysqli_next_result($connection)) { + return false; + } + if (!($this->result = @mysqli_store_result($connection))) { + return false; + } + return MDB2_OK; + } +} + +/** + * MDB2 MySQLi statement driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Statement_mysqli extends MDB2_Statement_Common +{ + // {{{ _execute() + + /** + * Execute a prepared query statement helper method. + * + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function &_execute($result_class = true, $result_wrap_class = false) + { + if (is_null($this->statement)) { + $result =& parent::_execute($result_class, $result_wrap_class); + return $result; + } + $this->db->last_query = $this->query; + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values)); + if ($this->db->getOption('disable_query')) { + $result = $this->is_manip ? 0 : null; + return $result; + } + + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + if (!is_object($this->statement)) { + $query = 'EXECUTE '.$this->statement; + } + if (!empty($this->positions)) { + $parameters = array(0 => $this->statement, 1 => ''); + $lobs = array(); + $i = 0; + foreach ($this->positions as $parameter) { + if (!array_key_exists($parameter, $this->values)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $value = $this->values[$parameter]; + $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null; + if (!is_object($this->statement)) { + if (is_resource($value) || $type == 'clob' || $type == 'blob' && $this->db->options['lob_allow_url_include']) { + if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { + if ($match[1] == 'file://') { + $value = $match[2]; + } + $value = @fopen($value, 'r'); + $close = true; + } + if (is_resource($value)) { + $data = ''; + while (!@feof($value)) { + $data.= @fread($value, $this->db->options['lob_buffer_length']); + } + if ($close) { + @fclose($value); + } + $value = $data; + } + } + $quoted = $this->db->quote($value, $type); + if (PEAR::isError($quoted)) { + return $quoted; + } + $param_query = 'SET @'.$parameter.' = '.$quoted; + $result = $this->db->_doQuery($param_query, true, $connection); + if (PEAR::isError($result)) { + return $result; + } + } else { + if (is_resource($value) || $type == 'clob' || $type == 'blob') { + $parameters[] = null; + $parameters[1].= 'b'; + $lobs[$i] = $parameter; + } else { + $quoted = $this->db->quote($value, $type, false); + if (PEAR::isError($quoted)) { + return $quoted; + } + $parameters[] = $quoted; + $parameters[1].= $this->db->datatype->mapPrepareDatatype($type); + } + ++$i; + } + } + + if (!is_object($this->statement)) { + $query.= ' USING @'.implode(', @', array_values($this->positions)); + } else { + $result = @call_user_func_array('mysqli_stmt_bind_param', $parameters); + if ($result === false) { + $err =& $this->db->raiseError(null, null, null, + 'Unable to bind parameters', __FUNCTION__); + return $err; + } + + foreach ($lobs as $i => $parameter) { + $value = $this->values[$parameter]; + $close = false; + if (!is_resource($value)) { + $close = true; + if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { + if ($match[1] == 'file://') { + $value = $match[2]; + } + $value = @fopen($value, 'r'); + } else { + $fp = @tmpfile(); + @fwrite($fp, $value); + @rewind($fp); + $value = $fp; + } + } + while (!@feof($value)) { + $data = @fread($value, $this->db->options['lob_buffer_length']); + @mysqli_stmt_send_long_data($this->statement, $i, $data); + } + if ($close) { + @fclose($value); + } + } + } + } + + if (!is_object($this->statement)) { + $result = $this->db->_doQuery($query, $this->is_manip, $connection); + if (PEAR::isError($result)) { + return $result; + } + + if ($this->is_manip) { + $affected_rows = $this->db->_affectedRows($connection, $result); + return $affected_rows; + } + + $result =& $this->db->_wrapResult($result, $this->result_types, + $result_class, $result_wrap_class, $this->limit, $this->offset); + } else { + if (!@mysqli_stmt_execute($this->statement)) { + $err =& $this->db->raiseError(null, null, null, + 'Unable to execute statement', __FUNCTION__); + return $err; + } + + if ($this->is_manip) { + $affected_rows = @mysqli_stmt_affected_rows($this->statement); + return $affected_rows; + } + + if ($this->db->options['result_buffering']) { + @mysqli_stmt_store_result($this->statement); + } + + $result =& $this->db->_wrapResult($this->statement, $this->result_types, + $result_class, $result_wrap_class, $this->limit, $this->offset); + } + + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ free() + + /** + * Release resources allocated for the specified prepared query. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function free() + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + $result = MDB2_OK; + + if (is_object($this->statement)) { + if (!@mysqli_stmt_close($this->statement)) { + $result = $this->db->raiseError(null, null, null, + 'Could not free statement', __FUNCTION__); + } + } elseif (!is_null($this->statement)) { + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $query = 'DEALLOCATE PREPARE '.$this->statement; + $result = $this->db->_doQuery($query, true, $connection); + } + + parent::free(); + return $result; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/oci8.php b/lib/Pear/MDB2/Driver/oci8.php new file mode 100644 index 0000000..48077d5 --- /dev/null +++ b/lib/Pear/MDB2/Driver/oci8.php @@ -0,0 +1,1625 @@ + | +// +----------------------------------------------------------------------+ + +// $Id: oci8.php,v 1.213 2008/03/08 14:18:39 quipo Exp $ + +/** + * MDB2 OCI8 driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_oci8 extends MDB2_Driver_Common +{ + // {{{ properties + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => '@'); + + var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"'); + + var $uncommitedqueries = 0; + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'oci8'; + $this->dbsyntax = 'oci8'; + + $this->supported['sequences'] = true; + $this->supported['indexes'] = true; + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['current_id'] = true; + $this->supported['affected_rows'] = true; + $this->supported['transactions'] = true; + $this->supported['savepoints'] = true; + $this->supported['limit_queries'] = true; + $this->supported['LOBs'] = true; + $this->supported['replace'] = 'emulated'; + $this->supported['sub_selects'] = true; + $this->supported['triggers'] = true; + $this->supported['auto_increment'] = false; // implementation is broken + $this->supported['primary_key'] = true; + $this->supported['result_introspection'] = true; + $this->supported['prepared_statements'] = true; + $this->supported['identifier_quoting'] = true; + $this->supported['pattern_escaping'] = true; + $this->supported['new_link'] = true; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['database_name_prefix'] = false; + $this->options['emulate_database'] = true; + $this->options['default_tablespace'] = false; + $this->options['default_text_field_length'] = 2000; + $this->options['lob_allow_url_include'] = false; + $this->options['result_prefetching'] = false; + $this->options['max_identifiers_length'] = 30; + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null) + { + if (is_resource($error)) { + $error_data = @OCIError($error); + $error = null; + } elseif ($this->connection) { + $error_data = @OCIError($this->connection); + } else { + $error_data = @OCIError(); + } + $native_code = $error_data['code']; + $native_msg = $error_data['message']; + if (is_null($error)) { + static $ecode_map; + if (empty($ecode_map)) { + $ecode_map = array( + 1 => MDB2_ERROR_CONSTRAINT, + 900 => MDB2_ERROR_SYNTAX, + 904 => MDB2_ERROR_NOSUCHFIELD, + 911 => MDB2_ERROR_SYNTAX, //invalid character + 913 => MDB2_ERROR_VALUE_COUNT_ON_ROW, + 921 => MDB2_ERROR_SYNTAX, + 923 => MDB2_ERROR_SYNTAX, + 942 => MDB2_ERROR_NOSUCHTABLE, + 955 => MDB2_ERROR_ALREADY_EXISTS, + 1400 => MDB2_ERROR_CONSTRAINT_NOT_NULL, + 1401 => MDB2_ERROR_INVALID, + 1407 => MDB2_ERROR_CONSTRAINT_NOT_NULL, + 1418 => MDB2_ERROR_NOT_FOUND, + 1435 => MDB2_ERROR_NOT_FOUND, + 1476 => MDB2_ERROR_DIVZERO, + 1722 => MDB2_ERROR_INVALID_NUMBER, + 2289 => MDB2_ERROR_NOSUCHTABLE, + 2291 => MDB2_ERROR_CONSTRAINT, + 2292 => MDB2_ERROR_CONSTRAINT, + 2449 => MDB2_ERROR_CONSTRAINT, + 24344 => MDB2_ERROR_SYNTAX, //success with compilation error + ); + } + if (isset($ecode_map[$native_code])) { + $error = $ecode_map[$native_code]; + } + } + return array($error, $native_code, $native_msg); + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!is_null($savepoint)) { + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'savepoint cannot be released when changes are auto committed', __FUNCTION__); + } + $query = 'SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + if (!$this->destructor_registered && $this->opened_persistent) { + $this->destructor_registered = true; + register_shutdown_function('MDB2_closeOpenTransactions'); + } + $this->in_transaction = true; + ++$this->uncommitedqueries; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + return MDB2_OK; + } + + if ($this->uncommitedqueries) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + if (!@OCICommit($connection)) { + return $this->raiseError(null, null, null, + 'Unable to commit transaction', __FUNCTION__); + } + $this->uncommitedqueries = 0; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ rollback() + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + $query = 'ROLLBACK TO SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + if ($this->uncommitedqueries) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + if (!@OCIRollback($connection)) { + return $this->raiseError(null, null, null, + 'Unable to rollback transaction', __FUNCTION__); + } + $this->uncommitedqueries = 0; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ function setTransactionIsolation() + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + switch ($isolation) { + case 'READ UNCOMMITTED': + $isolation = 'READ COMMITTED'; + case 'READ COMMITTED': + case 'REPEATABLE READ': + $isolation = 'SERIALIZABLE'; + case 'SERIALIZABLE': + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level is not supported: '.$isolation, __FUNCTION__); + } + + $query = "ALTER SESSION ISOLATION LEVEL $isolation"; + return $this->_doQuery($query, true); + } + + // }}} + // {{{ _doConnect() + + /** + * do the grunt work of the connect + * + * @return connection on success or MDB2 Error Object on failure + * @access protected + */ + function _doConnect($username, $password, $persistent = false) + { + if (!PEAR::loadExtension($this->phptype)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + $sid = ''; + + if (!empty($this->dsn['service']) && $this->dsn['hostspec']) { + //oci8://username:password@foo.example.com[:port]/?service=service + // service name is given, it is assumed that hostspec is really a + // hostname, we try to construct an oracle connection string from this + $port = $this->dsn['port'] ? $this->dsn['port'] : 1521; + $sid = sprintf("(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) + (HOST=%s) (PORT=%s))) + (CONNECT_DATA=(SERVICE_NAME=%s)))", + $this->dsn['hostspec'], + $port, + $this->dsn['service'] + ); + } elseif ($this->dsn['hostspec']) { + // we are given something like 'oci8://username:password@foo/' + // we have hostspec but not a service name, now we assume that + // hostspec is a tnsname defined in tnsnames.ora + $sid = $this->dsn['hostspec']; + if (isset($this->dsn['port']) && $this->dsn['port']) { + $sid = $sid.':'.$this->dsn['port']; + } + } else { + // oci://username:password@ + // if everything fails, we have to rely on environment variables + // not before a check to 'emulate_database' + if (!$this->options['emulate_database'] && $this->database_name) { + $sid = $this->database_name; + } elseif (getenv('ORACLE_SID')) { + $sid = getenv('ORACLE_SID'); + } elseif ($sid = getenv('TWO_TASK')) { + $sid = getenv('TWO_TASK'); + } else { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'not a valid connection string or environment variable [ORACLE_SID|TWO_TASK] not set', + __FUNCTION__); + } + } + + if (function_exists('oci_connect')) { + if (isset($this->dsn['new_link']) + && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) + ) { + $connect_function = 'oci_new_connect'; + } else { + $connect_function = $persistent ? 'oci_pconnect' : 'oci_connect'; + } + + $charset = empty($this->dsn['charset']) ? null : $this->dsn['charset']; + $session_mode = empty($this->dsn['session_mode']) ? null : $this->dsn['session_mode']; + $connection = @$connect_function($username, $password, $sid, $charset, $session_mode); + $error = @OCIError(); + if (isset($error['code']) && $error['code'] == 12541) { + // Couldn't find TNS listener. Try direct connection. + $connection = @$connect_function($username, $password, null, $charset); + } + } else { + $connect_function = $persistent ? 'OCIPLogon' : 'OCILogon'; + $connection = @$connect_function($username, $password, $sid); + + if (!empty($this->dsn['charset'])) { + $result = $this->setCharset($this->dsn['charset'], $connection); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (!$connection) { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__); + } + + if (empty($this->dsn['disable_iso_date'])) { + $query = "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'"; + $err =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($err)) { + $this->disconnect(false); + return $err; + } + } + + $query = "ALTER SESSION SET NLS_NUMERIC_CHARACTERS='. '"; + $err =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($err)) { + $this->disconnect(false); + return $err; + } + + return $connection; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return MDB2_OK on success, MDB2 Error Object on failure + * @access public + */ + function connect() + { + if (is_resource($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 + if (MDB2::areEquals($this->connected_dsn, $this->dsn) + && $this->opened_persistent == $this->options['persistent'] + ) { + return MDB2_OK; + } + $this->disconnect(false); + } + + if ($this->database_name && $this->options['emulate_database']) { + $this->dsn['username'] = $this->options['database_name_prefix'].$this->database_name; + } + + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + $this->connection = $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = ''; + $this->opened_persistent = $this->options['persistent']; + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + + if ($this->database_name) { + if ($this->database_name != $this->connected_database_name) { + $query = 'ALTER SESSION SET CURRENT_SCHEMA = "' .strtoupper($this->database_name) .'"'; + $result =& $this->_doQuery($query); + if (PEAR::isError($result)) { + $err = $this->raiseError($result, null, null, + 'Could not select the database: '.$this->database_name, __FUNCTION__); + return $err; + } + $this->connected_database_name = $this->database_name; + } + } + + $this->as_keyword = ' '; + $server_info = $this->getServerVersion(); + if (is_array($server_info)) { + if ($server_info['major'] >= '10') { + $this->as_keyword = ' AS '; + } + } + return MDB2_OK; + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $query = 'ALTER SESSION SET CURRENT_SCHEMA = "' .strtoupper($name) .'"'; + $result =& $this->_doQuery($query, true, $connection, false); + if (PEAR::isError($result)) { + if (!MDB2::isError($result, MDB2_ERROR_NOT_FOUND)) { + return $result; + } + return false; + } + return true; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_resource($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if (!$this->opened_persistent || $force) { + if (function_exists('oci_close')) { + @oci_close($this->connection); + } else { + @OCILogOff($this->connection); + } + } + $this->uncommitedqueries = 0; + } + return parent::disconnect($force); + } + + // }}} + // {{{ standaloneQuery() + + /** + * execute a query as DBA + * + * @param string $query the SQL query + * @param mixed $types array containing the types of the columns in + * the result set + * @param boolean $is_manip if the query is a manipulation query + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; + $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; + $connection = $this->_doConnect($user, $pass, $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $result =& $this->_doQuery($query, $is_manip, $connection, false); + if (!PEAR::isError($result)) { + if ($is_manip) { + $result = $this->_affectedRows($connection, $result); + } else { + $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset); + } + } + + @OCILogOff($connection); + return $result; + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if (preg_match('/^\s*SELECT/i', $query)) { + if (!preg_match('/\sFROM\s/i', $query)) { + $query.= " FROM dual"; + } + if ($limit > 0) { + // taken from http://svn.ez.no/svn/ezcomponents/packages/Database + $max = $offset + $limit; + if ($offset > 0) { + $min = $offset + 1; + $query = "SELECT * FROM (SELECT a.*, ROWNUM mdb2rn FROM ($query) a WHERE ROWNUM <= $max) WHERE mdb2rn >= $min"; + } else { + $query = "SELECT a.* FROM ($query) a WHERE ROWNUM <= $max"; + } + } + } + return $query; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->getOption('disable_query')) { + if ($is_manip) { + return 0; + } + return null; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + + $query = str_replace("\r\n", "\n", $query); //for fixing end-of-line character in the PL/SQL in windows + $result = @OCIParse($connection, $query); + if (!$result) { + $err = $this->raiseError(null, null, null, + 'Could not create statement', __FUNCTION__); + return $err; + } + + $mode = $this->in_transaction ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS; + if (!@OCIExecute($result, $mode)) { + $err =& $this->raiseError($result, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + if (is_numeric($this->options['result_prefetching'])) { + @ocisetprefetch($result, $this->options['result_prefetching']); + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return @OCIRowCount($result); + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } else { + $server_info = @ociserverversion($connection); + } + if (!$server_info) { + return $this->raiseError(null, null, null, + 'Could not get server information', __FUNCTION__); + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native) { + if (!preg_match('/ (\d+)\.(\d+)\.(\d+)\.([\d\.]+) /', $server_info, $tmp)) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'Could not parse version information:'.$server_info, __FUNCTION__); + } + $server_info = array( + 'major' => $tmp[1], + 'minor' => $tmp[2], + 'patch' => $tmp[3], + 'extra' => $tmp[4], + 'native' => $server_info, + ); + } + return $server_info; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * With some database backends, this is emulated. + * prepare() requires a generic query as string like + * 'INSERT INTO numbers VALUES(?,?)' or + * 'INSERT INTO numbers VALUES(:foo,:bar)'. + * The ? and :name and are placeholders which can be set using + * bindParam() and the query can be sent off using the execute() method. + * The allowed format for :name can be set with the 'bindname_format' option. + * + * @param string $query the query to prepare + * @param mixed $types array that contains the types of the placeholders + * @param mixed $result_types array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders + * @return mixed resource handle for the prepared query on success, a MDB2 + * error on failure + * @access public + * @see bindParam, execute + */ + function &prepare($query, $types = null, $result_types = null, $lobs = array()) + { + if ($this->options['emulate_prepared']) { + $obj =& parent::prepare($query, $types, $result_types, $lobs); + return $obj; + } + $is_manip = ($result_types === MDB2_PREPARE_MANIP); + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + $placeholder_type_guess = $placeholder_type = null; + $question = '?'; + $colon = ':'; + $positions = array(); + $position = 0; + $parameter = -1; + while ($position < strlen($query)) { + $q_position = strpos($query, $question, $position); + $c_position = strpos($query, $colon, $position); + if ($q_position && $c_position) { + $p_position = min($q_position, $c_position); + } elseif ($q_position) { + $p_position = $q_position; + } elseif ($c_position) { + $p_position = $c_position; + } else { + break; + } + if (is_null($placeholder_type)) { + $placeholder_type_guess = $query[$p_position]; + } + + $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position); + if (PEAR::isError($new_pos)) { + return $new_pos; + } + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + if ($query[$position] == $placeholder_type_guess) { + if (is_null($placeholder_type)) { + $placeholder_type = $query[$p_position]; + $question = $colon = $placeholder_type; + if (!empty($types) && is_array($types)) { + if ($placeholder_type == ':') { + if (is_int(key($types))) { + $types_tmp = $types; + $types = array(); + $count = -1; + } + } else { + $types = array_values($types); + } + } + } + if ($placeholder_type == ':') { + $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; + $parameter = preg_replace($regexp, '\\1', $query); + if ($parameter === '') { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'named parameter name must match "bindname_format" option', __FUNCTION__); + return $err; + } + // use parameter name in type array + if (isset($count) && isset($types_tmp[++$count])) { + $types[$parameter] = $types_tmp[$count]; + } + $length = strlen($parameter) + 1; + } else { + ++$parameter; + $length = strlen($parameter); + } + if (!in_array($parameter, $positions)) { + $positions[] = $parameter; + } + if (isset($types[$parameter]) + && ($types[$parameter] == 'clob' || $types[$parameter] == 'blob') + ) { + if (!isset($lobs[$parameter])) { + $lobs[$parameter] = $parameter; + } + $value = $this->quote(true, $types[$parameter]); + if (PEAR::isError($value)) { + return $value; + } + $query = substr_replace($query, $value, $p_position, $length); + $position = $p_position + strlen($value) - 1; + } elseif ($placeholder_type == '?') { + $query = substr_replace($query, ':'.$parameter, $p_position, 1); + $position = $p_position + $length; + } else { + $position = $p_position + 1; + } + } else { + $position = $p_position; + } + } + if (is_array($lobs)) { + $columns = $variables = ''; + foreach ($lobs as $parameter => $field) { + $columns.= ($columns ? ', ' : ' RETURNING ').$field; + $variables.= ($variables ? ', ' : ' INTO ').':'.$parameter; + } + $query.= $columns.$variables; + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $statement = @OCIParse($connection, $query); + if (!$statement) { + $err =& $this->raiseError(null, null, null, + 'Could not create statement', __FUNCTION__); + return $err; + } + + $class_name = 'MDB2_Statement_'.$this->phptype; + $obj = new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)); + return $obj; + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $query = "SELECT $sequence_name.nextval FROM DUAL"; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError(MDB2_ERROR_NOSUCHTABLE); + $result = $this->queryOne($query, 'integer'); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $result; + } + return $this->nextId($seq_name, false); + } + } + return $result; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + $seq = $table.(empty($field) ? '' : '_'.$field); + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true); + return $this->queryOne("SELECT $sequence_name.currval", 'integer'); + } + + // }}} + // {{{ currId() + + /** + * Returns the current id of a sequence + * + * @param string $seq_name name of the sequence + * @return mixed MDB2_Error or id + * @access public + */ + function currId($seq_name) + { + $sequence_name = $this->getSequenceName($seq_name); + $query = 'SELECT (last_number-1) FROM all_sequences'; + $query.= ' WHERE sequence_name='.$this->quote($sequence_name, 'text'); + $query.= ' OR sequence_name='.$this->quote(strtoupper($sequence_name), 'text'); + return $this->queryOne($query, 'integer'); + } +} + +/** + * MDB2 OCI8 result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Result_oci8 extends MDB2_Result_Common +{ + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + @OCIFetchInto($this->result, $row, OCI_ASSOC+OCI_RETURN_NULLS); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + @OCIFetchInto($this->result, $row, OCI_RETURN_NULLS); + } + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + // remove additional column at the end + if ($this->offset > 0) { + array_pop($row); + } + $mode = 0; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_name = @OCIColumnName($this->result, $column + 1); + $columns[$column_name] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + * @access public + */ + function numCols() + { + $cols = @OCINumCols($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + if ($this->offset > 0) { + --$cols; + } + return $cols; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with $result. + * + * @return boolean true on success, false if $result is invalid + * @access public + */ + function free() + { + if (is_resource($this->result) && $this->db->connection) { + $free = @OCIFreeCursor($this->result); + if ($free === false) { + return $this->db->raiseError(null, null, null, + 'Could not free result', __FUNCTION__); + } + } + $this->result = false; + return MDB2_OK; + + } +} + +/** + * MDB2 OCI8 buffered result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_BufferedResult_oci8 extends MDB2_Result_oci8 +{ + var $buffer; + var $buffer_rownum = - 1; + + // {{{ _fillBuffer() + + /** + * Fill the row buffer + * + * @param int $rownum row number upto which the buffer should be filled + if the row number is null all rows are ready into the buffer + * @return boolean true on success, false on failure + * @access protected + */ + function _fillBuffer($rownum = null) + { + if (isset($this->buffer) && is_array($this->buffer)) { + if (is_null($rownum)) { + if (!end($this->buffer)) { + return false; + } + } elseif (isset($this->buffer[$rownum])) { + return (bool)$this->buffer[$rownum]; + } + } + + $row = true; + while ((is_null($rownum) || $this->buffer_rownum < $rownum) + && ($row = @OCIFetchInto($this->result, $buffer, OCI_RETURN_NULLS)) + ) { + ++$this->buffer_rownum; + // remove additional column at the end + if ($this->offset > 0) { + array_pop($buffer); + } + if (empty($this->types)) { + foreach (array_keys($buffer) as $key) { + if (is_a($buffer[$key], 'oci-lob')) { + $buffer[$key] = $buffer[$key]->load(); + } + } + } + $this->buffer[$this->buffer_rownum] = $buffer; + } + + if (!$row) { + ++$this->buffer_rownum; + $this->buffer[$this->buffer_rownum] = false; + return false; + } + return true; + } + + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } elseif (is_null($this->result)) { + return null; + } + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + $target_rownum = $this->rownum + 1; + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if (!$this->_fillBuffer($target_rownum)) { + $null = null; + return $null; + } + $row = $this->buffer[$target_rownum]; + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $column_names = $this->getColumnNames(); + foreach ($column_names as $name => $i) { + $column_names[$name] = $row[$i]; + } + $row = $column_names; + } + $mode = 0; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return true; + } + if ($this->_fillBuffer($this->rownum + 1)) { + return true; + } + return false; + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + $this->_fillBuffer(); + return $this->buffer_rownum; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with $result. + * + * @return boolean true on success, false if $result is invalid + * @access public + */ + function free() + { + $this->buffer = null; + $this->buffer_rownum = null; + return parent::free(); + } +} + +/** + * MDB2 OCI8 statement driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Statement_oci8 extends MDB2_Statement_Common +{ + // {{{ Variables (Properties) + + var $type_maxlengths = array(); + + // }}} + // {{{ bindParam() + + /** + * Bind a variable to a parameter of a prepared query. + * + * @param int $parameter the order number of the parameter in the query + * statement. The order number of the first parameter is 1. + * @param mixed &$value variable that is meant to be bound to specified + * parameter. The type of the value depends on the $type argument. + * @param string $type specifies the type of the field + * @param int $maxlength specifies the maximum length of the field; if set to -1, the + * current length of $value is used + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function bindParam($parameter, &$value, $type = null, $maxlength = -1) + { + if (!is_numeric($parameter)) { + $parameter = preg_replace('/^:(.*)$/', '\\1', $parameter); + } + if (MDB2_OK === ($ret = parent::bindParam($parameter, $value, $type))) { + $this->type_maxlengths[$parameter] = $maxlength; + } + + return $ret; + } + + // }}} + // {{{ _execute() + + /** + * Execute a prepared query statement helper method. + * + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function &_execute($result_class = true, $result_wrap_class = false) + { + if (is_null($this->statement)) { + $result =& parent::_execute($result_class, $result_wrap_class); + return $result; + } + $this->db->last_query = $this->query; + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values)); + if ($this->db->getOption('disable_query')) { + $result = $this->is_manip ? 0 : null; + return $result; + } + + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $result = MDB2_OK; + $lobs = $quoted_values = array(); + $i = 0; + foreach ($this->positions as $parameter) { + if (!array_key_exists($parameter, $this->values)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null; + if ($type == 'clob' || $type == 'blob') { + $lobs[$i]['file'] = false; + if (is_resource($this->values[$parameter])) { + $fp = $this->values[$parameter]; + $this->values[$parameter] = ''; + while (!feof($fp)) { + $this->values[$parameter] .= fread($fp, 8192); + } + } elseif (is_a($this->values[$parameter], 'OCI-Lob')) { + //do nothing + } elseif ($this->db->getOption('lob_allow_url_include') + && preg_match('/^(\w+:\/\/)(.*)$/', $this->values[$parameter], $match) + ) { + $lobs[$i]['file'] = true; + if ($match[1] == 'file://') { + $this->values[$parameter] = $match[2]; + } + } + $lobs[$i]['value'] = $this->values[$parameter]; + $lobs[$i]['descriptor'] =& $this->values[$parameter]; + // Test to see if descriptor has already been created for this + // variable (i.e. if it has been bound more than once): + if (!is_a($this->values[$parameter], 'OCI-Lob')) { + $this->values[$parameter] = @OCINewDescriptor($connection, OCI_D_LOB); + if ($this->values[$parameter] === false) { + $result = $this->db->raiseError(null, null, null, + 'Unable to create descriptor for LOB in parameter: '.$parameter, __FUNCTION__); + break; + } + } + $lob_type = ($type == 'blob' ? OCI_B_BLOB : OCI_B_CLOB); + if (!@OCIBindByName($this->statement, ':'.$parameter, $lobs[$i]['descriptor'], -1, $lob_type)) { + $result = $this->db->raiseError($this->statement, null, null, + 'could not bind LOB parameter', __FUNCTION__); + break; + } + } else if ($type == OCI_B_BFILE) { + // Test to see if descriptor has already been created for this + // variable (i.e. if it has been bound more than once): + if (!is_a($this->values[$parameter], "OCI-Lob")) { + $this->values[$parameter] = @OCINewDescriptor($connection, OCI_D_FILE); + if ($this->values[$parameter] === false) { + $result = $this->db->raiseError(null, null, null, + 'Unable to create descriptor for BFILE in parameter: '.$parameter, __FUNCTION__); + break; + } + } + if (!@OCIBindByName($this->statement, ':'.$parameter, $this->values[$parameter], -1, $type)) { + $result = $this->db->raiseError($this->statement, null, null, + 'Could not bind BFILE parameter', __FUNCTION__); + break; + } + } else if ($type == OCI_B_ROWID) { + // Test to see if descriptor has already been created for this + // variable (i.e. if it has been bound more than once): + if (!is_a($this->values[$parameter], "OCI-Lob")) { + $this->values[$parameter] = @OCINewDescriptor($connection, OCI_D_ROWID); + if ($this->values[$parameter] === false) { + $result = $this->db->raiseError(null, null, null, + 'Unable to create descriptor for ROWID in parameter: '.$parameter, __FUNCTION__); + break; + } + } + if (!@OCIBindByName($this->statement, ':'.$parameter, $this->values[$parameter], -1, $type)) { + $result = $this->db->raiseError($this->statement, null, null, + 'Could not bind ROWID parameter', __FUNCTION__); + break; + } + } else if ($type == OCI_B_CURSOR) { + // Test to see if cursor has already been allocated for this + // variable (i.e. if it has been bound more than once): + if (!is_resource($this->values[$parameter]) || !get_resource_type($this->values[$parameter]) == "oci8 statement") { + $this->values[$parameter] = @OCINewCursor($connection); + if ($this->values[$parameter] === false) { + $result = $this->db->raiseError(null, null, null, + 'Unable to allocate cursor for parameter: '.$parameter, __FUNCTION__); + break; + } + } + if (!@OCIBindByName($this->statement, ':'.$parameter, $this->values[$parameter], -1, $type)) { + $result = $this->db->raiseError($this->statement, null, null, + 'Could not bind CURSOR parameter', __FUNCTION__); + break; + } + } else { + $maxlength = array_key_exists($parameter, $this->type_maxlengths) ? $this->type_maxlengths[$parameter] : -1; + $this->values[$parameter] = $this->db->quote($this->values[$parameter], $type, false); + $quoted_values[$i] =& $this->values[$parameter]; + if (PEAR::isError($quoted_values[$i])) { + return $quoted_values[$i]; + } + if (!@OCIBindByName($this->statement, ':'.$parameter, $quoted_values[$i], $maxlength)) { + $result = $this->db->raiseError($this->statement, null, null, + 'could not bind non-abstract parameter', __FUNCTION__); + break; + } + } + ++$i; + } + + $lob_keys = array_keys($lobs); + if (!PEAR::isError($result)) { + $mode = (!empty($lobs) || $this->db->in_transaction) ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS; + if (!@OCIExecute($this->statement, $mode)) { + $err =& $this->db->raiseError($this->statement, null, null, + 'could not execute statement', __FUNCTION__); + return $err; + } + + if (!empty($lobs)) { + foreach ($lob_keys as $i) { + if (!is_null($lobs[$i]['value']) && $lobs[$i]['value'] !== '') { + if (is_object($lobs[$i]['value'])) { + // Probably a NULL LOB + // @see http://bugs.php.net/bug.php?id=27485 + continue; + } + if ($lobs[$i]['file']) { + $result = $lobs[$i]['descriptor']->savefile($lobs[$i]['value']); + } else { + $result = $lobs[$i]['descriptor']->save($lobs[$i]['value']); + } + if (!$result) { + $result = $this->db->raiseError(null, null, null, + 'Unable to save descriptor contents', __FUNCTION__); + break; + } + } + } + + if (!PEAR::isError($result)) { + if (!$this->db->in_transaction) { + if (!@OCICommit($connection)) { + $result = $this->db->raiseError(null, null, null, + 'Unable to commit transaction', __FUNCTION__); + } + } else { + ++$this->db->uncommitedqueries; + } + } + } + } + + if (PEAR::isError($result)) { + return $result; + } + + if ($this->is_manip) { + $affected_rows = $this->db->_affectedRows($connection, $this->statement); + return $affected_rows; + } + + $result =& $this->db->_wrapResult($this->statement, $this->result_types, + $result_class, $result_wrap_class, $this->limit, $this->offset); + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ free() + + /** + * Release resources allocated for the specified prepared query. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function free() + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + $result = MDB2_OK; + + if (!is_null($this->statement) && !@OCIFreeStatement($this->statement)) { + $result = $this->db->raiseError(null, null, null, + 'Could not free statement', __FUNCTION__); + } + + parent::free(); + return $result; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/pgsql.php b/lib/Pear/MDB2/Driver/pgsql.php new file mode 100644 index 0000000..24af056 --- /dev/null +++ b/lib/Pear/MDB2/Driver/pgsql.php @@ -0,0 +1,1512 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: pgsql.php,v 1.197 2008/03/08 14:18:39 quipo Exp $ + +/** + * MDB2 PostGreSQL driver + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_Driver_pgsql extends MDB2_Driver_Common +{ + // {{{ properties + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => '\\'); + + var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"'); + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'pgsql'; + $this->dbsyntax = 'pgsql'; + + $this->supported['sequences'] = true; + $this->supported['indexes'] = true; + $this->supported['affected_rows'] = true; + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['transactions'] = true; + $this->supported['savepoints'] = true; + $this->supported['current_id'] = true; + $this->supported['limit_queries'] = true; + $this->supported['LOBs'] = true; + $this->supported['replace'] = 'emulated'; + $this->supported['sub_selects'] = true; + $this->supported['triggers'] = true; + $this->supported['auto_increment'] = 'emulated'; + $this->supported['primary_key'] = true; + $this->supported['result_introspection'] = true; + $this->supported['prepared_statements'] = true; + $this->supported['identifier_quoting'] = true; + $this->supported['pattern_escaping'] = true; + $this->supported['new_link'] = true; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['multi_query'] = false; + $this->options['disable_smart_seqname'] = false; + $this->options['max_identifiers_length'] = 63; + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null) + { + // Fall back to MDB2_ERROR if there was no mapping. + $error_code = MDB2_ERROR; + + $native_msg = ''; + if (is_resource($error)) { + $native_msg = @pg_result_error($error); + } elseif ($this->connection) { + $native_msg = @pg_last_error($this->connection); + if (!$native_msg && @pg_connection_status($this->connection) === PGSQL_CONNECTION_BAD) { + $native_msg = 'Database connection has been lost.'; + $error_code = MDB2_ERROR_CONNECT_FAILED; + } + } else { + $native_msg = @pg_last_error(); + } + + static $error_regexps; + if (empty($error_regexps)) { + $error_regexps = array( + '/column .* (of relation .*)?does not exist/i' + => MDB2_ERROR_NOSUCHFIELD, + '/(relation|sequence|table).*does not exist|class .* not found/i' + => MDB2_ERROR_NOSUCHTABLE, + '/database .* does not exist/' + => MDB2_ERROR_NOT_FOUND, + '/index .* does not exist/' + => MDB2_ERROR_NOT_FOUND, + '/database .* already exists/i' + => MDB2_ERROR_ALREADY_EXISTS, + '/relation .* already exists/i' + => MDB2_ERROR_ALREADY_EXISTS, + '/(divide|division) by zero$/i' + => MDB2_ERROR_DIVZERO, + '/pg_atoi: error in .*: can\'t parse /i' + => MDB2_ERROR_INVALID_NUMBER, + '/invalid input syntax for( type)? (integer|numeric)/i' + => MDB2_ERROR_INVALID_NUMBER, + '/value .* is out of range for type \w*int/i' + => MDB2_ERROR_INVALID_NUMBER, + '/integer out of range/i' + => MDB2_ERROR_INVALID_NUMBER, + '/value too long for type character/i' + => MDB2_ERROR_INVALID, + '/attribute .* not found|relation .* does not have attribute/i' + => MDB2_ERROR_NOSUCHFIELD, + '/column .* specified in USING clause does not exist in (left|right) table/i' + => MDB2_ERROR_NOSUCHFIELD, + '/parser: parse error at or near/i' + => MDB2_ERROR_SYNTAX, + '/syntax error at/' + => MDB2_ERROR_SYNTAX, + '/column reference .* is ambiguous/i' + => MDB2_ERROR_SYNTAX, + '/permission denied/' + => MDB2_ERROR_ACCESS_VIOLATION, + '/violates not-null constraint/' + => MDB2_ERROR_CONSTRAINT_NOT_NULL, + '/violates [\w ]+ constraint/' + => MDB2_ERROR_CONSTRAINT, + '/referential integrity violation/' + => MDB2_ERROR_CONSTRAINT, + '/more expressions than target columns/i' + => MDB2_ERROR_VALUE_COUNT_ON_ROW, + ); + } + if (is_numeric($error) && $error < 0) { + $error_code = $error; + } else { + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $native_msg)) { + $error_code = $code; + break; + } + } + } + return array($error_code, null, $native_msg); + } + + // }}} + // {{{ escape() + + /** + * Quotes a string so it can be safely used in a query. It will quote + * the text so it can safely be used within a query. + * + * @param string the input string to quote + * @param bool escape wildcards + * + * @return string quoted string + * + * @access public + */ + function escape($text, $escape_wildcards = false) + { + if ($escape_wildcards) { + $text = $this->escapePattern($text); + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + if (is_resource($connection) && version_compare(PHP_VERSION, '5.2.0RC5', '>=')) { + $text = @pg_escape_string($connection, $text); + } else { + $text = @pg_escape_string($text); + } + return $text; + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!is_null($savepoint)) { + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'savepoint cannot be released when changes are auto committed', __FUNCTION__); + } + $query = 'SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + if (!$this->destructor_registered && $this->opened_persistent) { + $this->destructor_registered = true; + register_shutdown_function('MDB2_closeOpenTransactions'); + } + $result =& $this->_doQuery('BEGIN', true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = true; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + $query = 'RELEASE SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + $result =& $this->_doQuery('COMMIT', true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ rollback() + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + $query = 'ROLLBACK TO SAVEPOINT '.$savepoint; + return $this->_doQuery($query, true); + } + + $query = 'ROLLBACK'; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ function setTransactionIsolation() + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + switch ($isolation) { + case 'READ UNCOMMITTED': + case 'READ COMMITTED': + case 'REPEATABLE READ': + case 'SERIALIZABLE': + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level is not supported: '.$isolation, __FUNCTION__); + } + + $query = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL $isolation"; + return $this->_doQuery($query, true); + } + + // }}} + // {{{ _doConnect() + + /** + * Do the grunt work of connecting to the database + * + * @return mixed connection resource on success, MDB2 Error Object on failure + * @access protected + */ + function _doConnect($username, $password, $database_name, $persistent = false) + { + if (!PEAR::loadExtension($this->phptype)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + if ($database_name == '') { + $database_name = 'template1'; + } + + $protocol = $this->dsn['protocol'] ? $this->dsn['protocol'] : 'tcp'; + + $params = array(''); + if ($protocol == 'tcp') { + if ($this->dsn['hostspec']) { + $params[0].= 'host=' . $this->dsn['hostspec']; + } + if ($this->dsn['port']) { + $params[0].= ' port=' . $this->dsn['port']; + } + } elseif ($protocol == 'unix') { + // Allow for pg socket in non-standard locations. + if ($this->dsn['socket']) { + $params[0].= 'host=' . $this->dsn['socket']; + } + if ($this->dsn['port']) { + $params[0].= ' port=' . $this->dsn['port']; + } + } + if ($database_name) { + $params[0].= ' dbname=\'' . addslashes($database_name) . '\''; + } + if ($username) { + $params[0].= ' user=\'' . addslashes($username) . '\''; + } + if ($password) { + $params[0].= ' password=\'' . addslashes($password) . '\''; + } + if (!empty($this->dsn['options'])) { + $params[0].= ' options=' . $this->dsn['options']; + } + if (!empty($this->dsn['tty'])) { + $params[0].= ' tty=' . $this->dsn['tty']; + } + if (!empty($this->dsn['connect_timeout'])) { + $params[0].= ' connect_timeout=' . $this->dsn['connect_timeout']; + } + if (!empty($this->dsn['sslmode'])) { + $params[0].= ' sslmode=' . $this->dsn['sslmode']; + } + if (!empty($this->dsn['service'])) { + $params[0].= ' service=' . $this->dsn['service']; + } + + if (!empty($this->dsn['new_link']) + && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)) + { + if (version_compare(phpversion(), '4.3.0', '>=')) { + $params[] = PGSQL_CONNECT_FORCE_NEW; + } + } + + $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; + $connection = @call_user_func_array($connect_function, $params); + if (!$connection) { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__); + } + + if (empty($this->dsn['disable_iso_date'])) { + if (!@pg_query($connection, "SET SESSION DATESTYLE = 'ISO'")) { + return $this->raiseError(null, null, null, + 'Unable to set date style to iso', __FUNCTION__); + } + } + + if (!empty($this->dsn['charset'])) { + $result = $this->setCharset($this->dsn['charset'], $connection); + if (PEAR::isError($result)) { + return $result; + } + } + + return $connection; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return true on success, MDB2 Error Object on failure + * @access public + */ + function connect() + { + if (is_resource($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 + if (MDB2::areEquals($this->connected_dsn, $this->dsn) + && $this->connected_database_name == $this->database_name + && ($this->opened_persistent == $this->options['persistent']) + ) { + return MDB2_OK; + } + $this->disconnect(false); + } + + if ($this->database_name) { + $connection = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->database_name, + $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $this->connection = $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = $this->database_name; + $this->opened_persistent = $this->options['persistent']; + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + } + + return MDB2_OK; + } + + // }}} + // {{{ setCharset() + + /** + * Set the charset on the current connection + * + * @param string charset + * @param resource connection handle + * + * @return true on success, MDB2 Error Object on failure + */ + function setCharset($charset, $connection = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + if (is_array($charset)) { + $charset = array_shift($charset); + $this->warnings[] = 'postgresql does not support setting client collation'; + } + $result = @pg_set_client_encoding($connection, $charset); + if ($result == -1) { + return $this->raiseError(null, null, null, + 'Unable to set client charset: '.$charset, __FUNCTION__); + } + return MDB2_OK; + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $res = $this->_doConnect($this->dsn['username'], + $this->dsn['password'], + $this->escape($name), + $this->options['persistent']); + if (!PEAR::isError($res)) { + return true; + } + + return false; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_resource($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if (!$this->opened_persistent || $force) { + @pg_close($this->connection); + } + } + return parent::disconnect($force); + } + + // }}} + // {{{ standaloneQuery() + + /** + * execute a query as DBA + * + * @param string $query the SQL query + * @param mixed $types array that contains the types of the columns in + * the result set + * @param boolean $is_manip if the query is a manipulation query + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function &standaloneQuery($query, $types = null, $is_manip = false) + { + $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; + $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; + $connection = $this->_doConnect($user, $pass, $this->database_name, $this->options['persistent']); + if (PEAR::isError($connection)) { + return $connection; + } + + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + + $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); + if (!PEAR::isError($result)) { + if ($is_manip) { + $result = $this->_affectedRows($connection, $result); + } else { + $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset); + } + } + + @pg_close($connection); + return $result; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->options['disable_query']) { + $result = $is_manip ? 0 : null; + return $result; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + + $function = $this->options['multi_query'] ? 'pg_send_query' : 'pg_query'; + $result = @$function($connection, $query); + if (!$result) { + $err =& $this->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } elseif ($this->options['multi_query']) { + if (!($result = @pg_get_result($connection))) { + $err =& $this->raiseError(null, null, null, + 'Could not get the first result from a multi query', __FUNCTION__); + return $err; + } + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return @pg_affected_rows($result); + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if ($limit > 0 + && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query) + ) { + $query = rtrim($query); + if (substr($query, -1) == ';') { + $query = substr($query, 0, -1); + } + if ($is_manip) { + $query = $this->_modifyManipQuery($query, $limit); + } else { + $query.= " LIMIT $limit OFFSET $offset"; + } + } + return $query; + } + + // }}} + // {{{ _modifyManipQuery() + + /** + * Changes a manip query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param integer $limit limit the number of rows + * @return string modified query + * @access protected + */ + function _modifyManipQuery($query, $limit) + { + $pos = strpos(strtolower($query), 'where'); + $where = $pos ? substr($query, $pos) : ''; + + $manip_clause = '(\bDELETE\b\s+(?:\*\s+)?\bFROM\b|\bUPDATE\b)'; + $from_clause = '([\w\.]+)'; + $where_clause = '(?:(.*)\bWHERE\b\s+(.*))|(.*)'; + $pattern = '/^'. $manip_clause . '\s+' . $from_clause .'(?:\s)*(?:'. $where_clause .')?$/i'; + $matches = preg_match($pattern, $query, $match); + if ($matches) { + $manip = $match[1]; + $from = $match[2]; + $what = (count($matches) == 6) ? $match[5] : $match[3]; + return $manip.' '.$from.' '.$what.' WHERE ctid=(SELECT ctid FROM '.$from.' '.$where.' LIMIT '.$limit.')'; + } + //return error? + return $query; + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + $query = 'SHOW SERVER_VERSION'; + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } else { + $server_info = $this->queryOne($query, 'text'); + if (PEAR::isError($server_info)) { + return $server_info; + } + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native && !PEAR::isError($server_info)) { + $tmp = explode('.', $server_info, 3); + if (empty($tmp[2]) + && isset($tmp[1]) + && preg_match('/(\d+)(.*)/', $tmp[1], $tmp2) + ) { + $server_info = array( + 'major' => $tmp[0], + 'minor' => $tmp2[1], + 'patch' => null, + 'extra' => $tmp2[2], + 'native' => $server_info, + ); + } else { + $server_info = array( + 'major' => isset($tmp[0]) ? $tmp[0] : null, + 'minor' => isset($tmp[1]) ? $tmp[1] : null, + 'patch' => isset($tmp[2]) ? $tmp[2] : null, + 'extra' => null, + 'native' => $server_info, + ); + } + } + return $server_info; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * With some database backends, this is emulated. + * prepare() requires a generic query as string like + * 'INSERT INTO numbers VALUES(?,?)' or + * 'INSERT INTO numbers VALUES(:foo,:bar)'. + * The ? and :name and are placeholders which can be set using + * bindParam() and the query can be sent off using the execute() method. + * The allowed format for :name can be set with the 'bindname_format' option. + * + * @param string $query the query to prepare + * @param mixed $types array that contains the types of the placeholders + * @param mixed $result_types array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders + * @return mixed resource handle for the prepared query on success, a MDB2 + * error on failure + * @access public + * @see bindParam, execute + */ + function &prepare($query, $types = null, $result_types = null, $lobs = array()) + { + if ($this->options['emulate_prepared']) { + $obj =& parent::prepare($query, $types, $result_types, $lobs); + return $obj; + } + $is_manip = ($result_types === MDB2_PREPARE_MANIP); + $offset = $this->offset; + $limit = $this->limit; + $this->offset = $this->limit = 0; + $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + $pgtypes = function_exists('pg_prepare') ? false : array(); + if ($pgtypes !== false && !empty($types)) { + $this->loadModule('Datatype', null, true); + } + $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); + $placeholder_type_guess = $placeholder_type = null; + $question = '?'; + $colon = ':'; + $positions = array(); + $position = $parameter = 0; + while ($position < strlen($query)) { + $q_position = strpos($query, $question, $position); + $c_position = strpos($query, $colon, $position); + //skip "::type" cast ("select id::varchar(20) from sometable where name=?") + $doublecolon_position = strpos($query, '::', $position); + if ($doublecolon_position !== false && $doublecolon_position == $c_position) { + $c_position = strpos($query, $colon, $position+2); + } + if ($q_position && $c_position) { + $p_position = min($q_position, $c_position); + } elseif ($q_position) { + $p_position = $q_position; + } elseif ($c_position) { + $p_position = $c_position; + } else { + break; + } + if (is_null($placeholder_type)) { + $placeholder_type_guess = $query[$p_position]; + } + + $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position); + if (PEAR::isError($new_pos)) { + return $new_pos; + } + if ($new_pos != $position) { + $position = $new_pos; + continue; //evaluate again starting from the new position + } + + if ($query[$position] == $placeholder_type_guess) { + if (is_null($placeholder_type)) { + $placeholder_type = $query[$p_position]; + $question = $colon = $placeholder_type; + if (!empty($types) && is_array($types)) { + if ($placeholder_type == ':') { + } else { + $types = array_values($types); + } + } + } + if ($placeholder_type_guess == '?') { + $length = 1; + $name = $parameter; + } else { + $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s'; + $param = preg_replace($regexp, '\\1', $query); + if ($param === '') { + $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'named parameter name must match "bindname_format" option', __FUNCTION__); + return $err; + } + $length = strlen($param) + 1; + $name = $param; + } + if ($pgtypes !== false) { + if (is_array($types) && array_key_exists($name, $types)) { + $pgtypes[] = $this->datatype->mapPrepareDatatype($types[$name]); + } elseif (is_array($types) && array_key_exists($parameter, $types)) { + $pgtypes[] = $this->datatype->mapPrepareDatatype($types[$parameter]); + } else { + $pgtypes[] = 'text'; + } + } + if (($key_parameter = array_search($name, $positions))) { + $next_parameter = 1; + foreach ($positions as $key => $value) { + if ($key_parameter == $key) { + break; + } + ++$next_parameter; + } + } else { + ++$parameter; + $next_parameter = $parameter; + $positions[] = $name; + } + $query = substr_replace($query, '$'.$parameter, $position, $length); + $position = $p_position + strlen($parameter); + } else { + $position = $p_position; + } + } + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + static $prep_statement_counter = 1; + $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); + $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); + if ($pgtypes === false) { + $result = @pg_prepare($connection, $statement_name, $query); + if (!$result) { + $err =& $this->raiseError(null, null, null, + 'Unable to create prepared statement handle', __FUNCTION__); + return $err; + } + } else { + $types_string = ''; + if ($pgtypes) { + $types_string = ' ('.implode(', ', $pgtypes).') '; + } + $query = 'PREPARE '.$statement_name.$types_string.' AS '.$query; + $statement =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($statement)) { + return $statement; + } + } + + $class_name = 'MDB2_Statement_'.$this->phptype; + $obj = new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset); + $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj)); + return $obj; + } + + // }}} + // {{{ function getSequenceName($sqn) + + /** + * adds sequence name formatting to a sequence name + * + * @param string name of the sequence + * + * @return string formatted sequence name + * + * @access public + */ + function getSequenceName($sqn) + { + if (false === $this->options['disable_smart_seqname']) { + if (strpos($sqn, '_') !== false) { + list($table, $field) = explode('_', $sqn, 2); + } + $schema_list = $this->queryOne("SELECT array_to_string(current_schemas(false), ',')"); + if (PEAR::isError($schema_list) || empty($schema_list) || count($schema_list) < 2) { + $order_by = ' a.attnum'; + $schema_clause = ' AND n.nspname=current_schema()'; + } else { + $schemas = explode(',', $schema_list); + $schema_clause = ' AND n.nspname IN ('.$schema_list.')'; + $counter = 1; + $order_by = ' CASE '; + foreach ($schemas as $schema) { + $order_by .= ' WHEN n.nspname='.$schema.' THEN '.$counter++; + } + $order_by .= ' ELSE '.$counter.' END, a.attnum'; + } + + $query = "SELECT substring((SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128) + FROM pg_attrdef d + WHERE d.adrelid = a.attrelid + AND d.adnum = a.attnum + AND a.atthasdef + ) FROM 'nextval[^'']*''([^'']*)') + FROM pg_attribute a + LEFT JOIN pg_class c ON c.oid = a.attrelid + LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef + LEFT JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE (c.relname = ".$this->quote($sqn, 'text'); + if (!empty($field)) { + $query .= " OR (c.relname = ".$this->quote($table, 'text')." AND a.attname = ".$this->quote($field, 'text').")"; + } + $query .= " )" + .$schema_clause." + AND NOT a.attisdropped + AND a.attnum > 0 + AND pg_get_expr(d.adbin, d.adrelid) LIKE 'nextval%' + ORDER BY ".$order_by; + $seqname = $this->queryOne($query); + if (!PEAR::isError($seqname) && !empty($seqname) && is_string($seqname)) { + return $seqname; + } + } + + return sprintf($this->options['seqname_format'], + preg_replace('/[^\w\$.]/i', '_', $sqn)); + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $query = "SELECT NEXTVAL('$sequence_name')"; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError(MDB2_ERROR_NOSUCHTABLE); + $result = $this->queryOne($query, 'integer'); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $this->raiseError($result, null, null, + 'on demand sequence could not be created', __FUNCTION__); + } + return $this->nextId($seq_name, false); + } + } + return $result; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + if (empty($table) && empty($field)) { + return $this->queryOne('SELECT lastval()', 'integer'); + } + $seq = $table.(empty($field) ? '' : '_'.$field); + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true); + return $this->queryOne("SELECT currval('$sequence_name')", 'integer'); + } + + // }}} + // {{{ currID() + + /** + * Returns the current id of a sequence + * + * @param string $seq_name name of the sequence + * @return mixed MDB2 Error Object or id + * @access public + */ + function currID($seq_name) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + return $this->queryOne("SELECT last_value FROM $sequence_name", 'integer'); + } +} + +/** + * MDB2 PostGreSQL result driver + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_Result_pgsql extends MDB2_Result_Common +{ + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $row = @pg_fetch_array($this->result, null, PGSQL_ASSOC); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + $row = @pg_fetch_row($this->result); + } + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_name = @pg_field_name($this->result, $column); + $columns[$column_name] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @access public + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + */ + function numCols() + { + $cols = @pg_num_fields($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + return $cols; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal result pointer to the next available result + * + * @return true on success, false if there is no more result set or an error object on failure + * @access public + */ + function nextResult() + { + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + if (!($this->result = @pg_get_result($connection))) { + return false; + } + return MDB2_OK; + } + + // }}} + // {{{ free() + + /** + * Free the internal resources associated with result. + * + * @return boolean true on success, false if result is invalid + * @access public + */ + function free() + { + if (is_resource($this->result) && $this->db->connection) { + $free = @pg_free_result($this->result); + if ($free === false) { + return $this->db->raiseError(null, null, null, + 'Could not free result', __FUNCTION__); + } + } + $this->result = false; + return MDB2_OK; + } +} + +/** + * MDB2 PostGreSQL buffered result driver + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql +{ + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if ($this->rownum != ($rownum - 1) && !@pg_result_seek($this->result, $rownum)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return MDB2_OK; + } + return $this->db->raiseError(MDB2_ERROR_INVALID, null, null, + 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + $numrows = $this->numRows(); + if (PEAR::isError($numrows)) { + return $numrows; + } + return $this->rownum < ($numrows - 1); + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + $rows = @pg_num_rows($this->result); + if (is_null($rows)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + return $this->db->raiseError(null, null, null, + 'Could not get row count', __FUNCTION__); + } + return $rows; + } +} + +/** + * MDB2 PostGreSQL statement driver + * + * @package MDB2 + * @category Database + * @author Paul Cooper + */ +class MDB2_Statement_pgsql extends MDB2_Statement_Common +{ + // {{{ _execute() + + /** + * Execute a prepared query statement helper method. + * + * @param mixed $result_class string which specifies which result class to use + * @param mixed $result_wrap_class string which specifies which class to wrap results in + * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure + * @access private + */ + function &_execute($result_class = true, $result_wrap_class = false) + { + if (is_null($this->statement)) { + $result =& parent::_execute($result_class, $result_wrap_class); + return $result; + } + $this->db->last_query = $this->query; + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values)); + if ($this->db->getOption('disable_query')) { + $result = $this->is_manip ? 0 : null; + return $result; + } + + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $query = false; + $parameters = array(); + // todo: disabled until pg_execute() bytea issues are cleared up + if (true || !function_exists('pg_execute')) { + $query = 'EXECUTE '.$this->statement; + } + if (!empty($this->positions)) { + foreach ($this->positions as $parameter) { + if (!array_key_exists($parameter, $this->values)) { + return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__); + } + $value = $this->values[$parameter]; + $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null; + if (is_resource($value) || $type == 'clob' || $type == 'blob' || $this->db->options['lob_allow_url_include']) { + if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) { + if ($match[1] == 'file://') { + $value = $match[2]; + } + $value = @fopen($value, 'r'); + $close = true; + } + if (is_resource($value)) { + $data = ''; + while (!@feof($value)) { + $data.= @fread($value, $this->db->options['lob_buffer_length']); + } + if ($close) { + @fclose($value); + } + $value = $data; + } + } + $quoted = $this->db->quote($value, $type, $query); + if (PEAR::isError($quoted)) { + return $quoted; + } + $parameters[] = $quoted; + } + if ($query) { + $query.= ' ('.implode(', ', $parameters).')'; + } + } + + if (!$query) { + $result = @pg_execute($connection, $this->statement, $parameters); + if (!$result) { + $err =& $this->db->raiseError(null, null, null, + 'Unable to execute statement', __FUNCTION__); + return $err; + } + } else { + $result = $this->db->_doQuery($query, $this->is_manip, $connection); + if (PEAR::isError($result)) { + return $result; + } + } + + if ($this->is_manip) { + $affected_rows = $this->db->_affectedRows($connection, $result); + return $affected_rows; + } + + $result =& $this->db->_wrapResult($result, $this->result_types, + $result_class, $result_wrap_class, $this->limit, $this->offset); + $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ free() + + /** + * Release resources allocated for the specified prepared query. + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function free() + { + if (is_null($this->positions)) { + return $this->db->raiseError(MDB2_ERROR, null, null, + 'Prepared statement has already been freed', __FUNCTION__); + } + $result = MDB2_OK; + + if (!is_null($this->statement)) { + $connection = $this->db->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $query = 'DEALLOCATE PREPARE '.$this->statement; + $result = $this->db->_doQuery($query, true, $connection); + } + + parent::free(); + return $result; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Driver/sqlite.php b/lib/Pear/MDB2/Driver/sqlite.php new file mode 100644 index 0000000..e48bac3 --- /dev/null +++ b/lib/Pear/MDB2/Driver/sqlite.php @@ -0,0 +1,1103 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: sqlite.php,v 1.158 2008/03/08 14:18:39 quipo Exp $ +// + +/** + * MDB2 SQLite driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_sqlite extends MDB2_Driver_Common +{ + // {{{ properties + var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => false); + + var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"'); + + var $_lasterror = ''; + + var $fix_assoc_fields_names = false; + + // }}} + // {{{ constructor + + /** + * Constructor + */ + function __construct() + { + parent::__construct(); + + $this->phptype = 'sqlite'; + $this->dbsyntax = 'sqlite'; + + $this->supported['sequences'] = 'emulated'; + $this->supported['indexes'] = true; + $this->supported['affected_rows'] = true; + $this->supported['summary_functions'] = true; + $this->supported['order_by_text'] = true; + $this->supported['current_id'] = 'emulated'; + $this->supported['limit_queries'] = true; + $this->supported['LOBs'] = true; + $this->supported['replace'] = true; + $this->supported['transactions'] = true; + $this->supported['savepoints'] = false; + $this->supported['sub_selects'] = true; + $this->supported['triggers'] = true; + $this->supported['auto_increment'] = true; + $this->supported['primary_key'] = false; // requires alter table implementation + $this->supported['result_introspection'] = false; // not implemented + $this->supported['prepared_statements'] = 'emulated'; + $this->supported['identifier_quoting'] = true; + $this->supported['pattern_escaping'] = false; + $this->supported['new_link'] = false; + + $this->options['DBA_username'] = false; + $this->options['DBA_password'] = false; + $this->options['base_transaction_name'] = '___php_MDB2_sqlite_auto_commit_off'; + $this->options['fixed_float'] = 0; + $this->options['database_path'] = ''; + $this->options['database_extension'] = ''; + $this->options['server_version'] = ''; + $this->options['max_identifiers_length'] = 128; //no real limit + } + + // }}} + // {{{ errorInfo() + + /** + * This method is used to collect information about an error + * + * @param integer $error + * @return array + * @access public + */ + function errorInfo($error = null) + { + $native_code = null; + if ($this->connection) { + $native_code = @sqlite_last_error($this->connection); + } + $native_msg = $this->_lasterror + ? html_entity_decode($this->_lasterror) : @sqlite_error_string($native_code); + + // PHP 5.2+ prepends the function name to $php_errormsg, so we need + // this hack to work around it, per bug #9599. + $native_msg = preg_replace('/^sqlite[a-z_]+\(\)[^:]*: /', '', $native_msg); + + if (is_null($error)) { + static $error_regexps; + if (empty($error_regexps)) { + $error_regexps = array( + '/^no such table:/' => MDB2_ERROR_NOSUCHTABLE, + '/^no such index:/' => MDB2_ERROR_NOT_FOUND, + '/^(table|index) .* already exists$/' => MDB2_ERROR_ALREADY_EXISTS, + '/PRIMARY KEY must be unique/i' => MDB2_ERROR_CONSTRAINT, + '/is not unique/' => MDB2_ERROR_CONSTRAINT, + '/columns .* are not unique/i' => MDB2_ERROR_CONSTRAINT, + '/uniqueness constraint failed/' => MDB2_ERROR_CONSTRAINT, + '/may not be NULL/' => MDB2_ERROR_CONSTRAINT_NOT_NULL, + '/^no such column:/' => MDB2_ERROR_NOSUCHFIELD, + '/no column named/' => MDB2_ERROR_NOSUCHFIELD, + '/column not present in both tables/i' => MDB2_ERROR_NOSUCHFIELD, + '/^near ".*": syntax error$/' => MDB2_ERROR_SYNTAX, + '/[0-9]+ values for [0-9]+ columns/i' => MDB2_ERROR_VALUE_COUNT_ON_ROW, + ); + } + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $native_msg)) { + $error = $code; + break; + } + } + } + return array($error, $native_code, $native_msg); + } + + // }}} + // {{{ escape() + + /** + * Quotes a string so it can be safely used in a query. It will quote + * the text so it can safely be used within a query. + * + * @param string the input string to quote + * @param bool escape wildcards + * + * @return string quoted string + * + * @access public + */ + function escape($text, $escape_wildcards = false) + { + $text = @sqlite_escape_string($text); + return $text; + } + + // }}} + // {{{ beginTransaction() + + /** + * Start a transaction or set a savepoint. + * + * @param string name of a savepoint to set + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function beginTransaction($savepoint = null) + { + $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!is_null($savepoint)) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } elseif ($this->in_transaction) { + return MDB2_OK; //nothing to do + } + if (!$this->destructor_registered && $this->opened_persistent) { + $this->destructor_registered = true; + register_shutdown_function('MDB2_closeOpenTransactions'); + } + $query = 'BEGIN TRANSACTION '.$this->options['base_transaction_name']; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = true; + return MDB2_OK; + } + + // }}} + // {{{ commit() + + /** + * Commit the database changes done during a transaction that is in + * progress or release a savepoint. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after committing the pending changes. + * + * @param string name of a savepoint to release + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function commit($savepoint = null) + { + $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + + $query = 'COMMIT TRANSACTION '.$this->options['base_transaction_name']; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ + + /** + * Cancel any database changes done during a transaction or since a specific + * savepoint that is in progress. This function may only be called when + * auto-committing is disabled, otherwise it will fail. Therefore, a new + * transaction is implicitly started after canceling the pending changes. + * + * @param string name of a savepoint to rollback to + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + */ + function rollback($savepoint = null) + { + $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint)); + if (!$this->in_transaction) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'rollback cannot be done changes are auto committed', __FUNCTION__); + } + if (!is_null($savepoint)) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'savepoints are not supported', __FUNCTION__); + } + + $query = 'ROLLBACK TRANSACTION '.$this->options['base_transaction_name']; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + return $result; + } + $this->in_transaction = false; + return MDB2_OK; + } + + // }}} + // {{{ function setTransactionIsolation() + + /** + * Set the transacton isolation level. + * + * @param string standard isolation level + * READ UNCOMMITTED (allows dirty reads) + * READ COMMITTED (prevents dirty reads) + * REPEATABLE READ (prevents nonrepeatable reads) + * SERIALIZABLE (prevents phantom reads) + * @return mixed MDB2_OK on success, a MDB2 error on failure + * + * @access public + * @since 2.1.1 + */ + function setTransactionIsolation($isolation) + { + $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); + switch ($isolation) { + case 'READ UNCOMMITTED': + $isolation = 0; + break; + case 'READ COMMITTED': + case 'REPEATABLE READ': + case 'SERIALIZABLE': + $isolation = 1; + break; + default: + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'isolation level is not supported: '.$isolation, __FUNCTION__); + } + + $query = "PRAGMA read_uncommitted=$isolation"; + return $this->_doQuery($query, true); + } + + // }}} + // {{{ getDatabaseFile() + + /** + * Builds the string with path+dbname+extension + * + * @return string full database path+file + * @access protected + */ + function _getDatabaseFile($database_name) + { + if ($database_name === '' || $database_name === ':memory:') { + return $database_name; + } + return $this->options['database_path'].$database_name.$this->options['database_extension']; + } + + // }}} + // {{{ connect() + + /** + * Connect to the database + * + * @return true on success, MDB2 Error Object on failure + **/ + function connect() + { + $database_file = $this->_getDatabaseFile($this->database_name); + if (is_resource($this->connection)) { + //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 + if (MDB2::areEquals($this->connected_dsn, $this->dsn) + && $this->connected_database_name == $database_file + && $this->opened_persistent == $this->options['persistent'] + ) { + return MDB2_OK; + } + $this->disconnect(false); + } + + if (!PEAR::loadExtension($this->phptype)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); + } + + if (!empty($this->database_name)) { + if ($database_file !== ':memory:') { + if (!file_exists($database_file)) { + if (!touch($database_file)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Could not create database file', __FUNCTION__); + } + if (!isset($this->dsn['mode']) + || !is_numeric($this->dsn['mode']) + ) { + $mode = 0644; + } else { + $mode = octdec($this->dsn['mode']); + } + if (!chmod($database_file, $mode)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Could not be chmodded database file', __FUNCTION__); + } + if (!file_exists($database_file)) { + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + 'Could not be found database file', __FUNCTION__); + } + } + if (!is_file($database_file)) { + return $this->raiseError(MDB2_ERROR_INVALID, null, null, + 'Database is a directory name', __FUNCTION__); + } + if (!is_readable($database_file)) { + return $this->raiseError(MDB2_ERROR_ACCESS_VIOLATION, null, null, + 'Could not read database file', __FUNCTION__); + } + } + + $connect_function = ($this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open'); + $php_errormsg = ''; + if (version_compare('5.1.0', PHP_VERSION, '>')) { + @ini_set('track_errors', true); + $connection = @$connect_function($database_file); + @ini_restore('track_errors'); + } else { + $connection = @$connect_function($database_file, 0666, $php_errormsg); + } + $this->_lasterror = $php_errormsg; + if (!$connection) { + return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, + 'unable to establish a connection', __FUNCTION__); + } + + if (!empty($this->dsn['charset'])) { + $result = $this->setCharset($this->dsn['charset'], $connection); + if (PEAR::isError($result)) { + return $result; + } + } + + $this->connection = $connection; + $this->connected_dsn = $this->dsn; + $this->connected_database_name = $database_file; + $this->opened_persistent = $this->getoption('persistent'); + $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; + } + return MDB2_OK; + } + + // }}} + // {{{ databaseExists() + + /** + * check if given database name is exists? + * + * @param string $name name of the database that should be checked + * + * @return mixed true/false on success, a MDB2 error on failure + * @access public + */ + function databaseExists($name) + { + $database_file = $this->_getDatabaseFile($name); + $result = file_exists($database_file); + return $result; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @param boolean $force if the disconnect should be forced even if the + * connection is opened persistently + * @return mixed true on success, false if not connected and error + * object on error + * @access public + */ + function disconnect($force = true) + { + if (is_resource($this->connection)) { + if ($this->in_transaction) { + $dsn = $this->dsn; + $database_name = $this->database_name; + $persistent = $this->options['persistent']; + $this->dsn = $this->connected_dsn; + $this->database_name = $this->connected_database_name; + $this->options['persistent'] = $this->opened_persistent; + $this->rollback(); + $this->dsn = $dsn; + $this->database_name = $database_name; + $this->options['persistent'] = $persistent; + } + + if (!$this->opened_persistent || $force) { + @sqlite_close($this->connection); + } + } + return parent::disconnect($force); + } + + // }}} + // {{{ getConnection() + + /** + * Returns a native connection + * + * @return mixed a valid MDB2 connection object, + * or a MDB2 error object on error + * @access public + */ + function getConnection() + { + $connection = parent::getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $fix_assoc_fields_names = $this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES; + if ($fix_assoc_fields_names !== $this->fix_assoc_fields_names) { + @sqlite_query("PRAGMA short_column_names = $fix_assoc_fields_names;", $connection); + $this->fix_assoc_fields_names = $fix_assoc_fields_names; + } + + return $connection; + } + + // }}} + // {{{ _doQuery() + + /** + * Execute a query + * @param string $query query + * @param boolean $is_manip if the query is a manipulation query + * @param resource $connection + * @param string $database_name + * @return result or error object + * @access protected + */ + function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null) + { + $this->last_query = $query; + $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre')); + if ($result) { + if (PEAR::isError($result)) { + return $result; + } + $query = $result; + } + if ($this->options['disable_query']) { + $result = $is_manip ? 0 : null; + return $result; + } + + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + + $function = $this->options['result_buffering'] + ? 'sqlite_query' : 'sqlite_unbuffered_query'; + $php_errormsg = ''; + if (version_compare('5.1.0', PHP_VERSION, '>')) { + @ini_set('track_errors', true); + do { + $result = @$function($query.';', $connection); + } while (sqlite_last_error($connection) == SQLITE_SCHEMA); + @ini_restore('track_errors'); + } else { + do { + $result = @$function($query.';', $connection, SQLITE_BOTH, $php_errormsg); + } while (sqlite_last_error($connection) == SQLITE_SCHEMA); + } + $this->_lasterror = $php_errormsg; + + if (!$result) { + $err =& $this->raiseError(null, null, null, + 'Could not execute statement', __FUNCTION__); + return $err; + } + + $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result)); + return $result; + } + + // }}} + // {{{ _affectedRows() + + /** + * Returns the number of rows affected + * + * @param resource $result + * @param resource $connection + * @return mixed MDB2 Error Object or the number of rows affected + * @access private + */ + function _affectedRows($connection, $result = null) + { + if (is_null($connection)) { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + } + return @sqlite_changes($connection); + } + + // }}} + // {{{ _modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param boolean $is_manip if it is a DML query + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string modified query + * @access protected + */ + function _modifyQuery($query, $is_manip, $limit, $offset) + { + if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) { + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { + $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', + 'DELETE FROM \1 WHERE 1=1', $query); + } + } + if ($limit > 0 + && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query) + ) { + $query = rtrim($query); + if (substr($query, -1) == ';') { + $query = substr($query, 0, -1); + } + if ($is_manip) { + $query.= " LIMIT $limit"; + } else { + $query.= " LIMIT $offset,$limit"; + } + } + return $query; + } + + // }}} + // {{{ getServerVersion() + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return mixed array/string with version information or MDB2 error object + * @access public + */ + function getServerVersion($native = false) + { + $server_info = false; + if ($this->connected_server_info) { + $server_info = $this->connected_server_info; + } elseif ($this->options['server_version']) { + $server_info = $this->options['server_version']; + } elseif (function_exists('sqlite_libversion')) { + $server_info = @sqlite_libversion(); + } + if (!$server_info) { + return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'Requires either the "server_version" option or the sqlite_libversion() function', __FUNCTION__); + } + // cache server_info + $this->connected_server_info = $server_info; + if (!$native) { + $tmp = explode('.', $server_info, 3); + $server_info = array( + 'major' => isset($tmp[0]) ? $tmp[0] : null, + 'minor' => isset($tmp[1]) ? $tmp[1] : null, + 'patch' => isset($tmp[2]) ? $tmp[2] : null, + 'extra' => null, + 'native' => $server_info, + ); + } + return $server_info; + } + + // }}} + // {{{ replace() + + /** + * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT + * query, except that if there is already a row in the table with the same + * key field values, the REPLACE query just updates its values instead of + * inserting a new row. + * + * The REPLACE type of query does not make part of the SQL standards. Since + * practically only SQLite implements it natively, this type of query is + * emulated through this method for other DBMS using standard types of + * queries inside a transaction to assure the atomicity of the operation. + * + * @access public + * + * @param string $table name of the table on which the REPLACE query will + * be executed. + * @param array $fields associative array that describes the fields and the + * values that will be inserted or updated in the specified table. The + * indexes of the array are the names of all the fields of the table. The + * values of the array are also associative arrays that describe the + * values and other properties of the table fields. + * + * Here follows a list of field properties that need to be specified: + * + * value: + * Value to be assigned to the specified field. This value may be + * of specified in database independent type format as this + * function can perform the necessary datatype conversions. + * + * Default: + * this property is required unless the Null property + * is set to 1. + * + * type + * Name of the type of the field. Currently, all types Metabase + * are supported except for clob and blob. + * + * Default: no type conversion + * + * null + * Boolean property that indicates that the value for this field + * should be set to null. + * + * The default value for fields missing in INSERT queries may be + * specified the definition of a table. Often, the default value + * is already null, but since the REPLACE may be emulated using + * an UPDATE query, make sure that all fields of the table are + * listed in this function argument array. + * + * Default: 0 + * + * key + * Boolean property that indicates that this field should be + * handled as a primary key or at least as part of the compound + * unique index of the table that will determine the row that will + * updated if it exists or inserted a new row otherwise. + * + * This function will fail if no key field is specified or if the + * value of a key field is set to null because fields that are + * part of unique index they may not be null. + * + * Default: 0 + * + * @return mixed MDB2_OK on success, a MDB2 error on failure + */ + function replace($table, $fields) + { + $count = count($fields); + $query = $values = ''; + $keys = $colnum = 0; + for (reset($fields); $colnum < $count; next($fields), $colnum++) { + $name = key($fields); + if ($colnum > 0) { + $query .= ','; + $values.= ','; + } + $query.= $this->quoteIdentifier($name, true); + if (isset($fields[$name]['null']) && $fields[$name]['null']) { + $value = 'NULL'; + } else { + $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null; + $value = $this->quote($fields[$name]['value'], $type); + if (PEAR::isError($value)) { + return $value; + } + } + $values.= $value; + if (isset($fields[$name]['key']) && $fields[$name]['key']) { + if ($value === 'NULL') { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'key value '.$name.' may not be NULL', __FUNCTION__); + } + $keys++; + } + } + if ($keys == 0) { + return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null, + 'not specified which fields are keys', __FUNCTION__); + } + + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + + $table = $this->quoteIdentifier($table, true); + $query = "REPLACE INTO $table ($query) VALUES ($values)"; + $result =& $this->_doQuery($query, true, $connection); + if (PEAR::isError($result)) { + return $result; + } + return $this->_affectedRows($connection, $result); + } + + // }}} + // {{{ nextID() + + /** + * Returns the next free id of a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true the sequence is + * automatic created, if it + * not exists + * + * @return mixed MDB2 Error Object or id + * @access public + */ + function nextID($seq_name, $ondemand = true) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->options['seqcol_name']; + $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->expectError(MDB2_ERROR_NOSUCHTABLE); + $result =& $this->_doQuery($query, true); + $this->popExpect(); + $this->popErrorHandling(); + if (PEAR::isError($result)) { + if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { + $this->loadModule('Manager', null, true); + $result = $this->manager->createSequence($seq_name); + if (PEAR::isError($result)) { + return $this->raiseError($result, null, null, + 'on demand sequence '.$seq_name.' could not be created', __FUNCTION__); + } else { + return $this->nextID($seq_name, false); + } + } + return $result; + } + $value = $this->lastInsertID(); + if (is_numeric($value)) { + $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value"; + $result =& $this->_doQuery($query, true); + if (PEAR::isError($result)) { + $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name; + } + } + return $value; + } + + // }}} + // {{{ lastInsertID() + + /** + * Returns the autoincrement ID if supported or $id or fetches the current + * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) + * + * @param string $table name of the table into which a new row was inserted + * @param string $field name of the field into which a new row was inserted + * @return mixed MDB2 Error Object or id + * @access public + */ + function lastInsertID($table = null, $field = null) + { + $connection = $this->getConnection(); + if (PEAR::isError($connection)) { + return $connection; + } + $value = @sqlite_last_insert_rowid($connection); + if (!$value) { + return $this->raiseError(null, null, null, + 'Could not get last insert ID', __FUNCTION__); + } + return $value; + } + + // }}} + // {{{ currID() + + /** + * Returns the current id of a sequence + * + * @param string $seq_name name of the sequence + * @return mixed MDB2 Error Object or id + * @access public + */ + function currID($seq_name) + { + $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); + $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); + $query = "SELECT MAX($seqcol_name) FROM $sequence_name"; + return $this->queryOne($query, 'integer'); + } +} + +/** + * MDB2 SQLite result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Result_sqlite extends MDB2_Result_Common +{ + // }}} + // {{{ fetchRow() + + /** + * Fetch a row and insert the data into an existing array. + * + * @param int $fetchmode how the array data should be indexed + * @param int $rownum number of the row where the data can be found + * @return int data array on success, a MDB2 error on failure + * @access public + */ + function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null) + { + if (!is_null($rownum)) { + $seek = $this->seek($rownum); + if (PEAR::isError($seek)) { + return $seek; + } + } + if ($fetchmode == MDB2_FETCHMODE_DEFAULT) { + $fetchmode = $this->db->fetchmode; + } + if ($fetchmode & MDB2_FETCHMODE_ASSOC) { + $row = @sqlite_fetch_array($this->result, SQLITE_ASSOC); + if (is_array($row) + && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE + ) { + $row = array_change_key_case($row, $this->db->options['field_case']); + } + } else { + $row = @sqlite_fetch_array($this->result, SQLITE_NUM); + } + if (!$row) { + if ($this->result === false) { + $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + return $err; + } + $null = null; + return $null; + } + $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL; + $rtrim = false; + if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) { + if (empty($this->types)) { + $mode += MDB2_PORTABILITY_RTRIM; + } else { + $rtrim = true; + } + } + if ($mode) { + $this->db->_fixResultArrayValues($row, $mode); + } + if (!empty($this->types)) { + $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim); + } + if (!empty($this->values)) { + $this->_assignBindColumns($row); + } + if ($fetchmode === MDB2_FETCHMODE_OBJECT) { + $object_class = $this->db->options['fetch_class']; + if ($object_class == 'stdClass') { + $row = (object) $row; + } else { + $row = &new $object_class($row); + } + } + ++$this->rownum; + return $row; + } + + // }}} + // {{{ _getColumnNames() + + /** + * Retrieve the names of columns returned by the DBMS in a query result. + * + * @return mixed Array variable that holds the names of columns as keys + * or an MDB2 error on failure. + * Some DBMS may not return any columns when the result set + * does not contain any rows. + * @access private + */ + function _getColumnNames() + { + $columns = array(); + $numcols = $this->numCols(); + if (PEAR::isError($numcols)) { + return $numcols; + } + for ($column = 0; $column < $numcols; $column++) { + $column_name = @sqlite_field_name($this->result, $column); + $columns[$column_name] = $column; + } + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $columns = array_change_key_case($columns, $this->db->options['field_case']); + } + return $columns; + } + + // }}} + // {{{ numCols() + + /** + * Count the number of columns returned by the DBMS in a query result. + * + * @access public + * @return mixed integer value with the number of columns, a MDB2 error + * on failure + */ + function numCols() + { + $cols = @sqlite_num_fields($this->result); + if (is_null($cols)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return count($this->types); + } + return $this->db->raiseError(null, null, null, + 'Could not get column count', __FUNCTION__); + } + return $cols; + } +} + +/** + * MDB2 SQLite buffered result driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_BufferedResult_sqlite extends MDB2_Result_sqlite +{ + // {{{ seek() + + /** + * Seek to a specific row in a result set + * + * @param int $rownum number of the row where the data can be found + * @return mixed MDB2_OK on success, a MDB2 error on failure + * @access public + */ + function seek($rownum = 0) + { + if (!@sqlite_seek($this->result, $rownum)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return MDB2_OK; + } + return $this->db->raiseError(MDB2_ERROR_INVALID, null, null, + 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__); + } + $this->rownum = $rownum - 1; + return MDB2_OK; + } + + // }}} + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return mixed true or false on sucess, a MDB2 error on failure + * @access public + */ + function valid() + { + $numrows = $this->numRows(); + if (PEAR::isError($numrows)) { + return $numrows; + } + return $this->rownum < ($numrows - 1); + } + + // }}} + // {{{ numRows() + + /** + * Returns the number of rows in a result object + * + * @return mixed MDB2 Error Object or the number of rows + * @access public + */ + function numRows() + { + $rows = @sqlite_num_rows($this->result); + if (is_null($rows)) { + if ($this->result === false) { + return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'resultset has already been freed', __FUNCTION__); + } elseif (is_null($this->result)) { + return 0; + } + return $this->db->raiseError(null, null, null, + 'Could not get row count', __FUNCTION__); + } + return $rows; + } +} + +/** + * MDB2 SQLite statement driver + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Statement_sqlite extends MDB2_Statement_Common +{ + +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Extended.php b/lib/Pear/MDB2/Extended.php new file mode 100644 index 0000000..7772c58 --- /dev/null +++ b/lib/Pear/MDB2/Extended.php @@ -0,0 +1,721 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Extended.php,v 1.60 2007/11/28 19:49:34 quipo Exp $ + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + */ + +/** + * Used by autoPrepare() + */ +define('MDB2_AUTOQUERY_INSERT', 1); +define('MDB2_AUTOQUERY_UPDATE', 2); +define('MDB2_AUTOQUERY_DELETE', 3); +define('MDB2_AUTOQUERY_SELECT', 4); + +/** + * MDB2_Extended: class which adds several high level methods to MDB2 + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Extended extends MDB2_Module_Common +{ + // {{{ autoPrepare() + + /** + * Generate an insert, update or delete query and call prepare() on it + * + * @param string table + * @param array the fields names + * @param int type of query to build + * MDB2_AUTOQUERY_INSERT + * MDB2_AUTOQUERY_UPDATE + * MDB2_AUTOQUERY_DELETE + * MDB2_AUTOQUERY_SELECT + * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement) + * @param array that contains the types of the placeholders + * @param mixed array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * + * @return resource handle for the query + * @see buildManipSQL + * @access public + */ + function autoPrepare($table, $table_fields, $mode = MDB2_AUTOQUERY_INSERT, + $where = false, $types = null, $result_types = MDB2_PREPARE_MANIP) + { + $query = $this->buildManipSQL($table, $table_fields, $mode, $where); + if (PEAR::isError($query)) { + return $query; + } + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + $lobs = array(); + foreach ((array)$types as $param => $type) { + if (($type == 'clob') || ($type == 'blob')) { + $lobs[$param] = $table_fields[$param]; + } + } + return $db->prepare($query, $types, $result_types, $lobs); + } + + // }}} + // {{{ autoExecute() + + /** + * Generate an insert, update or delete query and call prepare() and execute() on it + * + * @param string name of the table + * @param array assoc ($key=>$value) where $key is a field name and $value its value + * @param int type of query to build + * MDB2_AUTOQUERY_INSERT + * MDB2_AUTOQUERY_UPDATE + * MDB2_AUTOQUERY_DELETE + * MDB2_AUTOQUERY_SELECT + * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement) + * @param array that contains the types of the placeholders + * @param string which specifies which result class to use + * @param mixed array that contains the types of the columns in + * the result set or MDB2_PREPARE_RESULT, if set to + * MDB2_PREPARE_MANIP the query is handled as a manipulation query + * + * @return bool|MDB2_Error true on success, a MDB2 error on failure + * @see buildManipSQL + * @see autoPrepare + * @access public + */ + function &autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT, + $where = false, $types = null, $result_class = true, $result_types = MDB2_PREPARE_MANIP) + { + $fields_values = (array)$fields_values; + if ($mode == MDB2_AUTOQUERY_SELECT) { + if (is_array($result_types)) { + $keys = array_keys($result_types); + } elseif (!empty($fields_values)) { + $keys = $fields_values; + } else { + $keys = array(); + } + } else { + $keys = array_keys($fields_values); + } + $params = array_values($fields_values); + if (empty($params)) { + $query = $this->buildManipSQL($table, $keys, $mode, $where); + + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + if ($mode == MDB2_AUTOQUERY_SELECT) { + $result =& $db->query($query, $result_types, $result_class); + } else { + $result = $db->exec($query); + } + } else { + $stmt = $this->autoPrepare($table, $keys, $mode, $where, $types, $result_types); + if (PEAR::isError($stmt)) { + return $stmt; + } + $result =& $stmt->execute($params, $result_class); + $stmt->free(); + } + return $result; + } + + // }}} + // {{{ buildManipSQL() + + /** + * Make automaticaly an sql query for prepare() + * + * Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), MDB2_AUTOQUERY_INSERT) + * will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) + * NB : - This belongs more to a SQL Builder class, but this is a simple facility + * - Be carefull ! If you don't give a $where param with an UPDATE/DELETE query, all + * the records of the table will be updated/deleted ! + * + * @param string name of the table + * @param ordered array containing the fields names + * @param int type of query to build + * MDB2_AUTOQUERY_INSERT + * MDB2_AUTOQUERY_UPDATE + * MDB2_AUTOQUERY_DELETE + * MDB2_AUTOQUERY_SELECT + * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement) + * + * @return string sql query for prepare() + * @access public + */ + function buildManipSQL($table, $table_fields, $mode, $where = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($db->options['quote_identifier']) { + $table = $db->quoteIdentifier($table); + } + + if (!empty($table_fields) && $db->options['quote_identifier']) { + foreach ($table_fields as $key => $field) { + $table_fields[$key] = $db->quoteIdentifier($field); + } + } + + if ($where !== false && !is_null($where)) { + if (is_array($where)) { + $where = implode(' AND ', $where); + } + $where = ' WHERE '.$where; + } + + switch ($mode) { + case MDB2_AUTOQUERY_INSERT: + if (empty($table_fields)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Insert requires table fields', __FUNCTION__); + } + $cols = implode(', ', $table_fields); + $values = '?'.str_repeat(', ?', (count($table_fields) - 1)); + return 'INSERT INTO '.$table.' ('.$cols.') VALUES ('.$values.')'; + break; + case MDB2_AUTOQUERY_UPDATE: + if (empty($table_fields)) { + return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, + 'Update requires table fields', __FUNCTION__); + } + $set = implode(' = ?, ', $table_fields).' = ?'; + $sql = 'UPDATE '.$table.' SET '.$set.$where; + return $sql; + break; + case MDB2_AUTOQUERY_DELETE: + $sql = 'DELETE FROM '.$table.$where; + return $sql; + break; + case MDB2_AUTOQUERY_SELECT: + $cols = !empty($table_fields) ? implode(', ', $table_fields) : '*'; + $sql = 'SELECT '.$cols.' FROM '.$table.$where; + return $sql; + break; + } + return $db->raiseError(MDB2_ERROR_SYNTAX, null, null, + 'Non existant mode', __FUNCTION__); + } + + // }}} + // {{{ limitQuery() + + /** + * Generates a limited query + * + * @param string query + * @param array that contains the types of the columns in the result set + * @param integer the numbers of rows to fetch + * @param integer the row to start to fetching + * @param string which specifies which result class to use + * @param mixed string which specifies which class to wrap results in + * + * @return MDB2_Result|MDB2_Error result set on success, a MDB2 error on failure + * @access public + */ + function &limitQuery($query, $types, $limit, $offset = 0, $result_class = true, + $result_wrap_class = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $result = $db->setLimit($limit, $offset); + if (PEAR::isError($result)) { + return $result; + } + $result =& $db->query($query, $types, $result_class, $result_wrap_class); + return $result; + } + + // }}} + // {{{ execParam() + + /** + * Execute a parameterized DML statement. + * + * @param string the SQL query + * @param array if supplied, prepare/execute will be used + * with this array as execute parameters + * @param array that contains the types of the values defined in $params + * + * @return int|MDB2_Error affected rows on success, a MDB2 error on failure + * @access public + */ + function execParam($query, $params = array(), $param_types = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + settype($params, 'array'); + if (empty($params)) { + return $db->exec($query); + } + + $stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $result = $stmt->execute($params); + if (PEAR::isError($result)) { + return $result; + } + + $stmt->free(); + return $result; + } + + // }}} + // {{{ getOne() + + /** + * Fetch the first column of the first row of data returned from a query. + * Takes care of doing the query and freeing the results when finished. + * + * @param string the SQL query + * @param string that contains the type of the column in the result set + * @param array if supplied, prepare/execute will be used + * with this array as execute parameters + * @param array that contains the types of the values defined in $params + * @param int|string which column to return + * + * @return scalar|MDB2_Error data on success, a MDB2 error on failure + * @access public + */ + function getOne($query, $type = null, $params = array(), + $param_types = null, $colnum = 0) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + settype($params, 'array'); + settype($type, 'array'); + if (empty($params)) { + return $db->queryOne($query, $type, $colnum); + } + + $stmt = $db->prepare($query, $param_types, $type); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $result = $stmt->execute($params); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $one = $result->fetchOne($colnum); + $stmt->free(); + $result->free(); + return $one; + } + + // }}} + // {{{ getRow() + + /** + * Fetch the first row of data returned from a query. Takes care + * of doing the query and freeing the results when finished. + * + * @param string the SQL query + * @param array that contains the types of the columns in the result set + * @param array if supplied, prepare/execute will be used + * with this array as execute parameters + * @param array that contains the types of the values defined in $params + * @param int the fetch mode to use + * + * @return array|MDB2_Error data on success, a MDB2 error on failure + * @access public + */ + function getRow($query, $types = null, $params = array(), + $param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + settype($params, 'array'); + if (empty($params)) { + return $db->queryRow($query, $types, $fetchmode); + } + + $stmt = $db->prepare($query, $param_types, $types); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $result = $stmt->execute($params); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $row = $result->fetchRow($fetchmode); + $stmt->free(); + $result->free(); + return $row; + } + + // }}} + // {{{ getCol() + + /** + * Fetch a single column from a result set and return it as an + * indexed array. + * + * @param string the SQL query + * @param string that contains the type of the column in the result set + * @param array if supplied, prepare/execute will be used + * with this array as execute parameters + * @param array that contains the types of the values defined in $params + * @param int|string which column to return + * + * @return array|MDB2_Error data on success, a MDB2 error on failure + * @access public + */ + function getCol($query, $type = null, $params = array(), + $param_types = null, $colnum = 0) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + settype($params, 'array'); + settype($type, 'array'); + if (empty($params)) { + return $db->queryCol($query, $type, $colnum); + } + + $stmt = $db->prepare($query, $param_types, $type); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $result = $stmt->execute($params); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $col = $result->fetchCol($colnum); + $stmt->free(); + $result->free(); + return $col; + } + + // }}} + // {{{ getAll() + + /** + * Fetch all the rows returned from a query. + * + * @param string the SQL query + * @param array that contains the types of the columns in the result set + * @param array if supplied, prepare/execute will be used + * with this array as execute parameters + * @param array that contains the types of the values defined in $params + * @param int the fetch mode to use + * @param bool if set to true, the $all will have the first + * column as its first dimension + * @param bool $force_array used only when the query returns exactly + * two columns. If true, the values of the returned array will be + * one-element arrays instead of scalars. + * @param bool $group if true, the values of the returned array is + * wrapped in another array. If the same key value (in the first + * column) repeats itself, the values will be appended to this array + * instead of overwriting the existing values. + * + * @return array|MDB2_Error data on success, a MDB2 error on failure + * @access public + */ + function getAll($query, $types = null, $params = array(), + $param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT, + $rekey = false, $force_array = false, $group = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + settype($params, 'array'); + if (empty($params)) { + return $db->queryAll($query, $types, $fetchmode, $rekey, $force_array, $group); + } + + $stmt = $db->prepare($query, $param_types, $types); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $result = $stmt->execute($params); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $all = $result->fetchAll($fetchmode, $rekey, $force_array, $group); + $stmt->free(); + $result->free(); + return $all; + } + + // }}} + // {{{ getAssoc() + + /** + * Fetch the entire result set of a query and return it as an + * associative array using the first column as the key. + * + * If the result set contains more than two columns, the value + * will be an array of the values from column 2-n. If the result + * set contains only two columns, the returned value will be a + * scalar with the value of the second column (unless forced to an + * array with the $force_array parameter). A MDB2 error code is + * returned on errors. If the result set contains fewer than two + * columns, a MDB2_ERROR_TRUNCATED error is returned. + * + * For example, if the table 'mytable' contains: + *
+     *   ID      TEXT       DATE
+     * --------------------------------
+     *   1       'one'      944679408
+     *   2       'two'      944679408
+     *   3       'three'    944679408
+     * 
+ * Then the call getAssoc('SELECT id,text FROM mytable') returns: + *
+     *    array(
+     *      '1' => 'one',
+     *      '2' => 'two',
+     *      '3' => 'three',
+     *    )
+     * 
+ * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: + *
+     *    array(
+     *      '1' => array('one', '944679408'),
+     *      '2' => array('two', '944679408'),
+     *      '3' => array('three', '944679408')
+     *    )
+     * 
+ * + * If the more than one row occurs with the same value in the + * first column, the last row overwrites all previous ones by + * default. Use the $group parameter if you don't want to + * overwrite like this. Example: + *
+     * getAssoc('SELECT category,id,name FROM mytable', null, null
+     *           MDB2_FETCHMODE_ASSOC, false, true) returns:
+     *    array(
+     *      '1' => array(array('id' => '4', 'name' => 'number four'),
+     *                   array('id' => '6', 'name' => 'number six')
+     *             ),
+     *      '9' => array(array('id' => '4', 'name' => 'number four'),
+     *                   array('id' => '6', 'name' => 'number six')
+     *             )
+     *    )
+     * 
+ * + * Keep in mind that database functions in PHP usually return string + * values for results regardless of the database's internal type. + * + * @param string the SQL query + * @param array that contains the types of the columns in the result set + * @param array if supplied, prepare/execute will be used + * with this array as execute parameters + * @param array that contains the types of the values defined in $params + * @param bool $force_array used only when the query returns + * exactly two columns. If TRUE, the values of the returned array + * will be one-element arrays instead of scalars. + * @param bool $group if TRUE, the values of the returned array + * is wrapped in another array. If the same key value (in the first + * column) repeats itself, the values will be appended to this array + * instead of overwriting the existing values. + * + * @return array|MDB2_Error data on success, a MDB2 error on failure + * @access public + */ + function getAssoc($query, $types = null, $params = array(), $param_types = null, + $fetchmode = MDB2_FETCHMODE_DEFAULT, $force_array = false, $group = false) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + settype($params, 'array'); + if (empty($params)) { + return $db->queryAll($query, $types, $fetchmode, true, $force_array, $group); + } + + $stmt = $db->prepare($query, $param_types, $types); + if (PEAR::isError($stmt)) { + return $stmt; + } + + $result = $stmt->execute($params); + if (!MDB2::isResultCommon($result)) { + return $result; + } + + $all = $result->fetchAll($fetchmode, true, $force_array, $group); + $stmt->free(); + $result->free(); + return $all; + } + + // }}} + // {{{ executeMultiple() + + /** + * This function does several execute() calls on the same statement handle. + * $params must be an array indexed numerically from 0, one execute call is + * done for every 'row' in the array. + * + * If an error occurs during execute(), executeMultiple() does not execute + * the unfinished rows, but rather returns that error. + * + * @param resource query handle from prepare() + * @param array numeric array containing the data to insert into the query + * + * @return bool|MDB2_Error true on success, a MDB2 error on failure + * @access public + * @see prepare(), execute() + */ + function executeMultiple(&$stmt, $params = null) + { + for ($i = 0, $j = count($params); $i < $j; $i++) { + $result = $stmt->execute($params[$i]); + if (PEAR::isError($result)) { + return $result; + } + } + return MDB2_OK; + } + + // }}} + // {{{ getBeforeID() + + /** + * Returns the next free id of a sequence if the RDBMS + * does not support auto increment + * + * @param string name of the table into which a new row was inserted + * @param string name of the field into which a new row was inserted + * @param bool when true the sequence is automatic created, if it not exists + * @param bool if the returned value should be quoted + * + * @return int|MDB2_Error id on success, a MDB2 error on failure + * @access public + */ + function getBeforeID($table, $field = null, $ondemand = true, $quote = true) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($db->supports('auto_increment') !== true) { + $seq = $table.(empty($field) ? '' : '_'.$field); + $id = $db->nextID($seq, $ondemand); + if (!$quote || PEAR::isError($id)) { + return $id; + } + return $db->quote($id, 'integer'); + } elseif (!$quote) { + return null; + } + return 'NULL'; + } + + // }}} + // {{{ getAfterID() + + /** + * Returns the autoincrement ID if supported or $id + * + * @param mixed value as returned by getBeforeId() + * @param string name of the table into which a new row was inserted + * @param string name of the field into which a new row was inserted + * + * @return int|MDB2_Error id on success, a MDB2 error on failure + * @access public + */ + function getAfterID($id, $table, $field = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if ($db->supports('auto_increment') !== true) { + return $id; + } + return $db->lastInsertID($table, $field); + } + + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Iterator.php b/lib/Pear/MDB2/Iterator.php new file mode 100644 index 0000000..ca5e7b6 --- /dev/null +++ b/lib/Pear/MDB2/Iterator.php @@ -0,0 +1,259 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Iterator.php,v 1.22 2006/05/06 14:03:41 lsmith Exp $ + +/** + * PHP5 Iterator + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Iterator implements Iterator +{ + protected $fetchmode; + protected $result; + protected $row; + + // {{{ constructor + + /** + * Constructor + */ + public function __construct($result, $fetchmode = MDB2_FETCHMODE_DEFAULT) + { + $this->result = $result; + $this->fetchmode = $fetchmode; + } + // }}} + + // {{{ seek() + + /** + * Seek forward to a specific row in a result set + * + * @param int number of the row where the data can be found + * + * @return void + * @access public + */ + public function seek($rownum) + { + $this->row = null; + if ($this->result) { + $this->result->seek($rownum); + } + } + // }}} + + // {{{ next() + + /** + * Fetch next row of data + * + * @return void + * @access public + */ + public function next() + { + $this->row = null; + } + // }}} + + // {{{ current() + + /** + * return a row of data + * + * @return void + * @access public + */ + public function current() + { + if (is_null($this->row)) { + $row = $this->result->fetchRow($this->fetchmode); + if (PEAR::isError($row)) { + $row = false; + } + $this->row = $row; + } + return $this->row; + } + // }}} + + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return bool true/false, false is also returned on failure + * @access public + */ + public function valid() + { + return (bool)$this->current(); + } + // }}} + + // {{{ free() + + /** + * Free the internal resources associated with result. + * + * @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid + * @access public + */ + public function free() + { + if ($this->result) { + return $this->result->free(); + } + $this->result = false; + $this->row = null; + return false; + } + // }}} + + // {{{ key() + + /** + * Returns the row number + * + * @return int|bool|MDB2_Error true on success, false|MDB2_Error if result is invalid + * @access public + */ + public function key() + { + if ($this->result) { + return $this->result->rowCount(); + } + return false; + } + // }}} + + // {{{ rewind() + + /** + * Seek to the first row in a result set + * + * @return void + * @access public + */ + public function rewind() + { + } + // }}} + + // {{{ destructor + + /** + * Destructor + */ + public function __destruct() + { + $this->free(); + } + // }}} +} + +/** + * PHP5 buffered Iterator + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_BufferedIterator extends MDB2_Iterator implements SeekableIterator +{ + // {{{ valid() + + /** + * Check if the end of the result set has been reached + * + * @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid + * @access public + */ + public function valid() + { + if ($this->result) { + return $this->result->valid(); + } + return false; + } + // }}} + + // {{{count() + + /** + * Returns the number of rows in a result object + * + * @return int|MDB2_Error number of rows, false|MDB2_Error if result is invalid + * @access public + */ + public function count() + { + if ($this->result) { + return $this->result->numRows(); + } + return false; + } + // }}} + + // {{{ rewind() + + /** + * Seek to the first row in a result set + * + * @return void + * @access public + */ + public function rewind() + { + $this->seek(0); + } + // }}} +} + +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/LOB.php b/lib/Pear/MDB2/LOB.php new file mode 100644 index 0000000..69db267 --- /dev/null +++ b/lib/Pear/MDB2/LOB.php @@ -0,0 +1,264 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: LOB.php,v 1.34 2006/10/25 11:52:21 lsmith Exp $ + +/** + * @package MDB2 + * @category Database + * @author Lukas Smith + */ + +require_once 'MDB2.php'; + +/** + * MDB2_LOB: user land stream wrapper implementation for LOB support + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_LOB +{ + /** + * contains the key to the global MDB2 instance array of the associated + * MDB2 instance + * + * @var integer + * @access protected + */ + var $db_index; + + /** + * contains the key to the global MDB2_LOB instance array of the associated + * MDB2_LOB instance + * + * @var integer + * @access protected + */ + var $lob_index; + + // {{{ stream_open() + + /** + * open stream + * + * @param string specifies the URL that was passed to fopen() + * @param string the mode used to open the file + * @param int holds additional flags set by the streams API + * @param string not used + * + * @return bool + * @access public + */ + function stream_open($path, $mode, $options, &$opened_path) + { + if (!preg_match('/^rb?\+?$/', $mode)) { + return false; + } + $url = parse_url($path); + if (empty($url['host'])) { + return false; + } + $this->db_index = (int)$url['host']; + if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + return false; + } + $db =& $GLOBALS['_MDB2_databases'][$this->db_index]; + $this->lob_index = (int)$url['user']; + if (!isset($db->datatype->lobs[$this->lob_index])) { + return false; + } + return true; + } + // }}} + + // {{{ stream_read() + + /** + * read stream + * + * @param int number of bytes to read + * + * @return string + * @access public + */ + function stream_read($count) + { + if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + $db =& $GLOBALS['_MDB2_databases'][$this->db_index]; + $db->datatype->_retrieveLOB($db->datatype->lobs[$this->lob_index]); + + $data = $db->datatype->_readLOB($db->datatype->lobs[$this->lob_index], $count); + $length = strlen($data); + if ($length == 0) { + $db->datatype->lobs[$this->lob_index]['endOfLOB'] = true; + } + $db->datatype->lobs[$this->lob_index]['position'] += $length; + return $data; + } + } + // }}} + + // {{{ stream_write() + + /** + * write stream, note implemented + * + * @param string data + * + * @return int + * @access public + */ + function stream_write($data) + { + return 0; + } + // }}} + + // {{{ stream_tell() + + /** + * return the current position + * + * @return int current position + * @access public + */ + function stream_tell() + { + if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + $db =& $GLOBALS['_MDB2_databases'][$this->db_index]; + return $db->datatype->lobs[$this->lob_index]['position']; + } + } + // }}} + + // {{{ stream_eof() + + /** + * Check if stream reaches EOF + * + * @return bool + * @access public + */ + function stream_eof() + { + if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + return true; + } + + $db =& $GLOBALS['_MDB2_databases'][$this->db_index]; + $result = $db->datatype->_endOfLOB($db->datatype->lobs[$this->lob_index]); + if (version_compare(phpversion(), "5.0", ">=") + && version_compare(phpversion(), "5.1", "<") + ) { + return !$result; + } + return $result; + } + // }}} + + // {{{ stream_seek() + + /** + * Seek stream, not implemented + * + * @param int offset + * @param int whence + * + * @return bool + * @access public + */ + function stream_seek($offset, $whence) + { + return false; + } + // }}} + + // {{{ stream_stat() + + /** + * return information about stream + * + * @access public + */ + function stream_stat() + { + if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + $db =& $GLOBALS['_MDB2_databases'][$this->db_index]; + return array( + 'db_index' => $this->db_index, + 'lob_index' => $this->lob_index, + ); + } + } + // }}} + + // {{{ stream_close() + + /** + * close stream + * + * @access public + */ + function stream_close() + { + if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { + $db =& $GLOBALS['_MDB2_databases'][$this->db_index]; + if (isset($db->datatype->lobs[$this->lob_index])) { + $db->datatype->_destroyLOB($db->datatype->lobs[$this->lob_index]); + unset($db->datatype->lobs[$this->lob_index]); + } + } + } + // }}} +} + +// register streams wrapper +if (!stream_wrapper_register("MDB2LOB", "MDB2_LOB")) { + MDB2::raiseError(); + return false; +} + +?> diff --git a/lib/Pear/MDB2/Schema.php b/lib/Pear/MDB2/Schema.php new file mode 100644 index 0000000..0373970 --- /dev/null +++ b/lib/Pear/MDB2/Schema.php @@ -0,0 +1,2767 @@ + + * Author: Igor Feghali + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id: Schema.php,v 1.132 2009/02/22 21:43:22 ifeghali Exp $ + * @link http://pear.php.net/packages/MDB2_Schema + */ + +require_once 'MDB2.php'; + +define('MDB2_SCHEMA_DUMP_ALL', 0); +define('MDB2_SCHEMA_DUMP_STRUCTURE', 1); +define('MDB2_SCHEMA_DUMP_CONTENT', 2); + +/** + * If you add an error code here, make sure you also add a textual + * version of it in MDB2_Schema::errorMessage(). + */ + +define('MDB2_SCHEMA_ERROR', -1); +define('MDB2_SCHEMA_ERROR_PARSE', -2); +define('MDB2_SCHEMA_ERROR_VALIDATE', -3); +define('MDB2_SCHEMA_ERROR_UNSUPPORTED', -4); // Driver does not support this function +define('MDB2_SCHEMA_ERROR_INVALID', -5); // Invalid attribute value +define('MDB2_SCHEMA_ERROR_WRITER', -6); + +/** + * The database manager is a class that provides a set of database + * management services like installing, altering and dumping the data + * structures of databases. + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema extends PEAR +{ + // {{{ properties + + var $db; + + var $warnings = array(); + + var $options = array( + 'fail_on_invalid_names' => true, + 'dtd_file' => false, + 'valid_types' => array(), + 'force_defaults' => true, + 'parser' => 'MDB2_Schema_Parser', + 'writer' => 'MDB2_Schema_Writer', + 'validate' => 'MDB2_Schema_Validate', + 'drop_missing_tables' => false + ); + + // }}} + // {{{ apiVersion() + + /** + * Return the MDB2 API version + * + * @return string the MDB2 API version number + * @access public + */ + function apiVersion() + { + return '0.4.3'; + } + + // }}} + // {{{ arrayMergeClobber() + + /** + * Clobbers two arrays together + * + * @param array $a1 array that should be clobbered + * @param array $a2 array that should be clobbered + * + * @return array|false array on success and false on error + * + * @access public + * @author kc@hireability.com + */ + function arrayMergeClobber($a1, $a2) + { + if (!is_array($a1) || !is_array($a2)) { + return false; + } + foreach ($a2 as $key => $val) { + if (is_array($val) && array_key_exists($key, $a1) && is_array($a1[$key])) { + $a1[$key] = MDB2_Schema::arrayMergeClobber($a1[$key], $val); + } else { + $a1[$key] = $val; + } + } + return $a1; + } + + // }}} + // {{{ resetWarnings() + + /** + * reset the warning array + * + * @access public + * @return void + */ + function resetWarnings() + { + $this->warnings = array(); + } + + // }}} + // {{{ getWarnings() + + /** + * Get all warnings in reverse order + * + * This means that the last warning is the first element in the array + * + * @return array with warnings + * @access public + * @see resetWarnings() + */ + function getWarnings() + { + return array_reverse($this->warnings); + } + + // }}} + // {{{ setOption() + + /** + * Sets the option for the db class + * + * @param string $option option name + * @param mixed $value value for the option + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function setOption($option, $value) + { + if (isset($this->options[$option])) { + if (is_null($value)) { + return $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'may not set an option to value null'); + } + $this->options[$option] = $value; + return MDB2_OK; + } + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + "unknown option $option"); + } + + // }}} + // {{{ getOption() + + /** + * returns the value of an option + * + * @param string $option option name + * + * @return mixed the option value or error object + * @access public + */ + function getOption($option) + { + if (isset($this->options[$option])) { + return $this->options[$option]; + } + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, + null, null, "unknown option $option"); + } + + // }}} + // {{{ factory() + + /** + * Create a new MDB2 object for the specified database type + * type + * + * @param string|array|MDB2_Driver_Common &$db 'data source name', see the + * MDB2::parseDSN method for a description of the dsn format. + * Can also be specified as an array of the + * format returned by @see MDB2::parseDSN. + * Finally you can also pass an existing db object to be used. + * @param array $options An associative array of option names and their values. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + * @see MDB2::parseDSN + */ + function &factory(&$db, $options = array()) + { + $obj =& new MDB2_Schema(); + + $result = $obj->connect($db, $options); + if (PEAR::isError($result)) { + return $result; + } + return $obj; + } + + // }}} + // {{{ connect() + + /** + * Create a new MDB2 connection object and connect to the specified + * database + * + * @param string|array|MDB2_Driver_Common &$db 'data source name', see the + * MDB2::parseDSN method for a description of the dsn format. + * Can also be specified as an array of the + * format returned by MDB2::parseDSN. + * Finally you can also pass an existing db object to be used. + * @param array $options An associative array of option names and their values. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + * @see MDB2::parseDSN + */ + function connect(&$db, $options = array()) + { + $db_options = array(); + if (is_array($options)) { + foreach ($options as $option => $value) { + if (array_key_exists($option, $this->options)) { + $result = $this->setOption($option, $value); + if (PEAR::isError($result)) { + return $result; + } + } else { + $db_options[$option] = $value; + } + } + } + + $this->disconnect(); + if (!MDB2::isConnection($db)) { + $db =& MDB2::factory($db, $db_options); + } + + if (PEAR::isError($db)) { + return $db; + } + + $this->db =& $db; + $this->db->loadModule('Datatype'); + $this->db->loadModule('Manager'); + $this->db->loadModule('Reverse'); + $this->db->loadModule('Function'); + if (empty($this->options['valid_types'])) { + $this->options['valid_types'] = $this->db->datatype->getValidTypes(); + } + + return MDB2_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Log out and disconnect from the database. + * + * @access public + * @return void + */ + function disconnect() + { + if (MDB2::isConnection($this->db)) { + $this->db->disconnect(); + unset($this->db); + } + } + + // }}} + // {{{ parseDatabaseDefinition() + + /** + * Parse a database definition from a file or an array + * + * @param string|array $schema the database schema array or file name + * @param bool $skip_unreadable if non readable files should be skipped + * @param array $variables associative array that the defines the text string values + * that are meant to be used to replace the variables that are + * used in the schema description. + * @param bool $fail_on_invalid_names make function fail on invalid names + * @param array $structure database structure definition + * + * @access public + * @return array + */ + function parseDatabaseDefinition($schema, $skip_unreadable = false, $variables = array(), + $fail_on_invalid_names = true, $structure = false) + { + $database_definition = false; + if (is_string($schema)) { + // if $schema is not readable then we just skip it + // and simply copy the $current_schema file to that file name + if (is_readable($schema)) { + $database_definition = $this->parseDatabaseDefinitionFile($schema, $variables, $fail_on_invalid_names, $structure); + } + } elseif (is_array($schema)) { + $database_definition = $schema; + } + if (!$database_definition && !$skip_unreadable) { + $database_definition = $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'invalid data type of schema or unreadable data source'); + } + return $database_definition; + } + + // }}} + // {{{ parseDatabaseDefinitionFile() + + /** + * Parse a database definition file by creating a schema format + * parser object and passing the file contents as parser input data stream. + * + * @param string $input_file the database schema file. + * @param array $variables associative array that the defines the text string values + * that are meant to be used to replace the variables that are + * used in the schema description. + * @param bool $fail_on_invalid_names make function fail on invalid names + * @param array $structure database structure definition + * + * @access public + * @return array + */ + function parseDatabaseDefinitionFile($input_file, $variables = array(), + $fail_on_invalid_names = true, $structure = false) + { + $dtd_file = $this->options['dtd_file']; + if ($dtd_file) { + include_once 'XML/DTD/XmlValidator.php'; + $dtd =& new XML_DTD_XmlValidator; + if (!$dtd->isValid($dtd_file, $input_file)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_PARSE, null, null, $dtd->getMessage()); + } + } + + $class_name = $this->options['parser']; + + $result = MDB2::loadClass($class_name, $this->db->getOption('debug')); + if (PEAR::isError($result)) { + return $result; + } + + $parser =& new $class_name($variables, $fail_on_invalid_names, $structure, $this->options['valid_types'], $this->options['force_defaults']); + $result = $parser->setInputFile($input_file); + if (PEAR::isError($result)) { + return $result; + } + + $result = $parser->parse(); + if (PEAR::isError($result)) { + return $result; + } + if (PEAR::isError($parser->error)) { + return $parser->error; + } + + return $parser->database_definition; + } + + // }}} + // {{{ getDefinitionFromDatabase() + + /** + * Attempt to reverse engineer a schema structure from an existing MDB2 + * This method can be used if no xml schema file exists yet. + * The resulting xml schema file may need some manual adjustments. + * + * @return array|MDB2_Error array with definition or error object + * @access public + */ + function getDefinitionFromDatabase() + { + $database = $this->db->database_name; + if (empty($database)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'it was not specified a valid database name'); + } + + $class_name = $this->options['validate']; + + $result = MDB2::loadClass($class_name, $this->db->getOption('debug')); + if (PEAR::isError($result)) { + return $result; + } + + $val =& new $class_name($this->options['fail_on_invalid_names'], $this->options['valid_types'], $this->options['force_defaults']); + + $database_definition = array( + 'name' => $database, + 'create' => true, + 'overwrite' => false, + 'charset' => 'utf8', + 'description' => '', + 'comments' => '', + 'tables' => array(), + 'sequences' => array(), + ); + + $tables = $this->db->manager->listTables(); + if (PEAR::isError($tables)) { + return $tables; + } + + foreach ($tables as $table_name) { + $fields = $this->db->manager->listTableFields($table_name); + if (PEAR::isError($fields)) { + return $fields; + } + + $database_definition['tables'][$table_name] = array( + 'was' => '', + 'description' => '', + 'comments' => '', + 'fields' => array(), + 'indexes' => array(), + 'constraints' => array(), + 'initialization' => array() + ); + + $table_definition =& $database_definition['tables'][$table_name]; + foreach ($fields as $field_name) { + $definition = $this->db->reverse->getTableFieldDefinition($table_name, $field_name); + if (PEAR::isError($definition)) { + return $definition; + } + + if (!empty($definition[0]['autoincrement'])) { + $definition[0]['default'] = '0'; + } + + $table_definition['fields'][$field_name] = $definition[0]; + + $field_choices = count($definition); + if ($field_choices > 1) { + $warning = "There are $field_choices type choices in the table $table_name field $field_name (#1 is the default): "; + + $field_choice_cnt = 1; + + $table_definition['fields'][$field_name]['choices'] = array(); + foreach ($definition as $field_choice) { + $table_definition['fields'][$field_name]['choices'][] = $field_choice; + + $warning .= 'choice #'.($field_choice_cnt).': '.serialize($field_choice); + $field_choice_cnt++; + } + $this->warnings[] = $warning; + } + + /** + * The first parameter is used to verify if there are duplicated + * fields which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateField(array(), $table_definition['fields'][$field_name], $field_name); + if (PEAR::isError($result)) { + return $result; + } + } + + $keys = array(); + + $indexes = $this->db->manager->listTableIndexes($table_name); + if (PEAR::isError($indexes)) { + return $indexes; + } + + if (is_array($indexes)) { + foreach ($indexes as $index_name) { + $this->db->expectError(MDB2_ERROR_NOT_FOUND); + $definition = $this->db->reverse->getTableIndexDefinition($table_name, $index_name); + $this->db->popExpect(); + if (PEAR::isError($definition)) { + if (PEAR::isError($definition, MDB2_ERROR_NOT_FOUND)) { + continue; + } + return $definition; + } + + $keys[$index_name] = $definition; + } + } + + $constraints = $this->db->manager->listTableConstraints($table_name); + if (PEAR::isError($constraints)) { + return $constraints; + } + + if (is_array($constraints)) { + foreach ($constraints as $constraint_name) { + $this->db->expectError(MDB2_ERROR_NOT_FOUND); + $definition = $this->db->reverse->getTableConstraintDefinition($table_name, $constraint_name); + $this->db->popExpect(); + if (PEAR::isError($definition)) { + if (PEAR::isError($definition, MDB2_ERROR_NOT_FOUND)) { + continue; + } + return $definition; + } + + $keys[$constraint_name] = $definition; + } + } + + foreach ($keys as $key_name => $definition) { + if (array_key_exists('foreign', $definition) + && $definition['foreign'] + ) { + /** + * The first parameter is used to verify if there are duplicated + * foreign keys which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateConstraint(array(), $definition, $key_name); + if (PEAR::isError($result)) { + return $result; + } + + foreach ($definition['fields'] as $field_name => $field) { + /** + * The first parameter is used to verify if there are duplicated + * referencing fields which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateConstraintField(array(), $field_name); + if (PEAR::isError($result)) { + return $result; + } + + $definition['fields'][$field_name] = ''; + } + + foreach ($definition['references']['fields'] as $field_name => $field) { + /** + * The first parameter is used to verify if there are duplicated + * referenced fields which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateConstraintReferencedField(array(), $field_name); + if (PEAR::isError($result)) { + return $result; + } + + $definition['references']['fields'][$field_name] = ''; + } + + $table_definition['constraints'][$key_name] = $definition; + } else { + /** + * The first parameter is used to verify if there are duplicated + * indices which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateIndex(array(), $definition, $key_name); + if (PEAR::isError($result)) { + return $result; + } + + foreach ($definition['fields'] as $field_name => $field) { + /** + * The first parameter is used to verify if there are duplicated + * index fields which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateIndexField(array(), $field, $field_name); + if (PEAR::isError($result)) { + return $result; + } + + $definition['fields'][$field_name] = $field; + } + + $table_definition['indexes'][$key_name] = $definition; + } + } + + /** + * The first parameter is used to verify if there are duplicated + * tables which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateTable(array(), $table_definition, $table_name); + if (PEAR::isError($result)) { + return $result; + } + + } + + $sequences = $this->db->manager->listSequences(); + if (PEAR::isError($sequences)) { + return $sequences; + } + + if (is_array($sequences)) { + foreach ($sequences as $sequence_name) { + $definition = $this->db->reverse->getSequenceDefinition($sequence_name); + if (PEAR::isError($definition)) { + return $definition; + } + if (isset($database_definition['tables'][$sequence_name]) + && isset($database_definition['tables'][$sequence_name]['indexes']) + ) { + foreach ($database_definition['tables'][$sequence_name]['indexes'] as $index) { + if (isset($index['primary']) && $index['primary'] + && count($index['fields'] == 1) + ) { + $definition['on'] = array( + 'table' => $sequence_name, + 'field' => key($index['fields']), + ); + break; + } + } + } + + /** + * The first parameter is used to verify if there are duplicated + * sequences which we can guarantee that won't happen when reverse engineering + */ + $result = $val->validateSequence(array(), $definition, $sequence_name); + if (PEAR::isError($result)) { + return $result; + } + + $database_definition['sequences'][$sequence_name] = $definition; + } + } + + $result = $val->validateDatabase($database_definition); + if (PEAR::isError($result)) { + return $result; + } + + return $database_definition; + } + + // }}} + // {{{ createTableIndexes() + + /** + * A method to create indexes for an existing table + * + * @param string $table_name Name of the table + * @param array $indexes An array of indexes to be created + * @param boolean $overwrite If the table/index should be overwritten if it already exists + * + * @return mixed MDB2_Error if there is an error creating an index, MDB2_OK otherwise + * @access public + */ + function createTableIndexes($table_name, $indexes, $overwrite = false) + { + if (!$this->db->supports('indexes')) { + $this->db->debug('Indexes are not supported', __FUNCTION__); + return MDB2_OK; + } + + $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE); + foreach ($indexes as $index_name => $index) { + + // Does the index already exist, and if so, should it be overwritten? + $create_index = true; + $this->db->expectError($errorcodes); + if (!empty($index['primary']) || !empty($index['unique'])) { + $current_indexes = $this->db->manager->listTableConstraints($table_name); + } else { + $current_indexes = $this->db->manager->listTableIndexes($table_name); + } + + $this->db->popExpect(); + if (PEAR::isError($current_indexes)) { + if (!MDB2::isError($current_indexes, $errorcodes)) { + return $current_indexes; + } + } elseif (is_array($current_indexes) && in_array($index_name, $current_indexes)) { + if (!$overwrite) { + $this->db->debug('Index already exists: '.$index_name, __FUNCTION__); + $create_index = false; + } else { + $this->db->debug('Preparing to overwrite index: '.$index_name, __FUNCTION__); + + $this->db->expectError(MDB2_ERROR_NOT_FOUND); + if (!empty($index['primary']) || !empty($index['unique'])) { + $result = $this->db->manager->dropConstraint($table_name, $index_name); + } else { + $result = $this->db->manager->dropIndex($table_name, $index_name); + } + $this->db->popExpect(); + if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_NOT_FOUND)) { + return $result; + } + } + } + + // Check if primary is being used and if it's supported + if (!empty($index['primary']) && !$this->db->supports('primary_key')) { + + // Primary not supported so we fallback to UNIQUE and making the field NOT NULL + $index['unique'] = true; + + $changes = array(); + + foreach ($index['fields'] as $field => $empty) { + $field_info = $this->db->reverse->getTableFieldDefinition($table_name, $field); + if (PEAR::isError($field_info)) { + return $field_info; + } + if (!$field_info[0]['notnull']) { + $changes['change'][$field] = $field_info[0]; + + $changes['change'][$field]['notnull'] = true; + } + } + if (!empty($changes)) { + $this->db->manager->alterTable($table_name, $changes, false); + } + } + + // Should the index be created? + if ($create_index) { + if (!empty($index['primary']) || !empty($index['unique'])) { + $result = $this->db->manager->createConstraint($table_name, $index_name, $index); + } else { + $result = $this->db->manager->createIndex($table_name, $index_name, $index); + } + if (PEAR::isError($result)) { + return $result; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ createTableConstraints() + + /** + * A method to create foreign keys for an existing table + * + * @param string $table_name Name of the table + * @param array $constraints An array of foreign keys to be created + * @param boolean $overwrite If the foreign key should be overwritten if it already exists + * + * @return mixed MDB2_Error if there is an error creating a foreign key, MDB2_OK otherwise + * @access public + */ + function createTableConstraints($table_name, $constraints, $overwrite = false) + { + if (!$this->db->supports('indexes')) { + $this->db->debug('Indexes are not supported', __FUNCTION__); + return MDB2_OK; + } + + $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE); + foreach ($constraints as $constraint_name => $constraint) { + + // Does the foreign key already exist, and if so, should it be overwritten? + $create_constraint = true; + $this->db->expectError($errorcodes); + $current_constraints = $this->db->manager->listTableConstraints($table_name); + $this->db->popExpect(); + if (PEAR::isError($current_constraints)) { + if (!MDB2::isError($current_constraints, $errorcodes)) { + return $current_constraints; + } + } elseif (is_array($current_constraints) && in_array($constraint_name, $current_constraints)) { + if (!$overwrite) { + $this->db->debug('Foreign key already exists: '.$constraint_name, __FUNCTION__); + $create_constraint = false; + } else { + $this->db->debug('Preparing to overwrite foreign key: '.$constraint_name, __FUNCTION__); + $result = $this->db->manager->dropConstraint($table_name, $constraint_name); + if (PEAR::isError($result)) { + return $result; + } + } + } + + // Should the foreign key be created? + if ($create_constraint) { + $result = $this->db->manager->createConstraint($table_name, $constraint_name, $constraint); + if (PEAR::isError($result)) { + return $result; + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ createTable() + + /** + * Create a table and inititialize the table if data is available + * + * @param string $table_name name of the table to be created + * @param array $table multi dimensional array that contains the + * structure and optional data of the table + * @param bool $overwrite if the table/index should be overwritten if it already exists + * @param array $options an array of options to be passed to the database specific driver + * version of MDB2_Driver_Manager_Common::createTable(). + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function createTable($table_name, $table, $overwrite = false, $options = array()) + { + $create = true; + + $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE); + + $this->db->expectError($errorcodes); + + $tables = $this->db->manager->listTables(); + + $this->db->popExpect(); + if (PEAR::isError($tables)) { + if (!MDB2::isError($tables, $errorcodes)) { + return $tables; + } + } elseif (is_array($tables) && in_array($table_name, $tables)) { + if (!$overwrite) { + $create = false; + $this->db->debug('Table already exists: '.$table_name, __FUNCTION__); + } else { + $result = $this->db->manager->dropTable($table_name); + if (PEAR::isError($result)) { + return $result; + } + $this->db->debug('Overwritting table: '.$table_name, __FUNCTION__); + } + } + + if ($create) { + $result = $this->db->manager->createTable($table_name, $table['fields'], $options); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($table['initialization']) && is_array($table['initialization'])) { + $result = $this->initializeTable($table_name, $table); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($table['indexes']) && is_array($table['indexes'])) { + $result = $this->createTableIndexes($table_name, $table['indexes'], $overwrite); + if (PEAR::isError($result)) { + return $result; + } + } + + if (!empty($table['constraints']) && is_array($table['constraints'])) { + $result = $this->createTableConstraints($table_name, $table['constraints'], $overwrite); + if (PEAR::isError($result)) { + return $result; + } + } + + return MDB2_OK; + } + + // }}} + // {{{ initializeTable() + + /** + * Inititialize the table with data + * + * @param string $table_name name of the table + * @param array $table multi dimensional array that contains the + * structure and optional data of the table + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function initializeTable($table_name, $table) + { + $query_insertselect = 'INSERT INTO %s (%s) (SELECT %s FROM %s %s)'; + + $query_insert = 'INSERT INTO %s (%s) VALUES (%s)'; + $query_update = 'UPDATE %s SET %s %s'; + $query_delete = 'DELETE FROM %s %s'; + + $table_name = $this->db->quoteIdentifier($table_name, true); + + $result = MDB2_OK; + + $support_transactions = $this->db->supports('transactions'); + + foreach ($table['initialization'] as $instruction) { + $query = ''; + switch ($instruction['type']) { + case 'insert': + if (!isset($instruction['data']['select'])) { + $data = $this->getInstructionFields($instruction['data'], $table['fields']); + if (!empty($data)) { + $fields = implode(', ', array_keys($data)); + $values = implode(', ', array_values($data)); + + $query = sprintf($query_insert, $table_name, $fields, $values); + } + } else { + $data = $this->getInstructionFields($instruction['data']['select'], $table['fields']); + $where = $this->getInstructionWhere($instruction['data']['select'], $table['fields']); + + $select_table_name = $this->db->quoteIdentifier($instruction['data']['select']['table'], true); + if (!empty($data)) { + $fields = implode(', ', array_keys($data)); + $values = implode(', ', array_values($data)); + + $query = sprintf($query_insertselect, $table_name, $fields, $values, $select_table_name, $where); + } + } + break; + case 'update': + $data = $this->getInstructionFields($instruction['data'], $table['fields']); + $where = $this->getInstructionWhere($instruction['data'], $table['fields']); + if (!empty($data)) { + array_walk($data, array($this, 'buildFieldValue')); + $fields_values = implode(', ', $data); + + $query = sprintf($query_update, $table_name, $fields_values, $where); + } + break; + case 'delete': + $where = $this->getInstructionWhere($instruction['data'], $table['fields']); + $query = sprintf($query_delete, $table_name, $where); + break; + } + if ($query) { + if ($support_transactions && PEAR::isError($res = $this->db->beginNestedTransaction())) { + return $res; + } + + $result = $this->db->exec($query); + if (PEAR::isError($result)) { + return $result; + } + + if ($support_transactions && PEAR::isError($res = $this->db->completeNestedTransaction())) { + return $res; + } + } + } + return $result; + } + + // }}} + // {{{ buildFieldValue() + + /** + * Appends the contents of second argument + '=' to the beginning of first + * argument. + * + * Used with array_walk() in initializeTable() for UPDATEs. + * + * @param string &$element value of array's element + * @param string $key key of array's element + * + * @return void + * + * @access public + * @see MDB2_Schema::initializeTable() + */ + function buildFieldValue(&$element, $key) + { + $element = $key."=$element"; + } + + // }}} + // {{{ getExpression() + + /** + * Generates a string that represents a value that would be associated + * with a column in a DML instruction. + * + * @param array $element multi dimensional array that contains the + * structure of the current DML instruction. + * @param array $fields_definition multi dimensional array that contains the + * definition for current table's fields + * @param string $type type of given field + * + * @return string + * + * @access public + * @see MDB2_Schema::getInstructionFields(), MDB2_Schema::getInstructionWhere() + */ + function getExpression($element, $fields_definition = array(), $type = null) + { + $str = ''; + switch ($element['type']) { + case 'null': + $str .= 'NULL'; + break; + case 'value': + $str .= $this->db->quote($element['data'], $type); + break; + case 'column': + $str .= $this->db->quoteIdentifier($element['data'], true); + break; + case 'function': + $arguments = array(); + if (!empty($element['data']['arguments']) + && is_array($element['data']['arguments']) + ) { + foreach ($element['data']['arguments'] as $v) { + $arguments[] = $this->getExpression($v, $fields_definition); + } + } + if (method_exists($this->db->function, $element['data']['name'])) { + $user_func = array(&$this->db->function, $element['data']['name']); + + $str .= call_user_func_array($user_func, $arguments); + } else { + $str .= $element['data']['name'].'('; + $str .= implode(', ', $arguments); + $str .= ')'; + } + break; + case 'expression': + $type0 = $type1 = null; + if ($element['data']['operants'][0]['type'] == 'column' + && array_key_exists($element['data']['operants'][0]['data'], $fields_definition) + ) { + $type0 = $fields_definition[$element['data']['operants'][0]['data']]['type']; + } + + if ($element['data']['operants'][1]['type'] == 'column' + && array_key_exists($element['data']['operants'][1]['data'], $fields_definition) + ) { + $type1 = $fields_definition[$element['data']['operants'][1]['data']]['type']; + } + + $str .= '('; + $str .= $this->getExpression($element['data']['operants'][0], $fields_definition, $type1); + $str .= $this->getOperator($element['data']['operator']); + $str .= $this->getExpression($element['data']['operants'][1], $fields_definition, $type0); + $str .= ')'; + break; + } + + return $str; + } + + // }}} + // {{{ getOperator() + + /** + * Returns the matching SQL operator + * + * @param string $op parsed descriptive operator + * + * @return string matching SQL operator + * + * @access public + * @static + * @see MDB2_Schema::getExpression() + */ + function getOperator($op) + { + switch ($op) { + case 'PLUS': + return ' + '; + case 'MINUS': + return ' - '; + case 'TIMES': + return ' * '; + case 'DIVIDED': + return ' / '; + case 'EQUAL': + return ' = '; + case 'NOT EQUAL': + return ' != '; + case 'LESS THAN': + return ' < '; + case 'GREATER THAN': + return ' > '; + case 'LESS THAN OR EQUAL': + return ' <= '; + case 'GREATER THAN OR EQUAL': + return ' >= '; + default: + return ' '.$op.' '; + } + } + + // }}} + // {{{ getInstructionFields() + + /** + * Walks the parsed DML instruction array, field by field, + * storing them and their processed values inside a new array. + * + * @param array $instruction multi dimensional array that contains the + * structure of the current DML instruction. + * @param array $fields_definition multi dimensional array that contains the + * definition for current table's fields + * + * @return array array of strings in the form 'field_name' => 'value' + * + * @access public + * @static + * @see MDB2_Schema::initializeTable() + */ + function getInstructionFields($instruction, $fields_definition = array()) + { + $fields = array(); + if (!empty($instruction['field']) && is_array($instruction['field'])) { + foreach ($instruction['field'] as $field) { + $field_name = $this->db->quoteIdentifier($field['name'], true); + + $fields[$field_name] = $this->getExpression($field['group'], $fields_definition); + } + } + return $fields; + } + + // }}} + // {{{ getInstructionWhere() + + /** + * Translates the parsed WHERE expression of a DML instruction + * (array structure) to a SQL WHERE clause (string). + * + * @param array $instruction multi dimensional array that contains the + * structure of the current DML instruction. + * @param array $fields_definition multi dimensional array that contains the + * definition for current table's fields. + * + * @return string SQL WHERE clause + * + * @access public + * @static + * @see MDB2_Schema::initializeTable() + */ + function getInstructionWhere($instruction, $fields_definition = array()) + { + $where = ''; + if (!empty($instruction['where'])) { + $where = 'WHERE '.$this->getExpression($instruction['where'], $fields_definition); + } + return $where; + } + + // }}} + // {{{ createSequence() + + /** + * Create a sequence + * + * @param string $sequence_name name of the sequence to be created + * @param array $sequence multi dimensional array that contains the + * structure and optional data of the table + * @param bool $overwrite if the sequence should be overwritten if it already exists + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function createSequence($sequence_name, $sequence, $overwrite = false) + { + if (!$this->db->supports('sequences')) { + $this->db->debug('Sequences are not supported', __FUNCTION__); + return MDB2_OK; + } + + $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE); + $this->db->expectError($errorcodes); + $sequences = $this->db->manager->listSequences(); + $this->db->popExpect(); + if (PEAR::isError($sequences)) { + if (!MDB2::isError($sequences, $errorcodes)) { + return $sequences; + } + } elseif (is_array($sequence) && in_array($sequence_name, $sequences)) { + if (!$overwrite) { + $this->db->debug('Sequence already exists: '.$sequence_name, __FUNCTION__); + return MDB2_OK; + } + + $result = $this->db->manager->dropSequence($sequence_name); + if (PEAR::isError($result)) { + return $result; + } + $this->db->debug('Overwritting sequence: '.$sequence_name, __FUNCTION__); + } + + $start = 1; + $field = ''; + if (!empty($sequence['on'])) { + $table = $sequence['on']['table']; + $field = $sequence['on']['field']; + + $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NOT_CAPABLE); + $this->db->expectError($errorcodes); + $tables = $this->db->manager->listTables(); + $this->db->popExpect(); + if (PEAR::isError($tables) && !MDB2::isError($tables, $errorcodes)) { + return $tables; + } + + if (!PEAR::isError($tables) && is_array($tables) && in_array($table, $tables)) { + if ($this->db->supports('summary_functions')) { + $query = "SELECT MAX($field) FROM ".$this->db->quoteIdentifier($table, true); + } else { + $query = "SELECT $field FROM ".$this->db->quoteIdentifier($table, true)." ORDER BY $field DESC"; + } + $start = $this->db->queryOne($query, 'integer'); + if (PEAR::isError($start)) { + return $start; + } + ++$start; + } else { + $this->warnings[] = 'Could not sync sequence: '.$sequence_name; + } + } elseif (!empty($sequence['start']) && is_numeric($sequence['start'])) { + $start = $sequence['start']; + $table = ''; + } + + $result = $this->db->manager->createSequence($sequence_name, $start); + if (PEAR::isError($result)) { + return $result; + } + + return MDB2_OK; + } + + // }}} + // {{{ createDatabase() + + /** + * Create a database space within which may be created database objects + * like tables, indexes and sequences. The implementation of this function + * is highly DBMS specific and may require special permissions to run + * successfully. Consult the documentation or the DBMS drivers that you + * use to be aware of eventual configuration requirements. + * + * @param array $database_definition multi dimensional array that contains the current definition + * @param array $options an array of options to be passed to the + * database specific driver version of + * MDB2_Driver_Manager_Common::createTable(). + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function createDatabase($database_definition, $options = array()) + { + if (!isset($database_definition['name']) || !$database_definition['name']) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'no valid database name specified'); + } + + $create = (isset($database_definition['create']) && $database_definition['create']); + $overwrite = (isset($database_definition['overwrite']) && $database_definition['overwrite']); + + /** + * + * We need to clean up database name before any query to prevent + * database driver from using a inexistent database + * + */ + $previous_database_name = $this->db->setDatabase(''); + + // Lower / Upper case the db name if the portability deems so. + if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { + $func = $this->db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'; + + $db_name = $func($database_definition['name']); + } else { + $db_name = $database_definition['name']; + } + + if ($create) { + + $dbExists = $this->db->databaseExists($db_name); + if (PEAR::isError($dbExists)) { + return $dbExists; + } + + if ($dbExists && $overwrite) { + $this->db->expectError(MDB2_ERROR_CANNOT_DROP); + $result = $this->db->manager->dropDatabase($db_name); + $this->db->popExpect(); + if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_CANNOT_DROP)) { + return $result; + } + $dbExists = false; + $this->db->debug('Overwritting database: ' . $db_name, __FUNCTION__); + } + + $dbOptions = array(); + if (array_key_exists('charset', $database_definition) + && !empty($database_definition['charset'])) { + $dbOptions['charset'] = $database_definition['charset']; + } + + if ($dbExists) { + $this->db->debug('Database already exists: ' . $db_name, __FUNCTION__); + if (!empty($dbOptions)) { + $errorcodes = array(MDB2_ERROR_UNSUPPORTED, MDB2_ERROR_NO_PERMISSION); + $this->db->expectError($errorcodes); + $result = $this->db->manager->alterDatabase($db_name, $dbOptions); + $this->db->popExpect(); + if (PEAR::isError($result) && !MDB2::isError($result, $errorcodes)) { + return $result; + } + } + $create = false; + } else { + $this->db->expectError(MDB2_ERROR_UNSUPPORTED); + $result = $this->db->manager->createDatabase($db_name, $dbOptions); + $this->db->popExpect(); + if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_UNSUPPORTED)) { + return $result; + } + $this->db->debug('Creating database: ' . $db_name, __FUNCTION__); + } + } + + $this->db->setDatabase($db_name); + if (($support_transactions = $this->db->supports('transactions')) + && PEAR::isError($result = $this->db->beginNestedTransaction()) + ) { + return $result; + } + + $created_objects = 0; + if (isset($database_definition['tables']) + && is_array($database_definition['tables']) + ) { + foreach ($database_definition['tables'] as $table_name => $table) { + $result = $this->createTable($table_name, $table, $overwrite, $options); + if (PEAR::isError($result)) { + break; + } + $created_objects++; + } + } + if (!PEAR::isError($result) + && isset($database_definition['sequences']) + && is_array($database_definition['sequences']) + ) { + foreach ($database_definition['sequences'] as $sequence_name => $sequence) { + $result = $this->createSequence($sequence_name, $sequence, false, $overwrite); + + if (PEAR::isError($result)) { + break; + } + $created_objects++; + } + } + + if ($support_transactions) { + $res = $this->db->completeNestedTransaction(); + if (PEAR::isError($res)) { + $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'Could not end transaction ('. + $res->getMessage().' ('.$res->getUserinfo().'))'); + } + } elseif (PEAR::isError($result) && $created_objects) { + $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'the database was only partially created ('. + $result->getMessage().' ('.$result->getUserinfo().'))'); + } + + $this->db->setDatabase($previous_database_name); + + if (PEAR::isError($result) && $create + && PEAR::isError($result2 = $this->db->manager->dropDatabase($db_name)) + ) { + if (!MDB2::isError($result2, MDB2_ERROR_UNSUPPORTED)) { + return $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'Could not drop the created database after unsuccessful creation attempt ('. + $result2->getMessage().' ('.$result2->getUserinfo().'))'); + } + } + + return $result; + } + + // }}} + // {{{ compareDefinitions() + + /** + * Compare a previous definition with the currently parsed definition + * + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * + * @return array|MDB2_Error array of changes on success, or a error object + * @access public + */ + function compareDefinitions($current_definition, $previous_definition) + { + $changes = array(); + + if (!empty($current_definition['tables']) && is_array($current_definition['tables'])) { + $changes['tables'] = $defined_tables = array(); + foreach ($current_definition['tables'] as $table_name => $table) { + $previous_tables = array(); + if (!empty($previous_definition) && is_array($previous_definition)) { + $previous_tables = $previous_definition['tables']; + } + $change = $this->compareTableDefinitions($table_name, $table, $previous_tables, $defined_tables); + if (PEAR::isError($change)) { + return $change; + } + if (!empty($change)) { + $changes['tables'] = MDB2_Schema::arrayMergeClobber($changes['tables'], $change); + } + } + + if (!empty($previous_definition['tables']) + && is_array($previous_definition['tables'])) { + foreach ($previous_definition['tables'] as $table_name => $table) { + if (empty($defined_tables[$table_name])) { + $changes['tables']['remove'][$table_name] = true; + } + } + } + } + if (!empty($current_definition['sequences']) && is_array($current_definition['sequences'])) { + $changes['sequences'] = $defined_sequences = array(); + foreach ($current_definition['sequences'] as $sequence_name => $sequence) { + $previous_sequences = array(); + if (!empty($previous_definition) && is_array($previous_definition)) { + $previous_sequences = $previous_definition['sequences']; + } + + $change = $this->compareSequenceDefinitions($sequence_name, + $sequence, + $previous_sequences, + $defined_sequences); + if (PEAR::isError($change)) { + return $change; + } + if (!empty($change)) { + $changes['sequences'] = MDB2_Schema::arrayMergeClobber($changes['sequences'], $change); + } + } + if (!empty($previous_definition['sequences']) && is_array($previous_definition['sequences'])) { + foreach ($previous_definition['sequences'] as $sequence_name => $sequence) { + if (empty($defined_sequences[$sequence_name])) { + $changes['sequences']['remove'][$sequence_name] = true; + } + } + } + } + return $changes; + } + + // }}} + // {{{ compareTableFieldsDefinitions() + + /** + * Compare a previous definition with the currently parsed definition + * + * @param string $table_name name of the table + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * + * @return array|MDB2_Error array of changes on success, or a error object + * @access public + */ + function compareTableFieldsDefinitions($table_name, $current_definition, + $previous_definition) + { + $changes = $defined_fields = array(); + + if (is_array($current_definition)) { + foreach ($current_definition as $field_name => $field) { + $was_field_name = $field['was']; + if (!empty($previous_definition[$field_name]) + && ( + (isset($previous_definition[$field_name]['was']) + && $previous_definition[$field_name]['was'] == $was_field_name) + || !isset($previous_definition[$was_field_name]) + )) { + $was_field_name = $field_name; + } + + if (!empty($previous_definition[$was_field_name])) { + if ($was_field_name != $field_name) { + $changes['rename'][$was_field_name] = array('name' => $field_name, 'definition' => $field); + } + + if (!empty($defined_fields[$was_field_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'the field "'.$was_field_name. + '" was specified for more than one field of table'); + } + + $defined_fields[$was_field_name] = true; + + $change = $this->db->compareDefinition($field, $previous_definition[$was_field_name]); + if (PEAR::isError($change)) { + return $change; + } + + if (!empty($change)) { + if (array_key_exists('default', $change) + && $change['default'] + && !array_key_exists('default', $field)) { + $field['default'] = null; + } + + $change['definition'] = $field; + + $changes['change'][$field_name] = $change; + } + } else { + if ($field_name != $was_field_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'it was specified a previous field name ("'. + $was_field_name.'") for field "'.$field_name.'" of table "'. + $table_name.'" that does not exist'); + } + + $changes['add'][$field_name] = $field; + } + } + } + + if (isset($previous_definition) && is_array($previous_definition)) { + foreach ($previous_definition as $field_previous_name => $field_previous) { + if (empty($defined_fields[$field_previous_name])) { + $changes['remove'][$field_previous_name] = true; + } + } + } + + return $changes; + } + + // }}} + // {{{ compareTableIndexesDefinitions() + + /** + * Compare a previous definition with the currently parsed definition + * + * @param string $table_name name of the table + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * + * @return array|MDB2_Error array of changes on success, or a error object + * @access public + */ + function compareTableIndexesDefinitions($table_name, $current_definition, + $previous_definition) + { + $changes = $defined_indexes = array(); + + if (is_array($current_definition)) { + foreach ($current_definition as $index_name => $index) { + $was_index_name = $index['was']; + if (!empty($previous_definition[$index_name]) + && isset($previous_definition[$index_name]['was']) + && $previous_definition[$index_name]['was'] == $was_index_name + ) { + $was_index_name = $index_name; + } + if (!empty($previous_definition[$was_index_name])) { + $change = array(); + if ($was_index_name != $index_name) { + $change['name'] = $was_index_name; + } + + if (!empty($defined_indexes[$was_index_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'the index "'.$was_index_name.'" was specified for'. + ' more than one index of table "'.$table_name.'"'); + } + $defined_indexes[$was_index_name] = true; + + $previous_unique = array_key_exists('unique', $previous_definition[$was_index_name]) + ? $previous_definition[$was_index_name]['unique'] : false; + + $unique = array_key_exists('unique', $index) ? $index['unique'] : false; + if ($previous_unique != $unique) { + $change['unique'] = $unique; + } + + $previous_primary = array_key_exists('primary', $previous_definition[$was_index_name]) + ? $previous_definition[$was_index_name]['primary'] : false; + + $primary = array_key_exists('primary', $index) ? $index['primary'] : false; + if ($previous_primary != $primary) { + $change['primary'] = $primary; + } + + $defined_fields = array(); + $previous_fields = $previous_definition[$was_index_name]['fields']; + if (!empty($index['fields']) && is_array($index['fields'])) { + foreach ($index['fields'] as $field_name => $field) { + if (!empty($previous_fields[$field_name])) { + $defined_fields[$field_name] = true; + + $previous_sorting = array_key_exists('sorting', $previous_fields[$field_name]) + ? $previous_fields[$field_name]['sorting'] : ''; + + $sorting = array_key_exists('sorting', $field) ? $field['sorting'] : ''; + if ($previous_sorting != $sorting) { + $change['change'] = true; + } + } else { + $change['change'] = true; + } + } + } + if (isset($previous_fields) && is_array($previous_fields)) { + foreach ($previous_fields as $field_name => $field) { + if (empty($defined_fields[$field_name])) { + $change['change'] = true; + } + } + } + if (!empty($change)) { + $changes['change'][$index_name] = $current_definition[$index_name]; + } + } else { + if ($index_name != $was_index_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'it was specified a previous index name ("'.$was_index_name. + ') for index "'.$index_name.'" of table "'.$table_name.'" that does not exist'); + } + $changes['add'][$index_name] = $current_definition[$index_name]; + } + } + } + foreach ($previous_definition as $index_previous_name => $index_previous) { + if (empty($defined_indexes[$index_previous_name])) { + $changes['remove'][$index_previous_name] = $index_previous; + } + } + return $changes; + } + + // }}} + // {{{ compareTableDefinitions() + + /** + * Compare a previous definition with the currently parsed definition + * + * @param string $table_name name of the table + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * @param array &$defined_tables table names in the schema + * + * @return array|MDB2_Error array of changes on success, or a error object + * @access public + */ + function compareTableDefinitions($table_name, $current_definition, + $previous_definition, &$defined_tables) + { + $changes = array(); + + if (is_array($current_definition)) { + $was_table_name = $table_name; + if (!empty($current_definition['was'])) { + $was_table_name = $current_definition['was']; + } + if (!empty($previous_definition[$was_table_name])) { + $changes['change'][$was_table_name] = array(); + if ($was_table_name != $table_name) { + $changes['change'][$was_table_name] = array('name' => $table_name); + } + if (!empty($defined_tables[$was_table_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'the table "'.$was_table_name. + '" was specified for more than one table of the database'); + } + $defined_tables[$was_table_name] = true; + if (!empty($current_definition['fields']) && is_array($current_definition['fields'])) { + $previous_fields = array(); + if (isset($previous_definition[$was_table_name]['fields']) + && is_array($previous_definition[$was_table_name]['fields'])) { + $previous_fields = $previous_definition[$was_table_name]['fields']; + } + + $change = $this->compareTableFieldsDefinitions($table_name, + $current_definition['fields'], + $previous_fields); + + if (PEAR::isError($change)) { + return $change; + } + if (!empty($change)) { + $changes['change'][$was_table_name] = + MDB2_Schema::arrayMergeClobber($changes['change'][$was_table_name], $change); + } + } + if (!empty($current_definition['indexes']) && is_array($current_definition['indexes'])) { + $previous_indexes = array(); + if (isset($previous_definition[$was_table_name]['indexes']) + && is_array($previous_definition[$was_table_name]['indexes'])) { + $previous_indexes = $previous_definition[$was_table_name]['indexes']; + } + $change = $this->compareTableIndexesDefinitions($table_name, + $current_definition['indexes'], + $previous_indexes); + + if (PEAR::isError($change)) { + return $change; + } + if (!empty($change)) { + $changes['change'][$was_table_name]['indexes'] = $change; + } + } + if (empty($changes['change'][$was_table_name])) { + unset($changes['change'][$was_table_name]); + } + if (empty($changes['change'])) { + unset($changes['change']); + } + } else { + if ($table_name != $was_table_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'it was specified a previous table name ("'.$was_table_name. + '") for table "'.$table_name.'" that does not exist'); + } + $changes['add'][$table_name] = true; + } + } + + return $changes; + } + + // }}} + // {{{ compareSequenceDefinitions() + + /** + * Compare a previous definition with the currently parsed definition + * + * @param string $sequence_name name of the sequence + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * @param array &$defined_sequences names in the schema + * + * @return array|MDB2_Error array of changes on success, or a error object + * @access public + */ + function compareSequenceDefinitions($sequence_name, $current_definition, + $previous_definition, &$defined_sequences) + { + $changes = array(); + + if (is_array($current_definition)) { + $was_sequence_name = $sequence_name; + if (!empty($previous_definition[$sequence_name]) + && isset($previous_definition[$sequence_name]['was']) + && $previous_definition[$sequence_name]['was'] == $was_sequence_name + ) { + $was_sequence_name = $sequence_name; + } elseif (!empty($current_definition['was'])) { + $was_sequence_name = $current_definition['was']; + } + if (!empty($previous_definition[$was_sequence_name])) { + if ($was_sequence_name != $sequence_name) { + $changes['change'][$was_sequence_name]['name'] = $sequence_name; + } + + if (!empty($defined_sequences[$was_sequence_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'the sequence "'.$was_sequence_name.'" was specified as base'. + ' of more than of sequence of the database'); + } + + $defined_sequences[$was_sequence_name] = true; + + $change = array(); + if (!empty($current_definition['start']) + && isset($previous_definition[$was_sequence_name]['start']) + && $current_definition['start'] != $previous_definition[$was_sequence_name]['start'] + ) { + $change['start'] = $previous_definition[$sequence_name]['start']; + } + if (isset($current_definition['on']['table']) + && isset($previous_definition[$was_sequence_name]['on']['table']) + && $current_definition['on']['table'] != $previous_definition[$was_sequence_name]['on']['table'] + && isset($current_definition['on']['field']) + && isset($previous_definition[$was_sequence_name]['on']['field']) + && $current_definition['on']['field'] != $previous_definition[$was_sequence_name]['on']['field'] + ) { + $change['on'] = $current_definition['on']; + } + if (!empty($change)) { + $changes['change'][$was_sequence_name][$sequence_name] = $change; + } + } else { + if ($sequence_name != $was_sequence_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_INVALID, null, null, + 'it was specified a previous sequence name ("'.$was_sequence_name. + '") for sequence "'.$sequence_name.'" that does not exist'); + } + $changes['add'][$sequence_name] = true; + } + } + return $changes; + } + // }}} + // {{{ verifyAlterDatabase() + + /** + * Verify that the changes requested are supported + * + * @param array $changes associative array that contains the definition of the changes + * that are meant to be applied to the database structure. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function verifyAlterDatabase($changes) + { + if (!empty($changes['tables']['change']) && is_array($changes['tables']['change'])) { + foreach ($changes['tables']['change'] as $table_name => $table) { + if (!empty($table['indexes']) && is_array($table['indexes'])) { + if (!$this->db->supports('indexes')) { + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + 'indexes are not supported'); + } + $table_changes = count($table['indexes']); + if (!empty($table['indexes']['add'])) { + $table_changes--; + } + if (!empty($table['indexes']['remove'])) { + $table_changes--; + } + if (!empty($table['indexes']['change'])) { + $table_changes--; + } + if ($table_changes) { + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + 'index alteration not yet supported: '.implode(', ', array_keys($table['indexes']))); + } + } + unset($table['indexes']); + $result = $this->db->manager->alterTable($table_name, $table, true); + if (PEAR::isError($result)) { + return $result; + } + } + } + if (!empty($changes['sequences']) && is_array($changes['sequences'])) { + if (!$this->db->supports('sequences')) { + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + 'sequences are not supported'); + } + $sequence_changes = count($changes['sequences']); + if (!empty($changes['sequences']['add'])) { + $sequence_changes--; + } + if (!empty($changes['sequences']['remove'])) { + $sequence_changes--; + } + if (!empty($changes['sequences']['change'])) { + $sequence_changes--; + } + if ($sequence_changes) { + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + 'sequence alteration not yet supported: '.implode(', ', array_keys($changes['sequences']))); + } + } + return MDB2_OK; + } + + // }}} + // {{{ alterDatabaseIndexes() + + /** + * Execute the necessary actions to implement the requested changes + * in the indexes inside a database structure. + * + * @param string $table_name name of the table + * @param array $changes associative array that contains the definition of the changes + * that are meant to be applied to the database structure. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function alterDatabaseIndexes($table_name, $changes) + { + $alterations = 0; + if (empty($changes)) { + return $alterations; + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $index_name => $index) { + $this->db->expectError(MDB2_ERROR_NOT_FOUND); + if (!empty($index['primary']) || !empty($index['unique'])) { + $result = $this->db->manager->dropConstraint($table_name, $index_name, !empty($index['primary'])); + } else { + $result = $this->db->manager->dropIndex($table_name, $index_name); + } + $this->db->popExpect(); + if (PEAR::isError($result) && !MDB2::isError($result, MDB2_ERROR_NOT_FOUND)) { + return $result; + } + $alterations++; + } + } + if (!empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $index_name => $index) { + /** + * Drop existing index/constraint first. + * Since $changes doesn't tell us whether it's an index or a constraint before the change, + * we have to find out and call the appropriate method. + */ + if (in_array($index_name, $this->db->manager->listTableIndexes($table_name))) { + $result = $this->db->manager->dropIndex($table_name, $index_name); + } elseif (in_array($index_name, $this->db->manager->listTableConstraints($table_name))) { + $result = $this->db->manager->dropConstraint($table_name, $index_name); + } + if (!empty($result) && PEAR::isError($result)) { + return $result; + } + + if (!empty($index['primary']) || !empty($index['unique'])) { + $result = $this->db->manager->createConstraint($table_name, $index_name, $index); + } else { + $result = $this->db->manager->createIndex($table_name, $index_name, $index); + } + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $index_name => $index) { + if (!empty($index['primary']) || !empty($index['unique'])) { + $result = $this->db->manager->createConstraint($table_name, $index_name, $index); + } else { + $result = $this->db->manager->createIndex($table_name, $index_name, $index); + } + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + + return $alterations; + } + + // }}} + // {{{ alterDatabaseTables() + + /** + * Execute the necessary actions to implement the requested changes + * in the tables inside a database structure. + * + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * @param array $changes associative array that contains the definition of the changes + * that are meant to be applied to the database structure. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function alterDatabaseTables($current_definition, $previous_definition, $changes) + { + /* FIXME: tables marked to be added are initialized by createTable(), others don't */ + $alterations = 0; + if (empty($changes)) { + return $alterations; + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $table_name => $table) { + $result = $this->createTable($table_name, $current_definition[$table_name]); + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + + if ($this->options['drop_missing_tables'] + && !empty($changes['remove']) + && is_array($changes['remove'])) { + foreach ($changes['remove'] as $table_name => $table) { + $result = $this->db->manager->dropTable($table_name); + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $table_name => $table) { + $indexes = array(); + if (!empty($table['indexes'])) { + $indexes = $table['indexes']; + unset($table['indexes']); + } + if (!empty($indexes['remove'])) { + $result = $this->alterDatabaseIndexes($table_name, array('remove' => $indexes['remove'])); + if (PEAR::isError($result)) { + return $result; + } + unset($indexes['remove']); + $alterations += $result; + } + $result = $this->db->manager->alterTable($table_name, $table, false); + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + + // table may be renamed at this point + if (!empty($table['name'])) { + $table_name = $table['name']; + } + + if (!empty($indexes)) { + $result = $this->alterDatabaseIndexes($table_name, $indexes); + if (PEAR::isError($result)) { + return $result; + } + $alterations += $result; + } + } + } + + return $alterations; + } + + // }}} + // {{{ alterDatabaseSequences() + + /** + * Execute the necessary actions to implement the requested changes + * in the sequences inside a database structure. + * + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * @param array $changes associative array that contains the definition of the changes + * that are meant to be applied to the database structure. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function alterDatabaseSequences($current_definition, $previous_definition, $changes) + { + $alterations = 0; + if (empty($changes)) { + return $alterations; + } + + if (!empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $sequence_name => $sequence) { + $result = $this->createSequence($sequence_name, $current_definition[$sequence_name]); + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + + if (!empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $sequence_name => $sequence) { + $result = $this->db->manager->dropSequence($sequence_name); + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + + if (!empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $sequence_name => $sequence) { + $result = $this->db->manager->dropSequence($previous_definition[$sequence_name]['was']); + if (PEAR::isError($result)) { + return $result; + } + $result = $this->createSequence($sequence_name, $sequence); + if (PEAR::isError($result)) { + return $result; + } + $alterations++; + } + } + + return $alterations; + } + + // }}} + // {{{ alterDatabase() + + /** + * Execute the necessary actions to implement the requested changes + * in a database structure. + * + * @param array $current_definition multi dimensional array that contains the current definition + * @param array $previous_definition multi dimensional array that contains the previous definition + * @param array $changes associative array that contains the definition of the changes + * that are meant to be applied to the database structure. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function alterDatabase($current_definition, $previous_definition, $changes) + { + $alterations = 0; + if (empty($changes)) { + return $alterations; + } + + $result = $this->verifyAlterDatabase($changes); + if (PEAR::isError($result)) { + return $result; + } + + if (!empty($current_definition['name'])) { + $previous_database_name = $this->db->setDatabase($current_definition['name']); + } + + if (($support_transactions = $this->db->supports('transactions')) + && PEAR::isError($result = $this->db->beginNestedTransaction()) + ) { + return $result; + } + + if (!empty($changes['tables']) && !empty($current_definition['tables'])) { + $current_tables = isset($current_definition['tables']) ? $current_definition['tables'] : array(); + $previous_tables = isset($previous_definition['tables']) ? $previous_definition['tables'] : array(); + + $result = $this->alterDatabaseTables($current_tables, $previous_tables, $changes['tables']); + if (is_numeric($result)) { + $alterations += $result; + } + } + + if (!PEAR::isError($result) && !empty($changes['sequences'])) { + $current_sequences = isset($current_definition['sequences']) ? $current_definition['sequences'] : array(); + $previous_sequences = isset($previous_definition['sequences']) ? $previous_definition['sequences'] : array(); + + $result = $this->alterDatabaseSequences($current_sequences, $previous_sequences, $changes['sequences']); + if (is_numeric($result)) { + $alterations += $result; + } + } + + if ($support_transactions) { + $res = $this->db->completeNestedTransaction(); + if (PEAR::isError($res)) { + $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'Could not end transaction ('. + $res->getMessage().' ('.$res->getUserinfo().'))'); + } + } elseif (PEAR::isError($result) && $alterations) { + $result = $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'the requested database alterations were only partially implemented ('. + $result->getMessage().' ('.$result->getUserinfo().'))'); + } + + if (isset($previous_database_name)) { + $this->db->setDatabase($previous_database_name); + } + return $result; + } + + // }}} + // {{{ dumpDatabaseChanges() + + /** + * Dump the changes between two database definitions. + * + * @param array $changes associative array that specifies the list of database + * definitions changes as returned by the _compareDefinitions + * manager class function. + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function dumpDatabaseChanges($changes) + { + if (!empty($changes['tables'])) { + if (!empty($changes['tables']['add']) && is_array($changes['tables']['add'])) { + foreach ($changes['tables']['add'] as $table_name => $table) { + $this->db->debug("$table_name:", __FUNCTION__); + $this->db->debug("\tAdded table '$table_name'", __FUNCTION__); + } + } + + if (!empty($changes['tables']['remove']) && is_array($changes['tables']['remove'])) { + if ($this->options['drop_missing_tables']) { + foreach ($changes['tables']['remove'] as $table_name => $table) { + $this->db->debug("$table_name:", __FUNCTION__); + $this->db->debug("\tRemoved table '$table_name'", __FUNCTION__); + } + } else { + foreach ($changes['tables']['remove'] as $table_name => $table) { + $this->db->debug("\tObsolete table '$table_name' left as is", __FUNCTION__); + } + } + } + + if (!empty($changes['tables']['change']) && is_array($changes['tables']['change'])) { + foreach ($changes['tables']['change'] as $table_name => $table) { + if (array_key_exists('name', $table)) { + $this->db->debug("\tRenamed table '$table_name' to '".$table['name']."'", __FUNCTION__); + } + if (!empty($table['add']) && is_array($table['add'])) { + foreach ($table['add'] as $field_name => $field) { + $this->db->debug("\tAdded field '".$field_name."'", __FUNCTION__); + } + } + if (!empty($table['remove']) && is_array($table['remove'])) { + foreach ($table['remove'] as $field_name => $field) { + $this->db->debug("\tRemoved field '".$field_name."'", __FUNCTION__); + } + } + if (!empty($table['rename']) && is_array($table['rename'])) { + foreach ($table['rename'] as $field_name => $field) { + $this->db->debug("\tRenamed field '".$field_name."' to '".$field['name']."'", __FUNCTION__); + } + } + if (!empty($table['change']) && is_array($table['change'])) { + foreach ($table['change'] as $field_name => $field) { + $field = $field['definition']; + if (array_key_exists('type', $field)) { + $this->db->debug("\tChanged field '$field_name' type to '".$field['type']."'", __FUNCTION__); + } + + if (array_key_exists('unsigned', $field)) { + $this->db->debug("\tChanged field '$field_name' type to '". + (!empty($field['unsigned']) && $field['unsigned'] ? '' : 'not ')."unsigned'", + __FUNCTION__); + } + + if (array_key_exists('length', $field)) { + $this->db->debug("\tChanged field '$field_name' length to '". + (!empty($field['length']) ? $field['length']: 'no length')."'", __FUNCTION__); + } + if (array_key_exists('default', $field)) { + $this->db->debug("\tChanged field '$field_name' default to ". + (isset($field['default']) ? "'".$field['default']."'" : 'NULL'), __FUNCTION__); + } + + if (array_key_exists('notnull', $field)) { + $this->db->debug("\tChanged field '$field_name' notnull to ". + (!empty($field['notnull']) && $field['notnull'] ? 'true' : 'false'), + __FUNCTION__); + } + } + } + if (!empty($table['indexes']) && is_array($table['indexes'])) { + if (!empty($table['indexes']['add']) && is_array($table['indexes']['add'])) { + foreach ($table['indexes']['add'] as $index_name => $index) { + $this->db->debug("\tAdded index '".$index_name. + "' of table '$table_name'", __FUNCTION__); + } + } + if (!empty($table['indexes']['remove']) && is_array($table['indexes']['remove'])) { + foreach ($table['indexes']['remove'] as $index_name => $index) { + $this->db->debug("\tRemoved index '".$index_name. + "' of table '$table_name'", __FUNCTION__); + } + } + if (!empty($table['indexes']['change']) && is_array($table['indexes']['change'])) { + foreach ($table['indexes']['change'] as $index_name => $index) { + if (array_key_exists('name', $index)) { + $this->db->debug("\tRenamed index '".$index_name."' to '".$index['name']. + "' on table '$table_name'", __FUNCTION__); + } + if (array_key_exists('unique', $index)) { + $this->db->debug("\tChanged index '".$index_name."' unique to '". + !empty($index['unique'])."' on table '$table_name'", __FUNCTION__); + } + if (array_key_exists('primary', $index)) { + $this->db->debug("\tChanged index '".$index_name."' primary to '". + !empty($index['primary'])."' on table '$table_name'", __FUNCTION__); + } + if (array_key_exists('change', $index)) { + $this->db->debug("\tChanged index '".$index_name. + "' on table '$table_name'", __FUNCTION__); + } + } + } + } + } + } + } + if (!empty($changes['sequences'])) { + if (!empty($changes['sequences']['add']) && is_array($changes['sequences']['add'])) { + foreach ($changes['sequences']['add'] as $sequence_name => $sequence) { + $this->db->debug("$sequence_name:", __FUNCTION__); + $this->db->debug("\tAdded sequence '$sequence_name'", __FUNCTION__); + } + } + if (!empty($changes['sequences']['remove']) && is_array($changes['sequences']['remove'])) { + foreach ($changes['sequences']['remove'] as $sequence_name => $sequence) { + $this->db->debug("$sequence_name:", __FUNCTION__); + $this->db->debug("\tAdded sequence '$sequence_name'", __FUNCTION__); + } + } + if (!empty($changes['sequences']['change']) && is_array($changes['sequences']['change'])) { + foreach ($changes['sequences']['change'] as $sequence_name => $sequence) { + if (array_key_exists('name', $sequence)) { + $this->db->debug("\tRenamed sequence '$sequence_name' to '". + $sequence['name']."'", __FUNCTION__); + } + if (!empty($sequence['change']) && is_array($sequence['change'])) { + foreach ($sequence['change'] as $sequence_name => $sequence) { + if (array_key_exists('start', $sequence)) { + $this->db->debug("\tChanged sequence '$sequence_name' start to '". + $sequence['start']."'", __FUNCTION__); + } + } + } + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ dumpDatabase() + + /** + * Dump a previously parsed database structure in the Metabase schema + * XML based format suitable for the Metabase parser. This function + * may optionally dump the database definition with initialization + * commands that specify the data that is currently present in the tables. + * + * @param array $database_definition multi dimensional array that contains the current definition + * @param array $arguments associative array that takes pairs of tag + * names and values that define dump options. + *
array (
+     *                     'output_mode'    =>    String
+     *                         'file' :   dump into a file
+     *                         default:   dump using a function
+     *                     'output'        =>    String
+     *                         depending on the 'Output_Mode'
+     *                                  name of the file
+     *                                  name of the function
+     *                     'end_of_line'        =>    String
+     *                         end of line delimiter that should be used
+     *                         default: "\n"
+     *                 );
+ * @param int $dump Int that determines what data to dump + * + MDB2_SCHEMA_DUMP_ALL : the entire db + * + MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db + * + MDB2_SCHEMA_DUMP_CONTENT : only the content of the db + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function dumpDatabase($database_definition, $arguments, $dump = MDB2_SCHEMA_DUMP_ALL) + { + $class_name = $this->options['writer']; + + $result = MDB2::loadClass($class_name, $this->db->getOption('debug')); + if (PEAR::isError($result)) { + return $result; + } + + // get initialization data + if (isset($database_definition['tables']) && is_array($database_definition['tables']) + && $dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT + ) { + foreach ($database_definition['tables'] as $table_name => $table) { + $fields = array(); + $fieldsq = array(); + foreach ($table['fields'] as $field_name => $field) { + $fields[$field_name] = $field['type']; + + $fieldsq[] = $this->db->quoteIdentifier($field_name, true); + } + + $query = 'SELECT '.implode(', ', $fieldsq).' FROM '; + $query .= $this->db->quoteIdentifier($table_name, true); + + $data = $this->db->queryAll($query, $fields, MDB2_FETCHMODE_ASSOC); + + if (PEAR::isError($data)) { + return $data; + } + + if (!empty($data)) { + $initialization = array(); + $lob_buffer_length = $this->db->getOption('lob_buffer_length'); + foreach ($data as $row) { + $rows = array(); + foreach ($row as $key => $lob) { + if (is_resource($lob)) { + $value = ''; + while (!feof($lob)) { + $value .= fread($lob, $lob_buffer_length); + } + $row[$key] = $value; + } + $rows[] = array('name' => $key, 'group' => array('type' => 'value', 'data' => $row[$key])); + } + $initialization[] = array('type' => 'insert', 'data' => array('field' => $rows)); + } + $database_definition['tables'][$table_name]['initialization'] = $initialization; + } + } + } + + $writer =& new $class_name($this->options['valid_types']); + return $writer->dumpDatabase($database_definition, $arguments, $dump); + } + + // }}} + // {{{ writeInitialization() + + /** + * Write initialization and sequences + * + * @param string|array $data data file or data array + * @param string|array $structure structure file or array + * @param array $variables associative array that is passed to the argument + * of the same name to the parseDatabaseDefinitionFile function. (there third + * param) + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function writeInitialization($data, $structure = false, $variables = array()) + { + if ($structure) { + $structure = $this->parseDatabaseDefinition($structure, false, $variables); + if (PEAR::isError($structure)) { + return $structure; + } + } + + $data = $this->parseDatabaseDefinition($data, false, $variables, false, $structure); + if (PEAR::isError($data)) { + return $data; + } + + $previous_database_name = null; + if (!empty($data['name'])) { + $previous_database_name = $this->db->setDatabase($data['name']); + } elseif (!empty($structure['name'])) { + $previous_database_name = $this->db->setDatabase($structure['name']); + } + + if (!empty($data['tables']) && is_array($data['tables'])) { + foreach ($data['tables'] as $table_name => $table) { + if (empty($table['initialization'])) { + continue; + } + $result = $this->initializeTable($table_name, $table); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (!empty($structure['sequences']) && is_array($structure['sequences'])) { + foreach ($structure['sequences'] as $sequence_name => $sequence) { + if (isset($data['sequences'][$sequence_name]) + || !isset($sequence['on']['table']) + || !isset($data['tables'][$sequence['on']['table']]) + ) { + continue; + } + $result = $this->createSequence($sequence_name, $sequence, true); + if (PEAR::isError($result)) { + return $result; + } + } + } + if (!empty($data['sequences']) && is_array($data['sequences'])) { + foreach ($data['sequences'] as $sequence_name => $sequence) { + $result = $this->createSequence($sequence_name, $sequence, true); + if (PEAR::isError($result)) { + return $result; + } + } + } + + if (isset($previous_database_name)) { + $this->db->setDatabase($previous_database_name); + } + + return MDB2_OK; + } + + // }}} + // {{{ updateDatabase() + + /** + * Compare the correspondent files of two versions of a database schema + * definition: the previously installed and the one that defines the schema + * that is meant to update the database. + * If the specified previous definition file does not exist, this function + * will create the database from the definition specified in the current + * schema file. + * If both files exist, the function assumes that the database was previously + * installed based on the previous schema file and will update it by just + * applying the changes. + * If this function succeeds, the contents of the current schema file are + * copied to replace the previous schema file contents. Any subsequent schema + * changes should only be done on the file specified by the $current_schema_file + * to let this function make a consistent evaluation of the exact changes that + * need to be applied. + * + * @param string|array $current_schema filename or array of the updated database schema definition. + * @param string|array $previous_schema filename or array of the previously installed database schema definition. + * @param array $variables associative array that is passed to the argument of the same + * name to the parseDatabaseDefinitionFile function. (there third param) + * @param bool $disable_query determines if the disable_query option should be set to true + * for the alterDatabase() or createDatabase() call + * @param bool $overwrite_old_schema_file Overwrite? + * + * @return bool|MDB2_Error MDB2_OK or error object + * @access public + */ + function updateDatabase($current_schema, $previous_schema = false, + $variables = array(), $disable_query = false, + $overwrite_old_schema_file = false) + { + $current_definition = $this->parseDatabaseDefinition($current_schema, false, $variables, + $this->options['fail_on_invalid_names']); + + if (PEAR::isError($current_definition)) { + return $current_definition; + } + + $previous_definition = false; + if ($previous_schema) { + $previous_definition = $this->parseDatabaseDefinition($previous_schema, true, $variables, + $this->options['fail_on_invalid_names']); + if (PEAR::isError($previous_definition)) { + return $previous_definition; + } + } + + if ($previous_definition) { + $dbExists = $this->db->databaseExists($current_definition['name']); + if (PEAR::isError($dbExists)) { + return $dbExists; + } + + if (!$dbExists) { + return $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'database to update does not exist: '.$current_definition['name']); + } + + $changes = $this->compareDefinitions($current_definition, $previous_definition); + if (PEAR::isError($changes)) { + return $changes; + } + + if (is_array($changes)) { + $this->db->setOption('disable_query', $disable_query); + $result = $this->alterDatabase($current_definition, $previous_definition, $changes); + $this->db->setOption('disable_query', false); + if (PEAR::isError($result)) { + return $result; + } + $copy = true; + if ($this->db->options['debug']) { + $result = $this->dumpDatabaseChanges($changes); + if (PEAR::isError($result)) { + return $result; + } + } + } + } else { + $this->db->setOption('disable_query', $disable_query); + $result = $this->createDatabase($current_definition); + $this->db->setOption('disable_query', false); + if (PEAR::isError($result)) { + return $result; + } + } + + if ($overwrite_old_schema_file + && !$disable_query + && is_string($previous_schema) && is_string($current_schema) + && !copy($current_schema, $previous_schema)) { + + return $this->raiseError(MDB2_SCHEMA_ERROR, null, null, + 'Could not copy the new database definition file to the current file'); + } + + return MDB2_OK; + } + // }}} + // {{{ errorMessage() + + /** + * Return a textual error message for a MDB2 error code + * + * @param int|array $value integer error code, null to get the + * current error code-message map, + * or an array with a new error code-message map + * + * @return string error message, or false if the error code was not recognized + * @access public + */ + function errorMessage($value = null) + { + static $errorMessages; + if (is_array($value)) { + $errorMessages = $value; + return MDB2_OK; + } elseif (!isset($errorMessages)) { + $errorMessages = array( + MDB2_SCHEMA_ERROR => 'unknown error', + MDB2_SCHEMA_ERROR_PARSE => 'schema parse error', + MDB2_SCHEMA_ERROR_VALIDATE => 'schema validation error', + MDB2_SCHEMA_ERROR_INVALID => 'invalid', + MDB2_SCHEMA_ERROR_UNSUPPORTED => 'not supported', + MDB2_SCHEMA_ERROR_WRITER => 'schema writer error', + ); + } + + if (is_null($value)) { + return $errorMessages; + } + + if (PEAR::isError($value)) { + $value = $value->getCode(); + } + + return !empty($errorMessages[$value]) ? + $errorMessages[$value] : $errorMessages[MDB2_SCHEMA_ERROR]; + } + + // }}} + // {{{ raiseError() + + /** + * This method is used to communicate an error and invoke error + * callbacks etc. Basically a wrapper for PEAR::raiseError + * without the message string. + * + * @param int|PEAR_Error $code integer error code or and PEAR_Error instance + * @param int $mode error mode, see PEAR_Error docs + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * @param array $options Options, depending on the mode, @see PEAR::setErrorHandling + * @param string $userinfo Extra debug information. Defaults to the last + * query and native error code. + * + * @return object a PEAR error object + * @access public + * @see PEAR_Error + */ + function &raiseError($code = null, $mode = null, $options = null, $userinfo = null) + { + $err =& PEAR::raiseError(null, $code, $mode, $options, + $userinfo, 'MDB2_Schema_Error', true); + return $err; + } + + // }}} + // {{{ isError() + + /** + * Tell whether a value is an MDB2_Schema error. + * + * @param mixed $data the value to test + * @param int $code if $data is an error object, return true only if $code is + * a string and $db->getMessage() == $code or + * $code is an integer and $db->getCode() == $code + * + * @return bool true if parameter is an error + * @access public + */ + function isError($data, $code = null) + { + if (is_a($data, 'MDB2_Schema_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() === $code; + } else { + $code = (array)$code; + return in_array($data->getCode(), $code); + } + } + return false; + } + + // }}} +} + +/** + * MDB2_Schema_Error implements a class for reporting portable database error + * messages. + * + * @category Database + * @package MDB2_Schema + * @author Stig Bakken + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema_Error extends PEAR_Error +{ + /** + * MDB2_Schema_Error constructor. + * + * @param mixed $code error code, or string with error message. + * @param int $mode what 'error mode' to operate in + * @param int $level what error level to use for $mode & PEAR_ERROR_TRIGGER + * @param mixed $debuginfo additional debug info, such as the last query + * + * @access public + */ + function MDB2_Schema_Error($code = MDB2_SCHEMA_ERROR, $mode = PEAR_ERROR_RETURN, + $level = E_USER_NOTICE, $debuginfo = null) + { + $this->PEAR_Error('MDB2_Schema Error: ' . MDB2_Schema::errorMessage($code), $code, + $mode, $level, $debuginfo); + } +} +?> diff --git a/lib/Pear/MDB2/Schema/Parser.php b/lib/Pear/MDB2/Schema/Parser.php new file mode 100644 index 0000000..9e8e74b --- /dev/null +++ b/lib/Pear/MDB2/Schema/Parser.php @@ -0,0 +1,819 @@ + + * Author: Igor Feghali + * + * $Id: Parser.php,v 1.68 2008/11/30 03:34:00 clockwerx Exp $ + * + * @category Database + * @package MDB2_Schema + * @author Christian Dickmann + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id: Parser.php,v 1.68 2008/11/30 03:34:00 clockwerx Exp $ + * @link http://pear.php.net/packages/MDB2_Schema + */ + + +require_once 'XML/Parser.php'; +require_once 'MDB2/Schema/Validate.php'; + +/** + * Parses an XML schema file + * + * @category Database + * @package MDB2_Schema + * @author Christian Dickmann + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema_Parser extends XML_Parser +{ + var $database_definition = array(); + + var $elements = array(); + + var $element = ''; + + var $count = 0; + + var $table = array(); + + var $table_name = ''; + + var $field = array(); + + var $field_name = ''; + + var $init = array(); + + var $init_function = array(); + + var $init_expression = array(); + + var $init_field = array(); + + var $index = array(); + + var $index_name = ''; + + var $constraint = array(); + + var $constraint_name = ''; + + var $var_mode = false; + + var $variables = array(); + + var $sequence = array(); + + var $sequence_name = ''; + + var $error; + + var $structure = false; + + var $val; + + function __construct($variables, $fail_on_invalid_names = true, + $structure = false, $valid_types = array(), + $force_defaults = true) + { + // force ISO-8859-1 due to different defaults for PHP4 and PHP5 + // todo: this probably needs to be investigated some more andcleaned up + parent::XML_Parser('ISO-8859-1'); + + $this->variables = $variables; + $this->structure = $structure; + $this->val =& new MDB2_Schema_Validate($fail_on_invalid_names, $valid_types, $force_defaults); + } + + function MDB2_Schema_Parser($variables, $fail_on_invalid_names = true, + $structure = false, $valid_types = array(), + $force_defaults = true) + { + $this->__construct($variables, $fail_on_invalid_names, $structure, $valid_types, $force_defaults); + } + + function startHandler($xp, $element, $attribs) + { + if (strtolower($element) == 'variable') { + $this->var_mode = true; + return; + } + + $this->elements[$this->count++] = strtolower($element); + + $this->element = implode('-', $this->elements); + + switch ($this->element) { + /* Initialization */ + case 'database-table-initialization': + $this->table['initialization'] = array(); + break; + + /* Insert */ + /* insert: field+ */ + case 'database-table-initialization-insert': + $this->init = array('type' => 'insert', 'data' => array('field' => array())); + break; + /* insert-select: field+, table, where? */ + case 'database-table-initialization-insert-select': + $this->init['data']['table'] = ''; + break; + + /* Update */ + /* update: field+, where? */ + case 'database-table-initialization-update': + $this->init = array('type' => 'update', 'data' => array('field' => array())); + break; + + /* Delete */ + /* delete: where */ + case 'database-table-initialization-delete': + $this->init = array('type' => 'delete', 'data' => array('where' => array())); + break; + + /* Insert and Update */ + case 'database-table-initialization-insert-field': + case 'database-table-initialization-insert-select-field': + case 'database-table-initialization-update-field': + $this->init_field = array('name' => '', 'group' => array()); + break; + case 'database-table-initialization-insert-field-value': + case 'database-table-initialization-insert-select-field-value': + case 'database-table-initialization-update-field-value': + /* if value tag is empty cdataHandler is not called so we must force value element creation here */ + $this->init_field['group'] = array('type' => 'value', 'data' => ''); + break; + case 'database-table-initialization-insert-field-null': + case 'database-table-initialization-insert-select-field-null': + case 'database-table-initialization-update-field-null': + $this->init_field['group'] = array('type' => 'null'); + break; + case 'database-table-initialization-insert-field-function': + case 'database-table-initialization-insert-select-field-function': + case 'database-table-initialization-update-field-function': + $this->init_function = array('name' => ''); + break; + case 'database-table-initialization-insert-field-expression': + case 'database-table-initialization-insert-select-field-expression': + case 'database-table-initialization-update-field-expression': + $this->init_expression = array(); + break; + + /* All */ + case 'database-table-initialization-insert-select-where': + case 'database-table-initialization-update-where': + case 'database-table-initialization-delete-where': + $this->init['data']['where'] = array('type' => '', 'data' => array()); + break; + case 'database-table-initialization-insert-select-where-expression': + case 'database-table-initialization-update-where-expression': + case 'database-table-initialization-delete-where-expression': + $this->init_expression = array(); + break; + + /* One level simulation of expression-function recursion */ + case 'database-table-initialization-insert-field-expression-function': + case 'database-table-initialization-insert-select-field-expression-function': + case 'database-table-initialization-insert-select-where-expression-function': + case 'database-table-initialization-update-field-expression-function': + case 'database-table-initialization-update-where-expression-function': + case 'database-table-initialization-delete-where-expression-function': + $this->init_function = array('name' => ''); + break; + + /* One level simulation of function-expression recursion */ + case 'database-table-initialization-insert-field-function-expression': + case 'database-table-initialization-insert-select-field-function-expression': + case 'database-table-initialization-insert-select-where-function-expression': + case 'database-table-initialization-update-field-function-expression': + case 'database-table-initialization-update-where-function-expression': + case 'database-table-initialization-delete-where-function-expression': + $this->init_expression = array(); + break; + + /* Definition */ + case 'database': + $this->database_definition = array( + 'name' => '', + 'create' => '', + 'overwrite' => '', + 'charset' => '', + 'description' => '', + 'comments' => '', + 'tables' => array(), + 'sequences' => array() + ); + break; + case 'database-table': + $this->table_name = ''; + + $this->table = array( + 'was' => '', + 'description' => '', + 'comments' => '', + 'fields' => array(), + 'indexes' => array(), + 'constraints' => array(), + 'initialization' => array() + ); + break; + case 'database-table-declaration-field': + case 'database-table-declaration-foreign-field': + case 'database-table-declaration-foreign-references-field': + $this->field_name = ''; + + $this->field = array(); + break; + case 'database-table-declaration-index-field': + $this->field_name = ''; + + $this->field = array('sorting' => '', 'length' => ''); + break; + /* force field attributes to be initialized when the tag is empty in the XML */ + case 'database-table-declaration-field-was': + $this->field['was'] = ''; + break; + case 'database-table-declaration-field-type': + $this->field['type'] = ''; + break; + case 'database-table-declaration-field-fixed': + $this->field['fixed'] = ''; + break; + case 'database-table-declaration-field-default': + $this->field['default'] = ''; + break; + case 'database-table-declaration-field-notnull': + $this->field['notnull'] = ''; + break; + case 'database-table-declaration-field-autoincrement': + $this->field['autoincrement'] = ''; + break; + case 'database-table-declaration-field-unsigned': + $this->field['unsigned'] = ''; + break; + case 'database-table-declaration-field-length': + $this->field['length'] = ''; + break; + case 'database-table-declaration-field-description': + $this->field['description'] = ''; + break; + case 'database-table-declaration-field-comments': + $this->field['comments'] = ''; + break; + case 'database-table-declaration-index': + $this->index_name = ''; + + $this->index = array( + 'was' => '', + 'unique' =>'', + 'primary' => '', + 'fields' => array() + ); + break; + case 'database-table-declaration-foreign': + $this->constraint_name = ''; + + $this->constraint = array( + 'was' => '', + 'match' => '', + 'ondelete' => '', + 'onupdate' => '', + 'deferrable' => '', + 'initiallydeferred' => '', + 'foreign' => true, + 'fields' => array(), + 'references' => array('table' => '', 'fields' => array()) + ); + break; + case 'database-sequence': + $this->sequence_name = ''; + + $this->sequence = array( + 'was' => '', + 'start' => '', + 'description' => '', + 'comments' => '', + 'on' => array('table' => '', 'field' => '') + ); + break; + } + } + + function endHandler($xp, $element) + { + if (strtolower($element) == 'variable') { + $this->var_mode = false; + return; + } + + switch ($this->element) { + /* Initialization */ + + /* Insert */ + case 'database-table-initialization-insert-select': + $this->init['data'] = array('select' => $this->init['data']); + break; + + /* Insert and Delete */ + case 'database-table-initialization-insert-field': + case 'database-table-initialization-insert-select-field': + case 'database-table-initialization-update-field': + $result = $this->val->validateDataField($this->table['fields'], $this->init['data']['field'], $this->init_field); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->init['data']['field'][] = $this->init_field; + } + break; + case 'database-table-initialization-insert-field-function': + case 'database-table-initialization-insert-select-field-function': + case 'database-table-initialization-update-field-function': + $this->init_field['group'] = array('type' => 'function', 'data' => $this->init_function); + break; + case 'database-table-initialization-insert-field-expression': + case 'database-table-initialization-insert-select-field-expression': + case 'database-table-initialization-update-field-expression': + $this->init_field['group'] = array('type' => 'expression', 'data' => $this->init_expression); + break; + + /* All */ + case 'database-table-initialization-insert-select-where-expression': + case 'database-table-initialization-update-where-expression': + case 'database-table-initialization-delete-where-expression': + $this->init['data']['where']['type'] = 'expression'; + $this->init['data']['where']['data'] = $this->init_expression; + break; + case 'database-table-initialization-insert': + case 'database-table-initialization-delete': + case 'database-table-initialization-update': + $this->table['initialization'][] = $this->init; + break; + + /* One level simulation of expression-function recursion */ + case 'database-table-initialization-insert-field-expression-function': + case 'database-table-initialization-insert-select-field-expression-function': + case 'database-table-initialization-insert-select-where-expression-function': + case 'database-table-initialization-update-field-expression-function': + case 'database-table-initialization-update-where-expression-function': + case 'database-table-initialization-delete-where-expression-function': + $this->init_expression['operants'][] = array('type' => 'function', 'data' => $this->init_function); + break; + + /* One level simulation of function-expression recursion */ + case 'database-table-initialization-insert-field-function-expression': + case 'database-table-initialization-insert-select-field-function-expression': + case 'database-table-initialization-insert-select-where-function-expression': + case 'database-table-initialization-update-field-function-expression': + case 'database-table-initialization-update-where-function-expression': + case 'database-table-initialization-delete-where-function-expression': + $this->init_function['arguments'][] = array('type' => 'expression', 'data' => $this->init_expression); + break; + + /* Table definition */ + case 'database-table': + $result = $this->val->validateTable($this->database_definition['tables'], $this->table, $this->table_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->database_definition['tables'][$this->table_name] = $this->table; + } + break; + case 'database-table-name': + if (isset($this->structure['tables'][$this->table_name])) { + $this->table = $this->structure['tables'][$this->table_name]; + } + break; + + /* Field declaration */ + case 'database-table-declaration-field': + $result = $this->val->validateField($this->table['fields'], $this->field, $this->field_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->table['fields'][$this->field_name] = $this->field; + } + break; + + /* Index declaration */ + case 'database-table-declaration-index': + $result = $this->val->validateIndex($this->table['indexes'], $this->index, $this->index_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->table['indexes'][$this->index_name] = $this->index; + } + break; + case 'database-table-declaration-index-field': + $result = $this->val->validateIndexField($this->index['fields'], $this->field, $this->field_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->index['fields'][$this->field_name] = $this->field; + } + break; + + /* Foreign Key declaration */ + case 'database-table-declaration-foreign': + $result = $this->val->validateConstraint($this->table['constraints'], $this->constraint, $this->constraint_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->table['constraints'][$this->constraint_name] = $this->constraint; + } + break; + case 'database-table-declaration-foreign-field': + $result = $this->val->validateConstraintField($this->constraint['fields'], $this->field_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->constraint['fields'][$this->field_name] = ''; + } + break; + case 'database-table-declaration-foreign-references-field': + $result = $this->val->validateConstraintReferencedField($this->constraint['references']['fields'], $this->field_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->constraint['references']['fields'][$this->field_name] = ''; + } + break; + + /* Sequence declaration */ + case 'database-sequence': + $result = $this->val->validateSequence($this->database_definition['sequences'], $this->sequence, $this->sequence_name); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } else { + $this->database_definition['sequences'][$this->sequence_name] = $this->sequence; + } + break; + + /* End of File */ + case 'database': + $result = $this->val->validateDatabase($this->database_definition); + if (PEAR::isError($result)) { + $this->raiseError($result->getUserinfo(), 0, $xp, $result->getCode()); + } + break; + } + + unset($this->elements[--$this->count]); + $this->element = implode('-', $this->elements); + } + + function &raiseError($msg = null, $xmlecode = 0, $xp = null, $ecode = MDB2_SCHEMA_ERROR_PARSE) + { + if (is_null($this->error)) { + $error = ''; + if (is_resource($msg)) { + $error .= 'Parser error: '.xml_error_string(xml_get_error_code($msg)); + $xp = $msg; + } else { + $error .= 'Parser error: '.$msg; + if (!is_resource($xp)) { + $xp = $this->parser; + } + } + + if ($error_string = xml_error_string($xmlecode)) { + $error .= ' - '.$error_string; + } + + if (is_resource($xp)) { + $byte = @xml_get_current_byte_index($xp); + $line = @xml_get_current_line_number($xp); + $column = @xml_get_current_column_number($xp); + $error .= " - Byte: $byte; Line: $line; Col: $column"; + } + + $error .= "\n"; + + $this->error =& MDB2_Schema::raiseError($ecode, null, null, $error); + } + return $this->error; + } + + function cdataHandler($xp, $data) + { + if ($this->var_mode == true) { + if (!isset($this->variables[$data])) { + $this->raiseError('variable "'.$data.'" not found', null, $xp); + return; + } + $data = $this->variables[$data]; + } + + switch ($this->element) { + /* Initialization */ + + /* Insert */ + case 'database-table-initialization-insert-select-table': + $this->init['data']['table'] = $data; + break; + + /* Insert and Update */ + case 'database-table-initialization-insert-field-name': + case 'database-table-initialization-insert-select-field-name': + case 'database-table-initialization-update-field-name': + $this->init_field['name'] .= $data; + break; + case 'database-table-initialization-insert-field-value': + case 'database-table-initialization-insert-select-field-value': + case 'database-table-initialization-update-field-value': + $this->init_field['group']['data'] .= $data; + break; + case 'database-table-initialization-insert-field-function-name': + case 'database-table-initialization-insert-select-field-function-name': + case 'database-table-initialization-update-field-function-name': + $this->init_function['name'] .= $data; + break; + case 'database-table-initialization-insert-field-function-value': + case 'database-table-initialization-insert-select-field-function-value': + case 'database-table-initialization-update-field-function-value': + $this->init_function['arguments'][] = array('type' => 'value', 'data' => $data); + break; + case 'database-table-initialization-insert-field-function-column': + case 'database-table-initialization-insert-select-field-function-column': + case 'database-table-initialization-update-field-function-column': + $this->init_function['arguments'][] = array('type' => 'column', 'data' => $data); + break; + case 'database-table-initialization-insert-field-column': + case 'database-table-initialization-insert-select-field-column': + case 'database-table-initialization-update-field-column': + $this->init_field['group'] = array('type' => 'column', 'data' => $data); + break; + + /* All */ + case 'database-table-initialization-insert-field-expression-operator': + case 'database-table-initialization-insert-select-field-expression-operator': + case 'database-table-initialization-insert-select-where-expression-operator': + case 'database-table-initialization-update-field-expression-operator': + case 'database-table-initialization-update-where-expression-operator': + case 'database-table-initialization-delete-where-expression-operator': + $this->init_expression['operator'] = $data; + break; + case 'database-table-initialization-insert-field-expression-value': + case 'database-table-initialization-insert-select-field-expression-value': + case 'database-table-initialization-insert-select-where-expression-value': + case 'database-table-initialization-update-field-expression-value': + case 'database-table-initialization-update-where-expression-value': + case 'database-table-initialization-delete-where-expression-value': + $this->init_expression['operants'][] = array('type' => 'value', 'data' => $data); + break; + case 'database-table-initialization-insert-field-expression-column': + case 'database-table-initialization-insert-select-field-expression-column': + case 'database-table-initialization-insert-select-where-expression-column': + case 'database-table-initialization-update-field-expression-column': + case 'database-table-initialization-update-where-expression-column': + case 'database-table-initialization-delete-where-expression-column': + $this->init_expression['operants'][] = array('type' => 'column', 'data' => $data); + break; + + case 'database-table-initialization-insert-field-function-function': + case 'database-table-initialization-insert-field-function-expression': + case 'database-table-initialization-insert-field-expression-expression': + case 'database-table-initialization-update-field-function-function': + case 'database-table-initialization-update-field-function-expression': + case 'database-table-initialization-update-field-expression-expression': + case 'database-table-initialization-update-where-expression-expression': + case 'database-table-initialization-delete-where-expression-expression': + /* Recursion to be implemented yet */ + break; + + /* One level simulation of expression-function recursion */ + case 'database-table-initialization-insert-field-expression-function-name': + case 'database-table-initialization-insert-select-field-expression-function-name': + case 'database-table-initialization-insert-select-where-expression-function-name': + case 'database-table-initialization-update-field-expression-function-name': + case 'database-table-initialization-update-where-expression-function-name': + case 'database-table-initialization-delete-where-expression-function-name': + $this->init_function['name'] .= $data; + break; + case 'database-table-initialization-insert-field-expression-function-value': + case 'database-table-initialization-insert-select-field-expression-function-value': + case 'database-table-initialization-insert-select-where-expression-function-value': + case 'database-table-initialization-update-field-expression-function-value': + case 'database-table-initialization-update-where-expression-function-value': + case 'database-table-initialization-delete-where-expression-function-value': + $this->init_function['arguments'][] = array('type' => 'value', 'data' => $data); + break; + case 'database-table-initialization-insert-field-expression-function-column': + case 'database-table-initialization-insert-select-field-expression-function-column': + case 'database-table-initialization-insert-select-where-expression-function-column': + case 'database-table-initialization-update-field-expression-function-column': + case 'database-table-initialization-update-where-expression-function-column': + case 'database-table-initialization-delete-where-expression-function-column': + $this->init_function['arguments'][] = array('type' => 'column', 'data' => $data); + break; + + /* One level simulation of function-expression recursion */ + case 'database-table-initialization-insert-field-function-expression-operator': + case 'database-table-initialization-insert-select-field-function-expression-operator': + case 'database-table-initialization-update-field-function-expression-operator': + $this->init_expression['operator'] = $data; + break; + case 'database-table-initialization-insert-field-function-expression-value': + case 'database-table-initialization-insert-select-field-function-expression-value': + case 'database-table-initialization-update-field-function-expression-value': + $this->init_expression['operants'][] = array('type' => 'value', 'data' => $data); + break; + case 'database-table-initialization-insert-field-function-expression-column': + case 'database-table-initialization-insert-select-field-function-expression-column': + case 'database-table-initialization-update-field-function-expression-column': + $this->init_expression['operants'][] = array('type' => 'column', 'data' => $data); + break; + + /* Database */ + case 'database-name': + $this->database_definition['name'] .= $data; + break; + case 'database-create': + $this->database_definition['create'] .= $data; + break; + case 'database-overwrite': + $this->database_definition['overwrite'] .= $data; + break; + case 'database-charset': + $this->database_definition['charset'] .= $data; + break; + case 'database-description': + $this->database_definition['description'] .= $data; + break; + case 'database-comments': + $this->database_definition['comments'] .= $data; + break; + + /* Table declaration */ + case 'database-table-name': + $this->table_name .= $data; + break; + case 'database-table-was': + $this->table['was'] .= $data; + break; + case 'database-table-description': + $this->table['description'] .= $data; + break; + case 'database-table-comments': + $this->table['comments'] .= $data; + break; + + /* Field declaration */ + case 'database-table-declaration-field-name': + $this->field_name .= $data; + break; + case 'database-table-declaration-field-was': + $this->field['was'] .= $data; + break; + case 'database-table-declaration-field-type': + $this->field['type'] .= $data; + break; + case 'database-table-declaration-field-fixed': + $this->field['fixed'] .= $data; + break; + case 'database-table-declaration-field-default': + $this->field['default'] .= $data; + break; + case 'database-table-declaration-field-notnull': + $this->field['notnull'] .= $data; + break; + case 'database-table-declaration-field-autoincrement': + $this->field['autoincrement'] .= $data; + break; + case 'database-table-declaration-field-unsigned': + $this->field['unsigned'] .= $data; + break; + case 'database-table-declaration-field-length': + $this->field['length'] .= $data; + break; + case 'database-table-declaration-field-description': + $this->field['description'] .= $data; + break; + case 'database-table-declaration-field-comments': + $this->field['comments'] .= $data; + break; + + /* Index declaration */ + case 'database-table-declaration-index-name': + $this->index_name .= $data; + break; + case 'database-table-declaration-index-was': + $this->index['was'] .= $data; + break; + case 'database-table-declaration-index-unique': + $this->index['unique'] .= $data; + break; + case 'database-table-declaration-index-primary': + $this->index['primary'] .= $data; + break; + case 'database-table-declaration-index-field-name': + $this->field_name .= $data; + break; + case 'database-table-declaration-index-field-sorting': + $this->field['sorting'] .= $data; + break; + /* Add by Leoncx */ + case 'database-table-declaration-index-field-length': + $this->field['length'] .= $data; + break; + + /* Foreign Key declaration */ + case 'database-table-declaration-foreign-name': + $this->constraint_name .= $data; + break; + case 'database-table-declaration-foreign-was': + $this->constraint['was'] .= $data; + break; + case 'database-table-declaration-foreign-match': + $this->constraint['match'] .= $data; + break; + case 'database-table-declaration-foreign-ondelete': + $this->constraint['ondelete'] .= $data; + break; + case 'database-table-declaration-foreign-onupdate': + $this->constraint['onupdate'] .= $data; + break; + case 'database-table-declaration-foreign-deferrable': + $this->constraint['deferrable'] .= $data; + break; + case 'database-table-declaration-foreign-initiallydeferred': + $this->constraint['initiallydeferred'] .= $data; + break; + case 'database-table-declaration-foreign-field': + $this->field_name .= $data; + break; + case 'database-table-declaration-foreign-references-table': + $this->constraint['references']['table'] .= $data; + break; + case 'database-table-declaration-foreign-references-field': + $this->field_name .= $data; + break; + + /* Sequence declaration */ + case 'database-sequence-name': + $this->sequence_name .= $data; + break; + case 'database-sequence-was': + $this->sequence['was'] .= $data; + break; + case 'database-sequence-start': + $this->sequence['start'] .= $data; + break; + case 'database-sequence-description': + $this->sequence['description'] .= $data; + break; + case 'database-sequence-comments': + $this->sequence['comments'] .= $data; + break; + case 'database-sequence-on-table': + $this->sequence['on']['table'] .= $data; + break; + case 'database-sequence-on-field': + $this->sequence['on']['field'] .= $data; + break; + } + } +} + +?> diff --git a/lib/Pear/MDB2/Schema/Parser2.php b/lib/Pear/MDB2/Schema/Parser2.php new file mode 100644 index 0000000..0131847 --- /dev/null +++ b/lib/Pear/MDB2/Schema/Parser2.php @@ -0,0 +1,624 @@ + + * + * @category Database + * @package MDB2_Schema + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id: Parser2.php,v 1.12 2008/11/30 03:34:00 clockwerx Exp $ + * @link http://pear.php.net/packages/MDB2_Schema + */ + +require_once 'XML/Unserializer.php'; +require_once 'MDB2/Schema/Validate.php'; + +/** + * Parses an XML schema file + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema_Parser2 extends XML_Unserializer +{ + var $database_definition = array(); + + var $database_loaded = array(); + + var $variables = array(); + + var $error; + + var $structure = false; + + var $val; + + var $options = array(); + + var $table = array(); + + var $table_name = ''; + + var $field = array(); + + var $field_name = ''; + + var $index = array(); + + var $index_name = ''; + + var $constraint = array(); + + var $constraint_name = ''; + + var $sequence = array(); + + var $sequence_name = ''; + + var $init = array(); + + function __construct($variables, $fail_on_invalid_names = true, $structure = false, $valid_types = array(), $force_defaults = true) + { + // force ISO-8859-1 due to different defaults for PHP4 and PHP5 + // todo: this probably needs to be investigated some more and cleaned up + $this->options['encoding'] = 'ISO-8859-1'; + + $this->options['XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE'] = true; + $this->options['XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY'] = false; + + $this->options['forceEnum'] = array('table', 'field', 'index', 'foreign', 'insert', 'update', 'delete', 'sequence'); + + /* + * todo: find a way to force the following items not to be parsed as arrays + * as it cause problems in functions with multiple arguments + */ + //$this->options['forceNEnum'] = array('value', 'column'); + $this->variables = $variables; + $this->structure = $structure; + + $this->val =& new MDB2_Schema_Validate($fail_on_invalid_names, $valid_types, $force_defaults); + parent::XML_Unserializer($this->options); + } + + function MDB2_Schema_Parser2($variables, $fail_on_invalid_names = true, $structure = false, $valid_types = array(), $force_defaults = true) + { + $this->__construct($variables, $fail_on_invalid_names, $structure, $valid_types, $force_defaults); + } + + function parse() + { + $result = $this->unserialize($this->filename, true); + + if (PEAR::isError($result)) { + return $result; + } else { + $this->database_loaded = $this->getUnserializedData(); + return $this->fixDatabaseKeys($this->database_loaded); + } + } + + function setInputFile($filename) + { + $this->filename = $filename; + return MDB2_OK; + } + + function renameKey(&$arr, $oKey, $nKey) + { + $arr[$nKey] = &$arr[$oKey]; + unset($arr[$oKey]); + } + + function fixDatabaseKeys($database) + { + $this->database_definition = array( + 'name' => '', + 'create' => '', + 'overwrite' => '', + 'charset' => '', + 'description' => '', + 'comments' => '', + 'tables' => array(), + 'sequences' => array() + ); + + if (!empty($database['name'])) { + $this->database_definition['name'] = $database['name']; + } + if (!empty($database['create'])) { + $this->database_definition['create'] = $database['create']; + } + if (!empty($database['overwrite'])) { + $this->database_definition['overwrite'] = $database['overwrite']; + } + if (!empty($database['charset'])) { + $this->database_definition['charset'] = $database['charset']; + } + if (!empty($database['description'])) { + $this->database_definition['description'] = $database['description']; + } + if (!empty($database['comments'])) { + $this->database_definition['comments'] = $database['comments']; + } + + if (!empty($database['table']) && is_array($database['table'])) { + foreach ($database['table'] as $table) { + $this->fixTableKeys($table); + } + } + + if (!empty($database['sequence']) && is_array($database['sequence'])) { + foreach ($database['sequence'] as $sequence) { + $this->fixSequenceKeys($sequence); + } + } + + $result = $this->val->validateDatabase($this->database_definition); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } + + return MDB2_OK; + } + + function fixTableKeys($table) + { + $this->table = array( + 'was' => '', + 'description' => '', + 'comments' => '', + 'fields' => array(), + 'indexes' => array(), + 'constraints' => array(), + 'initialization' => array() + ); + + if (!empty($table['name'])) { + $this->table_name = $table['name']; + } else { + $this->table_name = ''; + } + if (!empty($table['was'])) { + $this->table['was'] = $table['was']; + } + if (!empty($table['description'])) { + $this->table['description'] = $table['description']; + } + if (!empty($table['comments'])) { + $this->table['comments'] = $table['comments']; + } + + if (!empty($table['declaration']) && is_array($table['declaration'])) { + if (!empty($table['declaration']['field']) && is_array($table['declaration']['field'])) { + foreach ($table['declaration']['field'] as $field) { + $this->fixTableFieldKeys($field); + } + } + + if (!empty($table['declaration']['index']) && is_array($table['declaration']['index'])) { + foreach ($table['declaration']['index'] as $index) { + $this->fixTableIndexKeys($index); + } + } + + if (!empty($table['declaration']['foreign']) && is_array($table['declaration']['foreign'])) { + foreach ($table['declaration']['foreign'] as $constraint) { + $this->fixTableConstraintKeys($constraint); + } + } + } + + if (!empty($table['initialization']) && is_array($table['initialization'])) { + if (!empty($table['initialization']['insert']) && is_array($table['initialization']['insert'])) { + foreach ($table['initialization']['insert'] as $init) { + $this->fixTableInitializationKeys($init, 'insert'); + } + } + if (!empty($table['initialization']['update']) && is_array($table['initialization']['update'])) { + foreach ($table['initialization']['update'] as $init) { + $this->fixTableInitializationKeys($init, 'update'); + } + } + if (!empty($table['initialization']['delete']) && is_array($table['initialization']['delete'])) { + foreach ($table['initialization']['delete'] as $init) { + $this->fixTableInitializationKeys($init, 'delete'); + } + } + } + + $result = $this->val->validateTable($this->database_definition['tables'], $this->table, $this->table_name); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } else { + $this->database_definition['tables'][$this->table_name] = $this->table; + } + + return MDB2_OK; + } + + function fixTableFieldKeys($field) + { + $this->field = array(); + if (!empty($field['name'])) { + $this->field_name = $field['name']; + } else { + $this->field_name = ''; + } + if (!empty($field['was'])) { + $this->field['was'] = $field['was']; + } + if (!empty($field['type'])) { + $this->field['type'] = $field['type']; + } + if (!empty($field['fixed'])) { + $this->field['fixed'] = $field['fixed']; + } + if (isset($field['default'])) { + $this->field['default'] = $field['default']; + } + if (!empty($field['notnull'])) { + $this->field['notnull'] = $field['notnull']; + } + if (!empty($field['autoincrement'])) { + $this->field['autoincrement'] = $field['autoincrement']; + } + if (!empty($field['unsigned'])) { + $this->field['unsigned'] = $field['unsigned']; + } + if (!empty($field['length'])) { + $this->field['length'] = $field['length']; + } + if (!empty($field['description'])) { + $this->field['description'] = $field['description']; + } + if (!empty($field['comments'])) { + $this->field['comments'] = $field['comments']; + } + + $result = $this->val->validateField($this->table['fields'], $this->field, $this->field_name); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } else { + $this->table['fields'][$this->field_name] = $this->field; + } + + return MDB2_OK; + } + + function fixTableIndexKeys($index) + { + $this->index = array( + 'was' => '', + 'unique' =>'', + 'primary' => '', + 'fields' => array() + ); + + if (!empty($index['name'])) { + $this->index_name = $index['name']; + } else { + $this->index_name = ''; + } + if (!empty($index['was'])) { + $this->index['was'] = $index['was']; + } + if (!empty($index['unique'])) { + $this->index['unique'] = $index['unique']; + } + if (!empty($index['primary'])) { + $this->index['primary'] = $index['primary']; + } + if (!empty($index['field'])) { + foreach ($index['field'] as $field) { + if (!empty($field['name'])) { + $this->field_name = $field['name']; + } else { + $this->field_name = ''; + } + $this->field = array( + 'sorting' => '', + 'length' => '' + ); + + if (!empty($field['sorting'])) { + $this->field['sorting'] = $field['sorting']; + } + if (!empty($field['length'])) { + $this->field['length'] = $field['length']; + } + + $result = $this->val->validateIndexField($this->index['fields'], $this->field, $this->field_name); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } + + $this->index['fields'][$this->field_name] = $this->field; + } + } + + $result = $this->val->validateIndex($this->table['indexes'], $this->index, $this->index_name); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } else { + $this->table['indexes'][$this->index_name] = $this->index; + } + + return MDB2_OK; + } + + function fixTableConstraintKeys($constraint) + { + $this->constraint = array( + 'was' => '', + 'match' => '', + 'ondelete' => '', + 'onupdate' => '', + 'deferrable' => '', + 'initiallydeferred' => '', + 'foreign' => true, + 'fields' => array(), + 'references' => array('table' => '', 'fields' => array()) + ); + + if (!empty($constraint['name'])) { + $this->constraint_name = $constraint['name']; + } else { + $this->constraint_name = ''; + } + if (!empty($constraint['was'])) { + $this->constraint['was'] = $constraint['was']; + } + if (!empty($constraint['match'])) { + $this->constraint['match'] = $constraint['match']; + } + if (!empty($constraint['ondelete'])) { + $this->constraint['ondelete'] = $constraint['ondelete']; + } + if (!empty($constraint['onupdate'])) { + $this->constraint['onupdate'] = $constraint['onupdate']; + } + if (!empty($constraint['deferrable'])) { + $this->constraint['deferrable'] = $constraint['deferrable']; + } + if (!empty($constraint['initiallydeferred'])) { + $this->constraint['initiallydeferred'] = $constraint['initiallydeferred']; + } + if (!empty($constraint['field']) && is_array($constraint['field'])) { + foreach ($constraint['field'] as $field) { + $result = $this->val->validateConstraintField($this->constraint['fields'], $field); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } + + $this->constraint['fields'][$field] = ''; + } + } + + if (!empty($constraint['references']) && is_array($constraint['references'])) { + /** + * As we forced 'table' to be enumerated + * we have to fix it on the foreign-references-table context + */ + if (!empty($constraint['references']['table']) && is_array($constraint['references']['table'])) { + $this->constraint['references']['table'] = $constraint['references']['table'][0]; + } + + if (!empty($constraint['references']['field']) && is_array($constraint['references']['field'])) { + foreach ($constraint['references']['field'] as $field) { + $result = $this->val->validateConstraintReferencedField($this->constraint['references']['fields'], $field); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } + + $this->constraint['references']['fields'][$field] = ''; + } + } + } + + $result = $this->val->validateConstraint($this->table['constraints'], $this->constraint, $this->constraint_name); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } else { + $this->table['constraints'][$this->constraint_name] = $this->constraint; + } + + return MDB2_OK; + } + + function fixTableInitializationKeys($element, $type = '') + { + if (!empty($element['select']) && is_array($element['select'])) { + $this->fixTableInitializationDataKeys($element['select']); + $this->init = array( 'select' => $this->init ); + } else { + $this->fixTableInitializationDataKeys($element); + } + + $this->table['initialization'][] = array( 'type' => $type, 'data' => $this->init ); + } + + function fixTableInitializationDataKeys($element) + { + $this->init = array(); + if (!empty($element['field']) && is_array($element['field'])) { + foreach ($element['field'] as $field) { + $name = $field['name']; + unset($field['name']); + + $this->setExpression($field); + $this->init['field'][] = array( 'name' => $name, 'group' => $field ); + } + } + /** + * As we forced 'table' to be enumerated + * we have to fix it on the insert-select context + */ + if (!empty($element['table']) && is_array($element['table'])) { + $this->init['table'] = $element['table'][0]; + } + if (!empty($element['where']) && is_array($element['where'])) { + $this->init['where'] = $element['where']; + $this->setExpression($this->init['where']); + } + } + + function setExpression(&$arr) + { + $element = each($arr); + + $arr = array( 'type' => $element['key'] ); + + $element = $element['value']; + + switch ($arr['type']) { + case 'null': + break; + case 'value': + case 'column': + $arr['data'] = $element; + break; + case 'function': + if (!empty($element) + && is_array($element) + ) { + $arr['data'] = array( 'name' => $element['name'] ); + unset($element['name']); + + foreach ($element as $type => $value) { + if (!empty($value)) { + if (is_array($value)) { + foreach ($value as $argument) { + $argument = array( $type => $argument ); + $this->setExpression($argument); + $arr['data']['arguments'][] = $argument; + } + } else { + $arr['data']['arguments'][] = array( 'type' => $type, 'data' => $value ); + } + } + } + } + break; + case 'expression': + $arr['data'] = array( 'operants' => array(), 'operator' => $element['operator'] ); + unset($element['operator']); + + foreach ($element as $k => $v) { + $argument = array( $k => $v ); + $this->setExpression($argument); + $arr['data']['operants'][] = $argument; + } + break; + } + } + + function fixSequenceKeys($sequence) + { + $this->sequence = array( + 'was' => '', + 'start' => '', + 'description' => '', + 'comments' => '', + 'on' => array('table' => '', 'field' => '') + ); + + if (!empty($sequence['name'])) { + $this->sequence_name = $sequence['name']; + } else { + $this->sequence_name = ''; + } + if (!empty($sequence['was'])) { + $this->sequence['was'] = $sequence['was']; + } + if (!empty($sequence['start'])) { + $this->sequence['start'] = $sequence['start']; + } + if (!empty($sequence['description'])) { + $this->sequence['description'] = $sequence['description']; + } + if (!empty($sequence['comments'])) { + $this->sequence['comments'] = $sequence['comments']; + } + if (!empty($sequence['on']) && is_array($sequence['on'])) { + /** + * As we forced 'table' to be enumerated + * we have to fix it on the sequence-on-table context + */ + if (!empty($sequence['on']['table']) && is_array($sequence['on']['table'])) { + $this->sequence['on']['table'] = $sequence['on']['table'][0]; + } + + /** + * As we forced 'field' to be enumerated + * we have to fix it on the sequence-on-field context + */ + if (!empty($sequence['on']['field']) && is_array($sequence['on']['field'])) { + $this->sequence['on']['field'] = $sequence['on']['field'][0]; + } + } + + $result = $this->val->validateSequence($this->database_definition['sequences'], $this->sequence, $this->sequence_name); + if (PEAR::isError($result)) { + return $this->raiseError($result->getUserinfo()); + } else { + $this->database_definition['sequences'][$this->sequence_name] = $this->sequence; + } + + return MDB2_OK; + } + + function &raiseError($msg = null, $ecode = MDB2_SCHEMA_ERROR_PARSE) + { + if (is_null($this->error)) { + $error = 'Parser error: '.$msg."\n"; + + $this->error =& MDB2_Schema::raiseError($ecode, null, null, $error); + } + return $this->error; + } +} + +?> diff --git a/lib/Pear/MDB2/Schema/Reserved/ibase.php b/lib/Pear/MDB2/Schema/Reserved/ibase.php new file mode 100644 index 0000000..b208abc --- /dev/null +++ b/lib/Pear/MDB2/Schema/Reserved/ibase.php @@ -0,0 +1,436 @@ + | +// +----------------------------------------------------------------------+ +// +// }}} +// {{{ $GLOBALS['_MDB2_Schema_Reserved']['ibase'] +/** + * Has a list of reserved words of Interbase/Firebird + * + * @package MDB2_Schema + * @category Database + * @access protected + * @author Lorenzo Alberton + */ +$GLOBALS['_MDB2_Schema_Reserved']['ibase'] = array( + 'ABS', + 'ABSOLUTE', + 'ACTION', + 'ACTIVE', + 'ADD', + 'ADMIN', + 'AFTER', + 'ALL', + 'ALLOCATE', + 'ALTER', + 'AND', + 'ANY', + 'ARE', + 'AS', + 'ASC', + 'ASCENDING', + 'ASSERTION', + 'AT', + 'AUTHORIZATION', + 'AUTO', + 'AUTODDL', + 'AVG', + 'BACKUP', + 'BASE_NAME', + 'BASED', + 'BASENAME', + 'BEFORE', + 'BEGIN', + 'BETWEEN', + 'BIGINT', + 'BIT', + 'BIT_LENGTH', + 'BLOB', + 'BLOCK', + 'BLOBEDIT', + 'BOOLEAN', + 'BOTH', + 'BOTH', + 'BREAK', + 'BUFFER', + 'BY', + 'CACHE', + 'CASCADE', + 'CASCADED', + 'CASE', + 'CASE', + 'CAST', + 'CATALOG', + 'CHAR', + 'CHAR_LENGTH', + 'CHARACTER', + 'CHARACTER_LENGTH', + 'CHECK', + 'CHECK_POINT_LEN', + 'CHECK_POINT_LENGTH', + 'CLOSE', + 'COALESCE', + 'COLLATE', + 'COLLATION', + 'COLUMN', + 'COMMENT', + 'COMMIT', + 'COMMITTED', + 'COMPILETIME', + 'COMPUTED', + 'CONDITIONAL', + 'CONNECT', + 'CONNECTION', + 'CONSTRAINT', + 'CONSTRAINTS', + 'CONTAINING', + 'CONTINUE', + 'CONVERT', + 'CORRESPONDING', + 'COUNT', + 'CREATE', + 'CROSS', + 'CSTRING', + 'CURRENT', + 'CURRENT_CONNECTION', + 'CURRENT_DATE', + 'CURRENT_ROLE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_TRANSACTION', + 'CURRENT_USER', + 'DATABASE', + 'DATE', + 'DAY', + 'DB_KEY', + 'DEALLOCATE', + 'DEBUG', + 'DEC', + 'DECIMAL', + 'DECLARE', + 'DEFAULT', + 'DEFERRABLE', + 'DEFERRED', + 'DELETE', + 'DELETING', + 'DESC', + 'DESCENDING', + 'DESCRIBE', + 'DESCRIPTOR', + 'DIAGNOSTICS', + 'DIFFERENCE', + 'DISCONNECT', + 'DISPLAY', + 'DISTINCT', + 'DO', + 'DOMAIN', + 'DOUBLE', + 'DROP', + 'ECHO', + 'EDIT', + 'ELSE', + 'END', + 'END-EXEC', + 'ENTRY_POINT', + 'ESCAPE', + 'EVENT', + 'EXCEPT', + 'EXCEPTION', + 'EXEC', + 'EXECUTE', + 'EXISTS', + 'EXIT', + 'EXTERN', + 'EXTERNAL', + 'EXTRACT', + 'FALSE', + 'FETCH', + 'FILE', + 'FILTER', + 'FIRST', + 'FLOAT', + 'FOR', + 'FOREIGN', + 'FOUND', + 'FREE_IT', + 'FROM', + 'FULL', + 'FUNCTION', + 'GDSCODE', + 'GEN_ID', + 'GENERATOR', + 'GET', + 'GLOBAL', + 'GO', + 'GOTO', + 'GRANT', + 'GROUP', + 'GROUP_COMMIT_WAIT', + 'GROUP_COMMIT_WAIT_TIME', + 'HAVING', + 'HELP', + 'HOUR', + 'IDENTITY', + 'IF', + 'IIF', + 'IMMEDIATE', + 'IN', + 'INACTIVE', + 'INDEX', + 'INDICATOR', + 'INIT', + 'INITIALLY', + 'INNER', + 'INPUT', + 'INPUT_TYPE', + 'INSENSITIVE', + 'INSERT', + 'INSERTING', + 'INT', + 'INTEGER', + 'INTERSECT', + 'INTERVAL', + 'INTO', + 'IS', + 'ISOLATION', + 'ISQL', + 'JOIN', + 'KEY', + 'LANGUAGE', + 'LAST', + 'LC_MESSAGES', + 'LC_TYPE', + 'LEADING', + 'LEADING', + 'LEADING', + 'LEAVE', + 'LEFT', + 'LENGTH', + 'LEV', + 'LEVEL', + 'LIKE', + 'LOCAL', + 'LOCK', + 'LOG_BUF_SIZE', + 'LOG_BUFFER_SIZE', + 'LOGFILE', + 'LONG', + 'LOWER', + 'MANUAL', + 'MATCH', + 'MAX', + 'MAX_SEGMENT', + 'MAXIMUM', + 'MAXIMUM_SEGMENT', + 'MERGE', + 'MESSAGE', + 'MIN', + 'MINIMUM', + 'MINUTE', + 'MODULE', + 'MODULE_NAME', + 'MONTH', + 'NAMES', + 'NATIONAL', + 'NATURAL', + 'NCHAR', + 'NEXT', + 'NO', + 'NOAUTO', + 'NOT', + 'NULL', + 'NULLIF', + 'NULLS', + 'NUM_LOG_BUFFERS', + 'NUM_LOG_BUFS', + 'NUMERIC', + 'OCTET_LENGTH', + 'OF', + 'ON', + 'ONLY', + 'OPEN', + 'OPTION', + 'OR', + 'ORDER', + 'OUTER', + 'OUTPUT', + 'OUTPUT_TYPE', + 'OVERFLOW', + 'OVERLAPS', + 'PAD', + 'PAGE', + 'PAGE_SIZE', + 'PAGELENGTH', + 'PAGES', + 'PARAMETER', + 'PARTIAL', + 'PASSWORD', + 'PERCENT', + 'PLAN', + 'POSITION', + 'POST_EVENT', + 'PRECISION', + 'PREPARE', + 'PRESERVE', + 'PRIMARY', + 'PRIOR', + 'PRIVILEGES', + 'PROCEDURE', + 'PUBLIC', + 'QUIT', + 'RAW_PARTITIONS', + 'RDB$DB_KEY', + 'READ', + 'REAL', + 'RECORD_VERSION', + 'RECREATE', + 'RECREATE ROW_COUNT', + 'REFERENCES', + 'RELATIVE', + 'RELEASE', + 'RESERV', + 'RESERVING', + 'RESTART', + 'RESTRICT', + 'RETAIN', + 'RETURN', + 'RETURNING', + 'RETURNING_VALUES', + 'RETURNS', + 'REVOKE', + 'RIGHT', + 'ROLE', + 'ROLLBACK', + 'ROW_COUNT', + 'ROWS', + 'RUNTIME', + 'SAVEPOINT', + 'SCALAR_ARRAY', + 'SCHEMA', + 'SCROLL', + 'SECOND', + 'SECTION', + 'SELECT', + 'SEQUENCE', + 'SESSION', + 'SESSION_USER', + 'SET', + 'SHADOW', + 'SHARED', + 'SHELL', + 'SHOW', + 'SINGULAR', + 'SIZE', + 'SKIP', + 'SMALLINT', + 'SNAPSHOT', + 'SOME', + 'SORT', + 'SPACE', + 'SQL', + 'SQLCODE', + 'SQLERROR', + 'SQLSTATE', + 'SQLWARNING', + 'STABILITY', + 'STARTING', + 'STARTS', + 'STATEMENT', + 'STATIC', + 'STATISTICS', + 'SUB_TYPE', + 'SUBSTRING', + 'SUM', + 'SUSPEND', + 'SYSTEM_USER', + 'TABLE', + 'TEMPORARY', + 'TERMINATOR', + 'THEN', + 'TIES', + 'TIME', + 'TIMESTAMP', + 'TIMEZONE_HOUR', + 'TIMEZONE_MINUTE', + 'TO', + 'TRAILING', + 'TRANSACTION', + 'TRANSLATE', + 'TRANSLATION', + 'TRIGGER', + 'TRIM', + 'TRUE', + 'TYPE', + 'UNCOMMITTED', + 'UNION', + 'UNIQUE', + 'UNKNOWN', + 'UPDATE', + 'UPDATING', + 'UPPER', + 'USAGE', + 'USER', + 'USING', + 'VALUE', + 'VALUES', + 'VARCHAR', + 'VARIABLE', + 'VARYING', + 'VERSION', + 'VIEW', + 'WAIT', + 'WEEKDAY', + 'WHEN', + 'WHENEVER', + 'WHERE', + 'WHILE', + 'WITH', + 'WORK', + 'WRITE', + 'YEAR', + 'YEARDAY', + 'ZONE', +); +// }}} +?> \ No newline at end of file diff --git a/lib/Pear/MDB2/Schema/Reserved/mssql.php b/lib/Pear/MDB2/Schema/Reserved/mssql.php new file mode 100644 index 0000000..74ac688 --- /dev/null +++ b/lib/Pear/MDB2/Schema/Reserved/mssql.php @@ -0,0 +1,258 @@ + | +// +----------------------------------------------------------------------+ +// }}} +// {{{ $GLOBALS['_MDB2_Schema_Reserved']['mssql'] +/** + * Has a list of all the reserved words for mssql. + * + * @package MDB2_Schema + * @category Database + * @access protected + * @author David Coallier + */ +$GLOBALS['_MDB2_Schema_Reserved']['mssql'] = array( + 'ADD', + 'CURRENT_TIMESTAMP', + 'GROUP', + 'OPENQUERY', + 'SERIALIZABLE', + 'ALL', + 'CURRENT_USER', + 'HAVING', + 'OPENROWSET', + 'SESSION_USER', + 'ALTER', + 'CURSOR', + 'HOLDLOCK', + 'OPTION', + 'SET', + 'AND', + 'DATABASE', + 'IDENTITY', + 'OR', + 'SETUSER', + 'ANY', + 'DBCC', + 'IDENTITYCOL', + 'ORDER', + 'SHUTDOWN', + 'AS', + 'DEALLOCATE', + 'IDENTITY_INSERT', + 'OUTER', + 'SOME', + 'ASC', + 'DECLARE', + 'IF', + 'OVER', + 'STATISTICS', + 'AUTHORIZATION', + 'DEFAULT', + 'IN', + 'PERCENT', + 'SUM', + 'AVG', + 'DELETE', + 'INDEX', + 'PERM', + 'SYSTEM_USER', + 'BACKUP', + 'DENY', + 'INNER', + 'PERMANENT', + 'TABLE', + 'BEGIN', + 'DESC', + 'INSERT', + 'PIPE', + 'TAPE', + 'BETWEEN', + 'DISK', + 'INTERSECT', + 'PLAN', + 'TEMP', + 'BREAK', + 'DISTINCT', + 'INTO', + 'PRECISION', + 'TEMPORARY', + 'BROWSE', + 'DISTRIBUTED', + 'IS', + 'PREPARE', + 'TEXTSIZE', + 'BULK', + 'DOUBLE', + 'ISOLATION', + 'PRIMARY', + 'THEN', + 'BY', + 'DROP', + 'JOIN', + 'PRINT', + 'TO', + 'CASCADE', + 'DUMMY', + 'KEY', + 'PRIVILEGES', + 'TOP', + 'CASE', + 'DUMP', + 'KILL', + 'PROC', + 'TRAN', + 'CHECK', + 'ELSE', + 'LEFT', + 'PROCEDURE', + 'TRANSACTION', + 'CHECKPOINT', + 'END', + 'LEVEL', + 'PROCESSEXIT', + 'TRIGGER', + 'CLOSE', + 'ERRLVL', + 'LIKE', + 'PUBLIC', + 'TRUNCATE', + 'CLUSTERED', + 'ERROREXIT', + 'LINENO', + 'RAISERROR', + 'TSEQUAL', + 'COALESCE', + 'ESCAPE', + 'LOAD', + 'READ', + 'UNCOMMITTED', + 'COLUMN', + 'EXCEPT', + 'MAX', + 'READTEXT', + 'UNION', + 'COMMIT', + 'EXEC', + 'MIN', + 'RECONFIGURE', + 'UNIQUE', + 'COMMITTED', + 'EXECUTE', + 'MIRROREXIT', + 'REFERENCES', + 'UPDATE', + 'COMPUTE', + 'EXISTS', + 'NATIONAL', + 'REPEATABLE', + 'UPDATETEXT', + 'CONFIRM', + 'EXIT', + 'NOCHECK', + 'REPLICATION', + 'USE', + 'CONSTRAINT', + 'FETCH', + 'NONCLUSTERED', + 'RESTORE', + 'USER', + 'CONTAINS', + 'FILE', + 'NOT', + 'RESTRICT', + 'VALUES', + 'CONTAINSTABLE', + 'FILLFACTOR', + 'NULL', + 'RETURN', + 'VARYING', + 'CONTINUE', + 'FLOPPY', + 'NULLIF', + 'REVOKE', + 'VIEW', + 'CONTROLROW', + 'FOR', + 'OF', + 'RIGHT', + 'WAITFOR', + 'CONVERT', + 'FOREIGN', + 'OFF', + 'ROLLBACK', + 'WHEN', + 'COUNT', + 'FREETEXT', + 'OFFSETS', + 'ROWCOUNT', + 'WHERE', + 'CREATE', + 'FREETEXTTABLE', + 'ON', + 'ROWGUIDCOL', + 'WHILE', + 'CROSS', + 'FROM', + 'ONCE', + 'RULE', + 'WITH', + 'CURRENT', + 'FULL', + 'ONLY', + 'SAVE', + 'WORK', + 'CURRENT_DATE', + 'GOTO', + 'OPEN', + 'SCHEMA', + 'WRITETEXT', + 'CURRENT_TIME', + 'GRANT', + 'OPENDATASOURCE', + 'SELECT', +); +//}}} + +?> diff --git a/lib/Pear/MDB2/Schema/Reserved/mysql.php b/lib/Pear/MDB2/Schema/Reserved/mysql.php new file mode 100644 index 0000000..4f0575e --- /dev/null +++ b/lib/Pear/MDB2/Schema/Reserved/mysql.php @@ -0,0 +1,284 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mysql.php,v 1.3 2006/03/01 12:16:40 lsmith Exp $ +// }}} +// {{{ $GLOBALS['_MDB2_Schema_Reserved']['mysql'] +/** + * Has a list of reserved words of mysql + * + * @package MDB2_Schema + * @category Database + * @access protected + * @author David Coalier + */ +$GLOBALS['_MDB2_Schema_Reserved']['mysql'] = array( + 'ADD', + 'ALL', + 'ALTER', + 'ANALYZE', + 'AND', + 'AS', + 'ASC', + 'ASENSITIVE', + 'BEFORE', + 'BETWEEN', + 'BIGINT', + 'BINARY', + 'BLOB', + 'BOTH', + 'BY', + 'CALL', + 'CASCADE', + 'CASE', + 'CHANGE', + 'CHAR', + 'CHARACTER', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'CONDITION', + 'CONNECTION', + 'CONSTRAINT', + 'CONTINUE', + 'CONVERT', + 'CREATE', + 'CROSS', + 'CURRENT_DATE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'CURSOR', + 'DATABASE', + 'DATABASES', + 'DAY_HOUR', + 'DAY_MICROSECOND', + 'DAY_MINUTE', + 'DAY_SECOND', + 'DEC', + 'DECIMAL', + 'DECLARE', + 'DEFAULT', + 'DELAYED', + 'DELETE', + 'DESC', + 'DESCRIBE', + 'DETERMINISTIC', + 'DISTINCT', + 'DISTINCTROW', + 'DIV', + 'DOUBLE', + 'DROP', + 'DUAL', + 'EACH', + 'ELSE', + 'ELSEIF', + 'ENCLOSED', + 'ESCAPED', + 'EXISTS', + 'EXIT', + 'EXPLAIN', + 'FALSE', + 'FETCH', + 'FLOAT', + 'FLOAT4', + 'FLOAT8', + 'FOR', + 'FORCE', + 'FOREIGN', + 'FROM', + 'FULLTEXT', + 'GOTO', + 'GRANT', + 'GROUP', + 'HAVING', + 'HIGH_PRIORITY', + 'HOUR_MICROSECOND', + 'HOUR_MINUTE', + 'HOUR_SECOND', + 'IF', + 'IGNORE', + 'IN', + 'INDEX', + 'INFILE', + 'INNER', + 'INOUT', + 'INSENSITIVE', + 'INSERT', + 'INT', + 'INT1', + 'INT2', + 'INT3', + 'INT4', + 'INT8', + 'INTEGER', + 'INTERVAL', + 'INTO', + 'IS', + 'ITERATE', + 'JOIN', + 'KEY', + 'KEYS', + 'KILL', + 'LABEL', + 'LEADING', + 'LEAVE', + 'LEFT', + 'LIKE', + 'LIMIT', + 'LINES', + 'LOAD', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'LOCK', + 'LONG', + 'LONGBLOB', + 'LONGTEXT', + 'LOOP', + 'LOW_PRIORITY', + 'MATCH', + 'MEDIUMBLOB', + 'MEDIUMINT', + 'MEDIUMTEXT', + 'MIDDLEINT', + 'MINUTE_MICROSECOND', + 'MINUTE_SECOND', + 'MOD', + 'MODIFIES', + 'NATURAL', + 'NOT', + 'NO_WRITE_TO_BINLOG', + 'NULL', + 'NUMERIC', + 'ON', + 'OPTIMIZE', + 'OPTION', + 'OPTIONALLY', + 'OR', + 'ORDER', + 'OUT', + 'OUTER', + 'OUTFILE', + 'PRECISION', + 'PRIMARY', + 'PROCEDURE', + 'PURGE', + 'RAID0', + 'READ', + 'READS', + 'REAL', + 'REFERENCES', + 'REGEXP', + 'RELEASE', + 'RENAME', + 'REPEAT', + 'REPLACE', + 'REQUIRE', + 'RESTRICT', + 'RETURN', + 'REVOKE', + 'RIGHT', + 'RLIKE', + 'SCHEMA', + 'SCHEMAS', + 'SECOND_MICROSECOND', + 'SELECT', + 'SENSITIVE', + 'SEPARATOR', + 'SET', + 'SHOW', + 'SMALLINT', + 'SONAME', + 'SPATIAL', + 'SPECIFIC', + 'SQL', + 'SQLEXCEPTION', + 'SQLSTATE', + 'SQLWARNING', + 'SQL_BIG_RESULT', + 'SQL_CALC_FOUND_ROWS', + 'SQL_SMALL_RESULT', + 'SSL', + 'STARTING', + 'STRAIGHT_JOIN', + 'TABLE', + 'TERMINATED', + 'THEN', + 'TINYBLOB', + 'TINYINT', + 'TINYTEXT', + 'TO', + 'TRAILING', + 'TRIGGER', + 'TRUE', + 'UNDO', + 'UNION', + 'UNIQUE', + 'UNLOCK', + 'UNSIGNED', + 'UPDATE', + 'USAGE', + 'USE', + 'USING', + 'UTC_DATE', + 'UTC_TIME', + 'UTC_TIMESTAMP', + 'VALUES', + 'VARBINARY', + 'VARCHAR', + 'VARCHARACTER', + 'VARYING', + 'WHEN', + 'WHERE', + 'WHILE', + 'WITH', + 'WRITE', + 'X509', + 'XOR', + 'YEAR_MONTH', + 'ZEROFILL', + ); + // }}} +?> diff --git a/lib/Pear/MDB2/Schema/Reserved/oci8.php b/lib/Pear/MDB2/Schema/Reserved/oci8.php new file mode 100644 index 0000000..57fe12d --- /dev/null +++ b/lib/Pear/MDB2/Schema/Reserved/oci8.php @@ -0,0 +1,171 @@ + | +// +----------------------------------------------------------------------+ +// }}} +// {{{ $GLOBALS['_MDB2_Schema_Reserved']['oci8'] +/** + * Has a list of all the reserved words for oracle. + * + * @package MDB2_Schema + * @category Database + * @access protected + * @author David Coallier + */ +$GLOBALS['_MDB2_Schema_Reserved']['oci8'] = array( + 'ACCESS', + 'ELSE', + 'MODIFY', + 'START', + 'ADD', + 'EXCLUSIVE', + 'NOAUDIT', + 'SELECT', + 'ALL', + 'EXISTS', + 'NOCOMPRESS', + 'SESSION', + 'ALTER', + 'FILE', + 'NOT', + 'SET', + 'AND', + 'FLOAT', + 'NOTFOUND ', + 'SHARE', + 'ANY', + 'FOR', + 'NOWAIT', + 'SIZE', + 'ARRAYLEN', + 'FROM', + 'NULL', + 'SMALLINT', + 'AS', + 'GRANT', + 'NUMBER', + 'SQLBUF', + 'ASC', + 'GROUP', + 'OF', + 'SUCCESSFUL', + 'AUDIT', + 'HAVING', + 'OFFLINE ', + 'SYNONYM', + 'BETWEEN', + 'IDENTIFIED', + 'ON', + 'SYSDATE', + 'BY', + 'IMMEDIATE', + 'ONLINE', + 'TABLE', + 'CHAR', + 'IN', + 'OPTION', + 'THEN', + 'CHECK', + 'INCREMENT', + 'OR', + 'TO', + 'CLUSTER', + 'INDEX', + 'ORDER', + 'TRIGGER', + 'COLUMN', + 'INITIAL', + 'PCTFREE', + 'UID', + 'COMMENT', + 'INSERT', + 'PRIOR', + 'UNION', + 'COMPRESS', + 'INTEGER', + 'PRIVILEGES', + 'UNIQUE', + 'CONNECT', + 'INTERSECT', + 'PUBLIC', + 'UPDATE', + 'CREATE', + 'INTO', + 'RAW', + 'USER', + 'CURRENT', + 'IS', + 'RENAME', + 'VALIDATE', + 'DATE', + 'LEVEL', + 'RESOURCE', + 'VALUES', + 'DECIMAL', + 'LIKE', + 'REVOKE', + 'VARCHAR', + 'DEFAULT', + 'LOCK', + 'ROW', + 'VARCHAR2', + 'DELETE', + 'LONG', + 'ROWID', + 'VIEW', + 'DESC', + 'MAXEXTENTS', + 'ROWLABEL', + 'WHENEVER', + 'DISTINCT', + 'MINUS', + 'ROWNUM', + 'WHERE', + 'DROP', + 'MODE', + 'ROWS', + 'WITH', +); +// }}} + +?> diff --git a/lib/Pear/MDB2/Schema/Reserved/pgsql.php b/lib/Pear/MDB2/Schema/Reserved/pgsql.php new file mode 100644 index 0000000..d358e9c --- /dev/null +++ b/lib/Pear/MDB2/Schema/Reserved/pgsql.php @@ -0,0 +1,147 @@ + | +// +----------------------------------------------------------------------+ +// +// }}} +// {{{ $GLOBALS['_MDB2_Schema_Reserved']['pgsql'] +/** + * Has a list of reserved words of pgsql + * + * @package MDB2_Schema + * @category Database + * @access protected + * @author Marcelo Santos Araujo + */ +$GLOBALS['_MDB2_Schema_Reserved']['pgsql'] = array( + 'ALL', + 'ANALYSE', + 'ANALYZE', + 'AND', + 'ANY', + 'AS', + 'ASC', + 'AUTHORIZATION', + 'BETWEEN', + 'BINARY', + 'BOTH', + 'CASE', + 'CAST', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'CONSTRAINT', + 'CREATE', + 'CURRENT_DATE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'DEFAULT', + 'DEFERRABLE', + 'DESC', + 'DISTINCT', + 'DO', + 'ELSE', + 'END', + 'EXCEPT', + 'FALSE', + 'FOR', + 'FOREIGN', + 'FREEZE', + 'FROM', + 'FULL', + 'GRANT', + 'GROUP', + 'HAVING', + 'ILIKE', + 'IN', + 'INITIALLY', + 'INNER', + 'INTERSECT', + 'INTO', + 'IS', + 'ISNULL', + 'JOIN', + 'LEADING', + 'LEFT', + 'LIKE', + 'LIMIT', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'NATURAL', + 'NEW', + 'NOT', + 'NOTNULL', + 'NULL', + 'OFF', + 'OFFSET', + 'OLD', + 'ON', + 'ONLY', + 'OR', + 'ORDER', + 'OUTER', + 'OVERLAPS', + 'PLACING', + 'PRIMARY', + 'REFERENCES', + 'SELECT', + 'SESSION_USER', + 'SIMILAR', + 'SOME', + 'TABLE', + 'THEN', + 'TO', + 'TRAILING', + 'TRUE', + 'UNION', + 'UNIQUE', + 'USER', + 'USING', + 'VERBOSE', + 'WHEN', + 'WHERE' +); +// }}} +?> + diff --git a/lib/Pear/MDB2/Schema/Validate.php b/lib/Pear/MDB2/Schema/Validate.php new file mode 100644 index 0000000..21be024 --- /dev/null +++ b/lib/Pear/MDB2/Schema/Validate.php @@ -0,0 +1,922 @@ + + * Author: Igor Feghali + * + * @category Database + * @package MDB2_Schema + * @author Christian Dickmann + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id: Validate.php,v 1.42 2008/11/30 03:34:00 clockwerx Exp $ + * @link http://pear.php.net/packages/MDB2_Schema + */ + +/** + * Validates an XML schema file + * + * @category Database + * @package MDB2_Schema + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema_Validate +{ + // {{{ properties + + var $fail_on_invalid_names = true; + + var $valid_types = array(); + + var $force_defaults = true; + + // }}} + // {{{ constructor + + function __construct($fail_on_invalid_names = true, $valid_types = array(), $force_defaults = true) + { + if (empty($GLOBALS['_MDB2_Schema_Reserved'])) { + $GLOBALS['_MDB2_Schema_Reserved'] = array(); + } + + if (is_array($fail_on_invalid_names)) { + $this->fail_on_invalid_names = array_intersect($fail_on_invalid_names, + array_keys($GLOBALS['_MDB2_Schema_Reserved'])); + } elseif ($fail_on_invalid_names === true) { + $this->fail_on_invalid_names = array_keys($GLOBALS['_MDB2_Schema_Reserved']); + } else { + $this->fail_on_invalid_names = array(); + } + $this->valid_types = $valid_types; + $this->force_defaults = $force_defaults; + } + + function MDB2_Schema_Validate($fail_on_invalid_names = true, $valid_types = array(), $force_defaults = true) + { + $this->__construct($fail_on_invalid_names, $valid_types, $force_defaults); + } + + // }}} + // {{{ raiseError() + + function &raiseError($ecode, $msg = null) + { + $error =& MDB2_Schema::raiseError($ecode, null, null, $msg); + return $error; + } + + // }}} + // {{{ isBoolean() + + /** + * Verifies if a given value can be considered boolean. If yes, set value + * to true or false according to its actual contents and return true. If + * not, keep its contents untouched and return false. + * + * @param mixed &$value value to be checked + * + * @return bool + * + * @access public + * @static + */ + function isBoolean(&$value) + { + if (is_bool($value)) { + return true; + } + + if ($value === 0 || $value === 1 || $value === '') { + $value = (bool)$value; + return true; + } + + if (!is_string($value)) { + return false; + } + + switch ($value) { + case '0': + case 'N': + case 'n': + case 'no': + case 'false': + $value = false; + break; + case '1': + case 'Y': + case 'y': + case 'yes': + case 'true': + $value = true; + break; + default: + return false; + } + return true; + } + + // }}} + // {{{ validateTable() + + /* Definition */ + /** + * Checks whether the definition of a parsed table is valid. Modify table + * definition when necessary. + * + * @param array $tables multi dimensional array that contains the + * tables of current database. + * @param array &$table multi dimensional array that contains the + * structure and optional data of the table. + * @param string $table_name name of the parsed table + * + * @return bool|error object + * + * @access public + */ + function validateTable($tables, &$table, $table_name) + { + /* Have we got a name? */ + if (!$table_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'a table has to have a name'); + } + + /* Table name duplicated? */ + if (is_array($tables) && isset($tables[$table_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'table "'.$table_name.'" already exists'); + } + + /* Table name reserved? */ + if (is_array($this->fail_on_invalid_names)) { + $name = strtoupper($table_name); + foreach ($this->fail_on_invalid_names as $rdbms) { + if (in_array($name, $GLOBALS['_MDB2_Schema_Reserved'][$rdbms])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'table name "'.$table_name.'" is a reserved word in: '.$rdbms); + } + } + } + + /* Was */ + if (empty($table['was'])) { + $table['was'] = $table_name; + } + + /* Have we got fields? */ + if (empty($table['fields']) || !is_array($table['fields'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'tables need one or more fields'); + } + + /* Autoincrement */ + $autoinc = $primary = false; + foreach ($table['fields'] as $field_name => $field) { + if (!empty($field['autoincrement'])) { + if ($autoinc) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'there was already an autoincrement field in "'.$table_name.'" before "'.$field_name.'"'); + } + $autoinc = $field_name; + } + } + + /* + * Checking Indexes + * this have to be done here otherwise we can't + * guarantee that all table fields were already + * defined in the moment we are parsing indexes + */ + if (!empty($table['indexes']) && is_array($table['indexes'])) { + foreach ($table['indexes'] as $name => $index) { + $skip_index = false; + if (!empty($index['primary'])) { + /* + * Lets see if we should skip this index since there is + * already an auto increment on this field this implying + * a primary key index. + */ + if (count($index['fields']) == '1' + && $autoinc + && array_key_exists($autoinc, $index['fields'])) { + $skip_index = true; + } elseif ($autoinc || $primary) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'there was already an primary index or autoincrement field in "'.$table_name.'" before "'.$name.'"'); + } else { + $primary = true; + } + } + + if (!$skip_index && is_array($index['fields'])) { + foreach ($index['fields'] as $field_name => $field) { + if (!isset($table['fields'][$field_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'index field "'.$field_name.'" does not exist'); + } + if (!empty($index['primary']) + && !$table['fields'][$field_name]['notnull'] + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'all primary key fields must be defined notnull in "'.$table_name.'"'); + } + } + } else { + unset($table['indexes'][$name]); + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ validateField() + + /** + * Checks whether the definition of a parsed field is valid. Modify field + * definition when necessary. + * + * @param array $fields multi dimensional array that contains the + * fields of current table. + * @param array &$field multi dimensional array that contains the + * structure of the parsed field. + * @param string $field_name name of the parsed field + * + * @return bool|error object + * + * @access public + */ + function validateField($fields, &$field, $field_name) + { + /* Have we got a name? */ + if (!$field_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field name missing'); + } + + /* Field name duplicated? */ + if (is_array($fields) && isset($fields[$field_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "'.$field_name.'" already exists'); + } + + /* Field name reserverd? */ + if (is_array($this->fail_on_invalid_names)) { + $name = strtoupper($field_name); + foreach ($this->fail_on_invalid_names as $rdbms) { + if (in_array($name, $GLOBALS['_MDB2_Schema_Reserved'][$rdbms])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field name "'.$field_name.'" is a reserved word in: '.$rdbms); + } + } + } + + /* Type check */ + if (empty($field['type'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'no field type specified'); + } + if (!empty($this->valid_types) && !array_key_exists($field['type'], $this->valid_types)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'no valid field type ("'.$field['type'].'") specified'); + } + + /* Unsigned */ + if (array_key_exists('unsigned', $field) && !$this->isBoolean($field['unsigned'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'unsigned has to be a boolean value'); + } + + /* Fixed */ + if (array_key_exists('fixed', $field) && !$this->isBoolean($field['fixed'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'fixed has to be a boolean value'); + } + + /* Length */ + if (array_key_exists('length', $field) && $field['length'] <= 0) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'length has to be an integer greater 0'); + } + + // if it's a DECIMAL datatype, check if a 'scale' value is provided: + // 8,4 should be translated to DECIMAL(8,4) + if (is_float($this->valid_types[$field['type']]) + && !empty($field['length']) + && strpos($field['length'], ',') !== false + ) { + list($field['length'], $field['scale']) = explode(',', $field['length']); + } + + /* Was */ + if (empty($field['was'])) { + $field['was'] = $field_name; + } + + /* Notnull */ + if (empty($field['notnull'])) { + $field['notnull'] = false; + } + if (!$this->isBoolean($field['notnull'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "notnull" has to be a boolean value'); + } + + /* Default */ + if ($this->force_defaults + && !array_key_exists('default', $field) + && $field['type'] != 'clob' && $field['type'] != 'blob' + ) { + $field['default'] = $this->valid_types[$field['type']]; + } + if (array_key_exists('default', $field)) { + if ($field['type'] == 'clob' || $field['type'] == 'blob') { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field['type'].'"-fields are not allowed to have a default value'); + } + if ($field['default'] === '' && !$field['notnull']) { + $field['default'] = null; + } + } + if (isset($field['default']) + && PEAR::isError($result = $this->validateDataFieldValue($field, $field['default'], $field_name)) + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'default value of "'.$field_name.'" is incorrect: '.$result->getUserinfo()); + } + + /* Autoincrement */ + if (!empty($field['autoincrement'])) { + if (!$field['notnull']) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'all autoincrement fields must be defined notnull'); + } + + if (empty($field['default'])) { + $field['default'] = '0'; + } elseif ($field['default'] !== '0' && $field['default'] !== 0) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'all autoincrement fields must be defined default "0"'); + } + } + return MDB2_OK; + } + + // }}} + // {{{ validateIndex() + + /** + * Checks whether a parsed index is valid. Modify index definition when + * necessary. + * + * @param array $table_indexes multi dimensional array that contains the + * indexes of current table. + * @param array &$index multi dimensional array that contains the + * structure of the parsed index. + * @param string $index_name name of the parsed index + * + * @return bool|error object + * + * @access public + */ + function validateIndex($table_indexes, &$index, $index_name) + { + if (!$index_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'an index has to have a name'); + } + if (is_array($table_indexes) && isset($table_indexes[$index_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'index "'.$index_name.'" already exists'); + } + if (array_key_exists('unique', $index) && !$this->isBoolean($index['unique'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "unique" has to be a boolean value'); + } + if (array_key_exists('primary', $index) && !$this->isBoolean($index['primary'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "primary" has to be a boolean value'); + } + + /* Have we got fields? */ + if (empty($index['fields']) || !is_array($index['fields'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'indexes need one or more fields'); + } + + if (empty($index['was'])) { + $index['was'] = $index_name; + } + return MDB2_OK; + } + + // }}} + // {{{ validateIndexField() + + /** + * Checks whether a parsed index-field is valid. Modify its definition when + * necessary. + * + * @param array $index_fields multi dimensional array that contains the + * fields of current index. + * @param array &$field multi dimensional array that contains the + * structure of the parsed index-field. + * @param string $field_name name of the parsed index-field + * + * @return bool|error object + * + * @access public + */ + function validateIndexField($index_fields, &$field, $field_name) + { + if (is_array($index_fields) && isset($index_fields[$field_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'index field "'.$field_name.'" already exists'); + } + if (!$field_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'the index-field-name is required'); + } + if (empty($field['sorting'])) { + $field['sorting'] = 'ascending'; + } elseif ($field['sorting'] !== 'ascending' && $field['sorting'] !== 'descending') { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'sorting type unknown'); + } + return MDB2_OK; + } + + // }}} + // {{{ validateConstraint() + + /** + * Checks whether a parsed foreign key is valid. Modify its definition when + * necessary. + * + * @param array $table_constraints multi dimensional array that contains the + * constraints of current table. + * @param array &$constraint multi dimensional array that contains the + * structure of the parsed foreign key. + * @param string $constraint_name name of the parsed foreign key + * + * @return bool|error object + * + * @access public + */ + function validateConstraint($table_constraints, &$constraint, $constraint_name) + { + if (!$constraint_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'a foreign key has to have a name'); + } + if (is_array($table_constraints) && isset($table_constraints[$constraint_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'foreign key "'.$constraint_name.'" already exists'); + } + + /* Have we got fields? */ + if (empty($constraint['fields']) || !is_array($constraint['fields'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'foreign key "'.$constraint_name.'" need one or more fields'); + } + + /* Have we got referenced fields? */ + if (empty($constraint['references']) || !is_array($constraint['references'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'foreign key "'.$constraint_name.'" need to reference one or more fields'); + } + + /* Have we got referenced table? */ + if (empty($constraint['references']['table'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'foreign key "'.$constraint_name.'" need to reference a table'); + } + + if (empty($constraint['was'])) { + $constraint['was'] = $constraint_name; + } + return MDB2_OK; + } + + // }}} + // {{{ validateConstraintField() + + /** + * Checks whether a foreign-field is valid. + * + * @param array $constraint_fields multi dimensional array that contains the + * fields of current foreign key. + * @param string $field_name name of the parsed foreign-field + * + * @return bool|error object + * + * @access public + */ + function validateConstraintField($constraint_fields, $field_name) + { + if (!$field_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'empty value for foreign-field'); + } + if (is_array($constraint_fields) && isset($constraint_fields[$field_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'foreign field "'.$field_name.'" already exists'); + } + return MDB2_OK; + } + + // }}} + // {{{ validateConstraintReferencedField() + + /** + * Checks whether a foreign-referenced field is valid. + * + * @param array $referenced_fields multi dimensional array that contains the + * fields of current foreign key. + * @param string $field_name name of the parsed foreign-field + * + * @return bool|error object + * + * @access public + */ + function validateConstraintReferencedField($referenced_fields, $field_name) + { + if (!$field_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'empty value for referenced foreign-field'); + } + if (is_array($referenced_fields) && isset($referenced_fields[$field_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'foreign field "'.$field_name.'" already referenced'); + } + return MDB2_OK; + } + + // }}} + // {{{ validateSequence() + + /** + * Checks whether the definition of a parsed sequence is valid. Modify + * sequence definition when necessary. + * + * @param array $sequences multi dimensional array that contains the + * sequences of current database. + * @param array &$sequence multi dimensional array that contains the + * structure of the parsed sequence. + * @param string $sequence_name name of the parsed sequence + * + * @return bool|error object + * + * @access public + */ + function validateSequence($sequences, &$sequence, $sequence_name) + { + if (!$sequence_name) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'a sequence has to have a name'); + } + + if (is_array($sequences) && isset($sequences[$sequence_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'sequence "'.$sequence_name.'" already exists'); + } + + if (is_array($this->fail_on_invalid_names)) { + $name = strtoupper($sequence_name); + foreach ($this->fail_on_invalid_names as $rdbms) { + if (in_array($name, $GLOBALS['_MDB2_Schema_Reserved'][$rdbms])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'sequence name "'.$sequence_name.'" is a reserved word in: '.$rdbms); + } + } + } + + if (empty($sequence['was'])) { + $sequence['was'] = $sequence_name; + } + + if (!empty($sequence['on']) + && (empty($sequence['on']['table']) || empty($sequence['on']['field'])) + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'sequence "'.$sequence_name.'" on a table was not properly defined'); + } + return MDB2_OK; + } + + // }}} + // {{{ validateDatabase() + + /** + * Checks whether a parsed database is valid. Modify its structure and + * data when necessary. + * + * @param array &$database multi dimensional array that contains the + * structure and optional data of the database. + * + * @return bool|error object + * + * @access public + */ + function validateDatabase(&$database) + { + /* Have we got a name? */ + if (!is_array($database) || !isset($database['name']) || !$database['name']) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'a database has to have a name'); + } + + /* Database name reserved? */ + if (is_array($this->fail_on_invalid_names)) { + $name = strtoupper($database['name']); + foreach ($this->fail_on_invalid_names as $rdbms) { + if (in_array($name, $GLOBALS['_MDB2_Schema_Reserved'][$rdbms])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'database name "'.$database['name'].'" is a reserved word in: '.$rdbms); + } + } + } + + /* Create */ + if (isset($database['create']) + && !$this->isBoolean($database['create']) + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "create" has to be a boolean value'); + } + + /* Overwrite */ + if (isset($database['overwrite']) + && $database['overwrite'] !== '' + && !$this->isBoolean($database['overwrite']) + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "overwrite" has to be a boolean value'); + } + + /* + * This have to be done here otherwise we can't guarantee that all + * tables were already defined in the moment we are parsing constraints + */ + if (isset($database['tables'])) { + foreach ($database['tables'] as $table_name => $table) { + if (!empty($table['constraints'])) { + foreach ($table['constraints'] as $constraint_name => $constraint) { + $referenced_table_name = $constraint['references']['table']; + + if (!isset($database['tables'][$referenced_table_name])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'referenced table "'.$referenced_table_name.'" of foreign key "'.$constraint_name.'" of table "'.$table_name.'" does not exist'); + } + + if (empty($constraint['references']['fields'])) { + $referenced_table = $database['tables'][$referenced_table_name]; + + $primary = false; + + if (!empty($referenced_table['indexes'])) { + foreach ($referenced_table['indexes'] as $index_name => $index) { + if (array_key_exists('primary', $index) + && $index['primary'] + ) { + $primary = array(); + foreach ($index['fields'] as $field_name => $field) { + $primary[$field_name] = ''; + } + break; + } + } + } + + if (!$primary) { + foreach ($referenced_table['fields'] as $field_name => $field) { + if (array_key_exists('autoincrement', $field) + && $field['autoincrement'] + ) { + $primary = array( $field_name => '' ); + break; + } + } + } + + if (!$primary) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'referenced table "'.$referenced_table_name.'" has no primary key and no referenced field was specified for foreign key "'.$constraint_name.'" of table "'.$table_name.'"'); + } + + $constraint['references']['fields'] = $primary; + } + + /* the same number of referencing and referenced fields ? */ + if (count($constraint['fields']) != count($constraint['references']['fields'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'The number of fields in the referenced key must match those of the foreign key "'.$constraint_name.'"'); + } + + $database['tables'][$table_name]['constraints'][$constraint_name]['references']['fields'] = $constraint['references']['fields']; + } + } + } + } + + /* + * This have to be done here otherwise we can't guarantee that all + * tables were already defined in the moment we are parsing sequences + */ + if (isset($database['sequences'])) { + foreach ($database['sequences'] as $seq_name => $seq) { + if (!empty($seq['on']) + && empty($database['tables'][$seq['on']['table']]['fields'][$seq['on']['field']]) + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'sequence "'.$seq_name.'" was assigned on unexisting field/table'); + } + } + } + return MDB2_OK; + } + + // }}} + // {{{ validateDataField() + + /* Data Manipulation */ + /** + * Checks whether a parsed DML-field is valid. Modify its structure when + * necessary. This is called when validating INSERT and + * UPDATE. + * + * @param array $table_fields multi dimensional array that contains the + * definition for current table's fields. + * @param array $instruction_fields multi dimensional array that contains the + * parsed fields of the current DML instruction. + * @param string &$field array that contains the parsed instruction field + * + * @return bool|error object + * + * @access public + */ + function validateDataField($table_fields, $instruction_fields, &$field) + { + if (!$field['name']) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field-name has to be specified'); + } + + if (is_array($instruction_fields) && isset($instruction_fields[$field['name']])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'field "'.$field['name'].'" already initialized'); + } + + if (is_array($table_fields) && !isset($table_fields[$field['name']])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field['name'].'" is not defined'); + } + + if (!isset($field['group']['type'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field['name'].'" has no initial value'); + } + + if (isset($field['group']['data']) + && $field['group']['type'] == 'value' + && $field['group']['data'] !== '' + && PEAR::isError($result = $this->validateDataFieldValue($table_fields[$field['name']], $field['group']['data'], $field['name'])) + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + 'value of "'.$field['name'].'" is incorrect: '.$result->getUserinfo()); + } + + return MDB2_OK; + } + + // }}} + // {{{ validateDataFieldValue() + + /** + * Checks whether a given value is compatible with a table field. This is + * done when parsing a field for a INSERT or UPDATE instruction. + * + * @param array $field_def multi dimensional array that contains the + * definition for current table's fields. + * @param string &$field_value value to fill the parsed field + * @param string $field_name name of the parsed field + * + * @return bool|error object + * + * @access public + * @see MDB2_Schema_Validate::validateInsertField() + */ + function validateDataFieldValue($field_def, &$field_value, $field_name) + { + switch ($field_def['type']) { + case 'text': + case 'clob': + if (!empty($field_def['length']) && strlen($field_value) > $field_def['length']) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is larger than "'.$field_def['length'].'"'); + } + break; + case 'blob': + $field_value = pack('H*', $field_value); + if (!empty($field_def['length']) && strlen($field_value) > $field_def['length']) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is larger than "'.$field_def['type'].'"'); + } + break; + case 'integer': + if ($field_value != ((int)$field_value)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is not of type "'.$field_def['type'].'"'); + } + //$field_value = (int)$field_value; + if (!empty($field_def['unsigned']) && $field_def['unsigned'] && $field_value < 0) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" signed instead of unsigned'); + } + break; + case 'boolean': + if (!$this->isBoolean($field_value)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is not of type "'.$field_def['type'].'"'); + } + break; + case 'date': + if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/', $field_value) + && $field_value !== 'CURRENT_DATE' + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is not of type "'.$field_def['type'].'"'); + } + break; + case 'timestamp': + if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $field_value) + && strcasecmp($field_value, 'now()') != 0 + && $field_value !== 'CURRENT_TIMESTAMP' + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is not of type "'.$field_def['type'].'"'); + } + break; + case 'time': + if (!preg_match("/([0-9]{2}):([0-9]{2}):([0-9]{2})/", $field_value) + && $field_value !== 'CURRENT_TIME' + ) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is not of type "'.$field_def['type'].'"'); + } + break; + case 'float': + case 'double': + if ($field_value != (double)$field_value) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, + '"'.$field_value.'" is not of type "'.$field_def['type'].'"'); + } + //$field_value = (double)$field_value; + break; + } + return MDB2_OK; + } +} + +?> diff --git a/lib/Pear/MDB2/Schema/Writer.php b/lib/Pear/MDB2/Schema/Writer.php new file mode 100644 index 0000000..5ae4918 --- /dev/null +++ b/lib/Pear/MDB2/Schema/Writer.php @@ -0,0 +1,581 @@ + + * Author: Igor Feghali + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith + * @author Igor Feghali + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id: Writer.php,v 1.40 2008/11/30 03:34:00 clockwerx Exp $ + * @link http://pear.php.net/packages/MDB2_Schema + */ + +/** + * Writes an XML schema file + * + * @category Database + * @package MDB2_Schema + * @author Lukas Smith + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/MDB2_Schema + */ +class MDB2_Schema_Writer +{ + // {{{ properties + + var $valid_types = array(); + + // }}} + // {{{ constructor + + function __construct($valid_types = array()) + { + $this->valid_types = $valid_types; + } + + function MDB2_Schema_Writer($valid_types = array()) + { + $this->__construct($valid_types); + } + + // }}} + // {{{ raiseError() + + /** + * This method is used to communicate an error and invoke error + * callbacks etc. Basically a wrapper for PEAR::raiseError + * without the message string. + * + * @param int|PEAR_Error $code integer error code or and PEAR_Error instance + * @param int $mode error mode, see PEAR_Error docs + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * @param string $options Extra debug information. Defaults to the last + * query and native error code. + * + * @return object a PEAR error object + * @access public + * @see PEAR_Error + */ + function &raiseError($code = null, $mode = null, $options = null, $userinfo = null) + { + $error =& MDB2_Schema::raiseError($code, $mode, $options, $userinfo); + return $error; + } + + // }}} + // {{{ _escapeSpecialChars() + + /** + * add escapecharacters to all special characters in a string + * + * @param string $string string that should be escaped + * + * @return string escaped string + * @access protected + */ + function _escapeSpecialChars($string) + { + if (!is_string($string)) { + $string = strval($string); + } + + $escaped = ''; + for ($char = 0, $count = strlen($string); $char < $count; $char++) { + switch ($string[$char]) { + case '&': + $escaped .= '&'; + break; + case '>': + $escaped .= '>'; + break; + case '<': + $escaped .= '<'; + break; + case '"': + $escaped .= '"'; + break; + case '\'': + $escaped .= '''; + break; + default: + $code = ord($string[$char]); + if ($code < 32 || $code > 127) { + $escaped .= "&#$code;"; + } else { + $escaped .= $string[$char]; + } + break; + } + } + return $escaped; + } + + // }}} + // {{{ _dumpBoolean() + + /** + * dump the structure of a sequence + * + * @param string $boolean boolean value or variable definition + * + * @return string with xml boolea definition + * @access private + */ + function _dumpBoolean($boolean) + { + if (is_string($boolean)) { + if ($boolean !== 'true' || $boolean !== 'false' + || preg_match('/.*/', $boolean) + ) { + return $boolean; + } + } + return $boolean ? 'true' : 'false'; + } + + // }}} + // {{{ dumpSequence() + + /** + * dump the structure of a sequence + * + * @param string $sequence_definition sequence definition + * @param string $sequence_name sequence name + * @param string $eol end of line characters + * @param integer $dump determines what data to dump + * MDB2_SCHEMA_DUMP_ALL : the entire db + * MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db + * MDB2_SCHEMA_DUMP_CONTENT : only the content of the db + * + * @return mixed string xml sequence definition on success, or a error object + * @access public + */ + function dumpSequence($sequence_definition, $sequence_name, $eol, $dump = MDB2_SCHEMA_DUMP_ALL) + { + $buffer = "$eol $eol $sequence_name$eol"; + if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT) { + if (!empty($sequence_definition['start'])) { + $start = $sequence_definition['start']; + $buffer .= " $start$eol"; + } + } + + if (!empty($sequence_definition['on'])) { + $buffer .= " $eol"; + $buffer .= " ".$sequence_definition['on']['table']; + $buffer .= "
$eol ".$sequence_definition['on']['field']; + $buffer .= "$eol
$eol"; + } + $buffer .= "
$eol"; + + return $buffer; + } + + // }}} + // {{{ dumpDatabase() + + /** + * Dump a previously parsed database structure in the Metabase schema + * XML based format suitable for the Metabase parser. This function + * may optionally dump the database definition with initialization + * commands that specify the data that is currently present in the tables. + * + * @param array $database_definition unknown + * @param array $arguments associative array that takes pairs of tag + * names and values that define dump options. + * array ( + * 'output_mode' => String + * 'file' : dump into a file + * default: dump using a function + * 'output' => String + * depending on the 'Output_Mode' + * name of the file + * name of the function + * 'end_of_line' => String + * end of line delimiter that should be used + * default: "\n" + * ); + * @param integer $dump determines what data to dump + * MDB2_SCHEMA_DUMP_ALL : the entire db + * MDB2_SCHEMA_DUMP_STRUCTURE : only the structure of the db + * MDB2_SCHEMA_DUMP_CONTENT : only the content of the db + * + * @return mixed MDB2_OK on success, or a error object + * @access public + */ + function dumpDatabase($database_definition, $arguments, $dump = MDB2_SCHEMA_DUMP_ALL) + { + if (!empty($arguments['output'])) { + if (!empty($arguments['output_mode']) && $arguments['output_mode'] == 'file') { + $fp = fopen($arguments['output'], 'w'); + if ($fp === false) { + return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null, + 'it was not possible to open output file'); + } + + $output = false; + } elseif (is_callable($arguments['output'])) { + $output = $arguments['output']; + } else { + return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null, + 'no valid output function specified'); + } + } else { + return $this->raiseError(MDB2_SCHEMA_ERROR_WRITER, null, null, + 'no output method specified'); + } + + $eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n"; + + $sequences = array(); + if (!empty($database_definition['sequences']) + && is_array($database_definition['sequences']) + ) { + foreach ($database_definition['sequences'] as $sequence_name => $sequence) { + $table = !empty($sequence['on']) ? $sequence['on']['table'] :''; + + $sequences[$table][] = $sequence_name; + } + } + + $buffer = ''.$eol; + $buffer .= "$eol$eol ".$database_definition['name'].""; + $buffer .= "$eol ".$this->_dumpBoolean($database_definition['create']).""; + $buffer .= "$eol ".$this->_dumpBoolean($database_definition['overwrite'])."$eol"; + $buffer .= "$eol ".$database_definition['charset']."$eol"; + + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + } + + if (!empty($database_definition['tables']) && is_array($database_definition['tables'])) { + foreach ($database_definition['tables'] as $table_name => $table) { + $buffer = "$eol $eol$eol $table_name$eol"; + if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_STRUCTURE) { + $buffer .= "$eol $eol"; + if (!empty($table['fields']) && is_array($table['fields'])) { + foreach ($table['fields'] as $field_name => $field) { + if (empty($field['type'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null, + 'it was not specified the type of the field "'. + $field_name.'" of the table "'.$table_name.'"'); + } + if (!empty($this->valid_types) && !array_key_exists($field['type'], $this->valid_types)) { + return $this->raiseError(MDB2_SCHEMA_ERROR_UNSUPPORTED, null, null, + 'type "'.$field['type'].'" is not yet supported'); + } + $buffer .= "$eol $eol $field_name$eol "; + $buffer .= $field['type']."$eol"; + if (!empty($field['fixed']) && $field['type'] === 'text') { + $buffer .= " ".$this->_dumpBoolean($field['fixed'])."$eol"; + } + if (array_key_exists('default', $field) + && $field['type'] !== 'clob' && $field['type'] !== 'blob' + ) { + $buffer .= ' '.$this->_escapeSpecialChars($field['default'])."$eol"; + } + if (!empty($field['notnull'])) { + $buffer .= " ".$this->_dumpBoolean($field['notnull'])."$eol"; + } else { + $buffer .= " false$eol"; + } + if (!empty($field['autoincrement'])) { + $buffer .= " " . $field['autoincrement'] ."$eol"; + } + if (!empty($field['unsigned'])) { + $buffer .= " ".$this->_dumpBoolean($field['unsigned'])."$eol"; + } + if (!empty($field['length'])) { + $buffer .= ' '.$field['length']."$eol"; + } + $buffer .= " $eol"; + } + } + + if (!empty($table['indexes']) && is_array($table['indexes'])) { + foreach ($table['indexes'] as $index_name => $index) { + if (strtolower($index_name) === 'primary') { + $index_name = $table_name . '_pKey'; + } + $buffer .= "$eol $eol $index_name$eol"; + if (!empty($index['unique'])) { + $buffer .= " ".$this->_dumpBoolean($index['unique'])."$eol"; + } + + if (!empty($index['primary'])) { + $buffer .= " ".$this->_dumpBoolean($index['primary'])."$eol"; + } + + foreach ($index['fields'] as $field_name => $field) { + $buffer .= " $eol $field_name$eol"; + if (!empty($field) && is_array($field)) { + $buffer .= ' '.$field['sorting']."$eol"; + } + $buffer .= " $eol"; + } + $buffer .= " $eol"; + } + } + + if (!empty($table['constraints']) && is_array($table['constraints'])) { + foreach ($table['constraints'] as $constraint_name => $constraint) { + $buffer .= "$eol $eol $constraint_name$eol"; + if (empty($constraint['fields']) || !is_array($constraint['fields'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null, + 'it was not specified a field for the foreign key "'. + $constraint_name.'" of the table "'.$table_name.'"'); + } + if (!is_array($constraint['references']) || empty($constraint['references']['table'])) { + return $this->raiseError(MDB2_SCHEMA_ERROR_VALIDATE, null, null, + 'it was not specified the referenced table of the foreign key "'. + $constraint_name.'" of the table "'.$table_name.'"'); + } + if (!empty($constraint['match'])) { + $buffer .= " ".$constraint['match']."$eol"; + } + if (!empty($constraint['ondelete'])) { + $buffer .= " ".$constraint['ondelete']."$eol"; + } + if (!empty($constraint['onupdate'])) { + $buffer .= " ".$constraint['onupdate']."$eol"; + } + if (!empty($constraint['deferrable'])) { + $buffer .= " ".$constraint['deferrable']."$eol"; + } + if (!empty($constraint['initiallydeferred'])) { + $buffer .= " ".$constraint['initiallydeferred']."$eol"; + } + foreach ($constraint['fields'] as $field_name => $field) { + $buffer .= " $field_name$eol"; + } + $buffer .= " $eol
".$constraint['references']['table']."
$eol"; + foreach ($constraint['references']['fields'] as $field_name => $field) { + $buffer .= " $field_name$eol"; + } + $buffer .= " $eol"; + + $buffer .= " $eol"; + } + } + + $buffer .= "$eol $eol"; + } + + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + } + + $buffer = ''; + if ($dump == MDB2_SCHEMA_DUMP_ALL || $dump == MDB2_SCHEMA_DUMP_CONTENT) { + if (!empty($table['initialization']) && is_array($table['initialization'])) { + $buffer = "$eol $eol"; + foreach ($table['initialization'] as $instruction) { + switch ($instruction['type']) { + case 'insert': + $buffer .= "$eol $eol"; + foreach ($instruction['data']['field'] as $field) { + $field_name = $field['name']; + + $buffer .= "$eol $eol $field_name$eol"; + $buffer .= $this->writeExpression($field['group'], 5, $arguments); + $buffer .= " $eol"; + } + $buffer .= "$eol $eol"; + break; + case 'update': + $buffer .= "$eol $eol"; + foreach ($instruction['data']['field'] as $field) { + $field_name = $field['name']; + + $buffer .= "$eol $eol $field_name$eol"; + $buffer .= $this->writeExpression($field['group'], 5, $arguments); + $buffer .= " $eol"; + } + + if (!empty($instruction['data']['where']) + && is_array($instruction['data']['where']) + ) { + $buffer .= " $eol"; + $buffer .= $this->writeExpression($instruction['data']['where'], 5, $arguments); + $buffer .= " $eol"; + } + + $buffer .= "$eol $eol"; + break; + case 'delete': + $buffer .= "$eol $eol$eol"; + if (!empty($instruction['data']['where']) + && is_array($instruction['data']['where']) + ) { + $buffer .= " $eol"; + $buffer .= $this->writeExpression($instruction['data']['where'], 5, $arguments); + $buffer .= " $eol"; + } + $buffer .= "$eol $eol"; + break; + } + } + $buffer .= "$eol $eol"; + } + } + $buffer .= "$eol $eol"; + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + } + + if (isset($sequences[$table_name])) { + foreach ($sequences[$table_name] as $sequence) { + $result = $this->dumpSequence($database_definition['sequences'][$sequence], + $sequence, $eol, $dump); + if (PEAR::isError($result)) { + return $result; + } + + if ($output) { + call_user_func($output, $result); + } else { + fwrite($fp, $result); + } + } + } + } + } + + if (isset($sequences[''])) { + foreach ($sequences[''] as $sequence) { + $result = $this->dumpSequence($database_definition['sequences'][$sequence], + $sequence, $eol, $dump); + if (PEAR::isError($result)) { + return $result; + } + + if ($output) { + call_user_func($output, $result); + } else { + fwrite($fp, $result); + } + } + } + + $buffer = "$eol
$eol"; + if ($output) { + call_user_func($output, $buffer); + } else { + fwrite($fp, $buffer); + fclose($fp); + } + + return MDB2_OK; + } + + // }}} + // {{{ writeExpression() + + /** + * Dumps the structure of an element. Elements can be value, column, + * function or expression. + * + * @param array $element multi dimensional array that represents the parsed element + * of a DML instruction. + * @param integer $offset base indentation width + * @param array $arguments associative array that takes pairs of tag + * names and values that define dump options. + * + * @return string + * + * @access public + * @see MDB2_Schema_Writer::dumpDatabase() + */ + function writeExpression($element, $offset = 0, $arguments = null) + { + $eol = isset($arguments['end_of_line']) ? $arguments['end_of_line'] : "\n"; + $str = ''; + + $indent = str_repeat(' ', $offset); + $noffset = $offset + 1; + + switch ($element['type']) { + case 'value': + $str .= "$indent".$this->_escapeSpecialChars($element['data'])."$eol"; + break; + case 'column': + $str .= "$indent".$this->_escapeSpecialChars($element['data'])."$eol"; + break; + case 'function': + $str .= "$indent$eol$indent ".$this->_escapeSpecialChars($element['data']['name'])."$eol"; + + if (!empty($element['data']['arguments']) + && is_array($element['data']['arguments']) + ) { + foreach ($element['data']['arguments'] as $v) { + $str .= $this->writeExpression($v, $noffset, $arguments); + } + } + + $str .= "$indent$eol"; + break; + case 'expression': + $str .= "$indent$eol"; + $str .= $this->writeExpression($element['data']['operants'][0], $noffset, $arguments); + $str .= "$indent ".$element['data']['operator']."$eol"; + $str .= $this->writeExpression($element['data']['operants'][1], $noffset, $arguments); + $str .= "$indent$eol"; + break; + } + return $str; + } + + // }}} +} +?> diff --git a/lib/Pear/Net/Nmap.php b/lib/Pear/Net/Nmap.php new file mode 100644 index 0000000..cbed94a --- /dev/null +++ b/lib/Pear/Net/Nmap.php @@ -0,0 +1,271 @@ + + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ + +require_once 'System.php'; +require_once 'Nmap/Parser.php'; +require_once 'Nmap/Exception.php'; + +/** + * Simple wrapper interface for the Nmap utility. + * + * @category Net + * @package Net_Nmap + * @author Luca Corbo + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ +class Net_Nmap +{ + + /** + * Location of the nmap binary + * + * @var string $nmap_path + * @see Net_Nmap::__construct() + * @access private + */ + private $_nmap_binary; + + /** + * Absolute path to store the Nmap XML output file. + * + * @var string + * @see Net_Nmap::__construct() + * @access private + */ + private $_output_file = null; + + /** + * Delete Nmap output file after parsing + * + * @var string + * @access private + */ + private $_delete_output_file = true; + + /** + * The hostname/IP failed to resolve + * + * @var array + * @access private + */ + private $_failed_to_resolve = array(); + + /** + * Nmap option arguments + * + * @var array + * @link http://nmap.org/book/man-briefoptions.html + * @access private + */ + private $_nmap_options = array(); + + /** + * Creates a new Nmap object + * + * Available options are: + * + * - string nmap_binary: The location of the Nmap binary. + * If not specified, defaults to '/usr/bin/nmap'. + * + * - string output_file: Path to store the Nmap XML output file. + * If not specified, a temporary file is created. + * + * @param array $options optional. An array of options used to create the + * Nmap object. All options must be optional and are + * represented as key-value pairs. + * + * @access public + */ + public function __construct(array $options = array()) + { + if (array_key_exists('nmap_binary', $options)) { + $this->_nmap_binary = (string)$options['nmap_binary']; + } else { + $this->_nmap_binary = System::which('nmap'); + } + + if (array_key_exists('output_file', $options)) { + $this->_output_file = (string)$options['output_file']; + } + } + + /** + * Prepare the command to execute + * + * @param array $targets contains hostnames, IP addresses, networks to scan + * + * @return string + * @access private + */ + private function _createCommandLine($targets) + { + + if ($this->_output_file === null) { + $this->_output_file = tempnam(System::tmpdir(), __CLASS__); + } else { + $this->_delete_output_file = false; + } + + $cmd = escapeshellarg($this->_nmap_binary); + $cmd .= ' ' . implode(' ', $this->_nmap_options); + $cmd .= ' -oX ' . escapeshellarg($this->_output_file) . ' '; + foreach ($targets as $target) { + $cmd .= escapeshellarg($target) . ' '; + } + $cmd .= '2>&1'; + if (OS_WINDOWS) { + $cmd = '"' . $cmd . '"'; + } + return $cmd; + } + + /** + * Scan the specified target + * + * @param array $targets Array contains hostnames, IP addresses, + * networks to scan + * + * @return true | PEAR_Error + * @throws Net_Nmap_Exception If Nmap binary does not exist or + * the command failed to execute. + * @access public + */ + public function scan($targets) + { + exec($this->_createCommandLine($targets), $out, $ret_var); + + if ($ret_var > 0) { + throw new Net_Nmap_Exception(implode(' ', $out)); + } else { + foreach ($out as $row) { + preg_match('@^Failed to resolve given hostname/IP:\s+(.+)\.\s+Note@', + $row, + $matches); + if (count($matches) > 0) { + $this->_failed_to_resolve[] = $matches[1]; + } + } + return true; + } + } + + /** + * Get all the discovered hosts + * + * @param string $output_file Absolute path of the file to parse (optional) + * + * @return ArrayIterator Returns Hosts Object on success. + * @throws Net_Nmap_Exception If a parsing error occurred. + * @access public + */ + public function parseXMLOutput($output_file = null) + { + if ($output_file === null) { + $output_file = $this->_output_file; + } else { + $this->_delete_output_file = false; + } + $parse = new Net_Nmap_Parser(); + $parse->setInputFile($output_file); + $parse->folding = false; + + $res = $parse->parse(); + if (PEAR::isError($res)) { + throw new Net_Nmap_Exception($res); + } + if ($this->_delete_output_file) { + unlink($this->_output_file); + } + return $parse->getHosts(); + } + + /** + * Get all the hostnames/IPs failed to resolve during scanning operation + * + * @return Array Returns array + * @access public + */ + public function getFailedToResolveHosts() + { + return $this->_failed_to_resolve; + } + + /** + * Enable Nmap options + * Available nmap options are: + * + * - boolean os_detection: Enable the OS detection (-O). + * - boolean service_info: Probe open ports to determine + * service/version info (-sV) + * - string port_ranges : Port ranges, only scan + * specified ports (-p ) + * Ex: 22; 1-65535; U:53,111,137,T:21-25,80,139,8080 + * - boolean all_options : Enables OS detection and Version detection, + * Script scanning and Traceroute (-A) + * + * @param array $nmap_options Nmap options to enable + * + * @return void + * @link http://nmap.org/book/man-briefoptions.html + * @throws Net_Nmap_Exception If the option argument is not valid. + * @access public + */ + public function enableOptions($nmap_options) + { + $enable_os_detection = array_key_exists('os_detection', $nmap_options); + $enable_service_info = array_key_exists('service_info', $nmap_options); + $enable_port_ranges = array_key_exists('port_ranges', $nmap_options); + $enable_all_options = array_key_exists('all_options', $nmap_options); + + if ($enable_os_detection && $nmap_options['os_detection']) { + $this->_nmap_options[] = '-O'; + } + if ($enable_service_info && $nmap_options['service_info']) { + $this->_nmap_options[] = '-sV'; + } + if ($enable_port_ranges) { + $port_ranges = $nmap_options['port_ranges']; + $allowed_format = '([U,T]\:)*[0-9]+(-[0-9]+)*'; + + $regexp = '/^' . $allowed_format . '(,' . $allowed_format . ')*$/'; + if (preg_match($regexp, $port_ranges)) { + $this->_nmap_options[] = '-p ' . $port_ranges; + } else { + throw new Net_Nmap_Exception('Port ranges: not valid format.'); + } + } + if ($enable_all_options && $nmap_options['all_options']) { + $this->_nmap_options[] = '-A'; + } + } +} +?> \ No newline at end of file diff --git a/lib/Pear/Net/Nmap/Exception.php b/lib/Pear/Net/Nmap/Exception.php new file mode 100644 index 0000000..18016f8 --- /dev/null +++ b/lib/Pear/Net/Nmap/Exception.php @@ -0,0 +1,63 @@ + + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ + +require_once 'PEAR/Exception.php'; + +/** + * An exception thrown by Net_Nmap when it encounters an unrecoverable error. + * + * PHP version 5 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA + * + * @category Net + * @package Net_Nmap + * @author Luca Corbo + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ +class Net_Nmap_Exception extends PEAR_Exception +{ + +} +?> \ No newline at end of file diff --git a/lib/Pear/Net/Nmap/Host.php b/lib/Pear/Net/Nmap/Host.php new file mode 100644 index 0000000..cecd0c3 --- /dev/null +++ b/lib/Pear/Net/Nmap/Host.php @@ -0,0 +1,242 @@ + + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ + +/** + * Host object + * + * @category Net + * @package Net_Nmap + * @author Luca Corbo + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ +class Net_Nmap_Host +{ + + /** + * Status of the Host + * @var string + * @access private + */ + private $_status; + + /** + * Contains all discovered addresses grouped by type + * Example: + * Array ([mac] => Array ([0] => 00:19:E3:07:D5:37) + * [ipv4] => Array ([0] => 192.168.1.100 + * [1] => 192.168.1.112)) + * @var array + * @access private + */ + private $_addresses = array(); + + /** + * Contains all discovered hostnames + * @var array + * @access private + */ + private $_hostnames = array(); + + /** + * Contains the name of the discovered Operating System + * and the relative accuracy. + * Elements are sorted by decreasing accuracy + * @var array + * @access private + */ + private $_os = array(); + + /** + * Contains all discovered Service objects + * @var ArrayIterator + * @access private + */ + private $_services; + + /** + * Constructor + * + * @return void + * @access public + */ + public function __construct() + { + $this->_services = new ArrayIterator(); + } + + /** + * Returns the value of the discovered address + * By default the first ipv4 address is returned + * + * @param string $type Type of address (i.e. mac, ipv4, ipv6) + * @param int $index The index number of the parameter to obtain + * + * @return string + * @access public + */ + public function getAddress($type = 'ipv4', $index = 0) + { + return $this->_addresses[$type][$index]; + } + + /** + * Add an address to the addresses container + * + * @param string $type Type of address (i.e. mac, ipv4, ipv6) + * @param string $value Address value + * + * @return void + * @access public + */ + public function addAddress($type, $value) + { + $this->_addresses = array_merge_recursive($this->_addresses, + array($type => array($value))); + } + + /** + * Returns the value of the discovered hostname + * By default the first hostname is returned + * + * @param int $index The index number of the parameter to obtain + * + * @return string + * @access public + */ + public function getHostname($index = 0) + { + if (count($this->_hostnames) == 0) { + return 'unknown'; + } + return $this->_hostnames[$index]; + } + + /** + * Add a hostname to the hostnames container + * + * @param string $value hostaname value + * + * @return void + * @access public + */ + public function addHostname($value) + { + $this->_hostnames[] = $value; + } + + /** + * Add a service object to the services container + * + * @param object $service Service object + * + * @return void + * @access public + */ + public function addService($service) + { + $this->_services->append($service); + } + + /** + * Returns the discovered services + * + * @return ArrayIterator + * @access public + */ + public function getServices() + { + return $this->_services; + } + + /** + * Add an the accuracy ant the OS name to the OS container + * + * @param string $accuracy accuracy value + * @param string $name OS name value + * + * @return void + * @access public + */ + public function addOS($accuracy, $name) + { + $this->_os[] = array('accuracy'=> $accuracy, 'name' => $name); + } + + /** + * Returns the name of discovered OS with the highest accuracy value. + * + * @return string + * @access public + */ + public function getOS() + { + array_multisort($this->_os, SORT_DESC); + return $this->_os[0]['name']; + } + + /** + * Returns the OS container the discovered OS + * All informations are sorted by decreasing accuracy + * + * @return array + * @access public + */ + public function getAllOS() + { + return $this->_os; + } + + /** + * Set the status of the Host + * + * @param string $status Host status + * + * @return void + * @access public + */ + public function setStatus($status) + { + $this->_status = $status; + } + + /** + * Returns the status of the Host + * + * @return string + * @access public + */ + public function getStatus() + { + return $this->_status; + } +} +?> \ No newline at end of file diff --git a/lib/Pear/Net/Nmap/Parser.php b/lib/Pear/Net/Nmap/Parser.php new file mode 100644 index 0000000..4a09c7f --- /dev/null +++ b/lib/Pear/Net/Nmap/Parser.php @@ -0,0 +1,163 @@ + + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ + +require_once 'XML/Parser.php'; +require_once 'Net/Nmap/Host.php'; +require_once 'Net/Nmap/Service.php'; + +/** + * Parses a Nmap XML output file + * + * @category Net + * @package Net_Nmap + * @author Luca Corbo + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + * @link http://nmap.org/data/nmap.dtd + */ +class Net_Nmap_Parser extends XML_Parser +{ + /** + * Container for the host objects + * @var ArrayIterator + * @access private + */ + private $_hosts; + + /** + * start handler + * + * @param resource $parser xml parser resource + * @param string $name element name + * @param array $attribs attributes + * + * @return void + * @access public + */ + public function startHandler($parser, $name, $attribs) + { + switch ($name) { + case 'host': + if (!$this->_hosts instanceof ArrayIterator) { + $this->_hosts = new ArrayIterator(); + } + $this->_hosts->append(new Net_Nmap_Host()); + if ($this->_hosts->count() > 1) { + $this->_hosts->next(); + } + $this->_host = $this->_hosts->current(); + break; + case 'status': + $this->_host->setStatus($attribs['state']); + break; + case 'address': + $this->_host->addAddress($attribs['addrtype'], $attribs['addr']); + break; + case 'hostname': + $this->_host->addHostname($attribs['name']); + break; + case 'port': + $this->_service = new Net_Nmap_Service(); + + $this->_service->protocol = @$attribs['protocol']; + $this->_service->port = @$attribs['portid']; + break; + case 'service': + $this->_service->name = @$attribs['name']; + $this->_service->product = @$attribs['product']; + $this->_service->version = @$attribs['version']; + $this->_service->extrainfo = @$attribs['extrainfo']; + if (isset($attribs['ostype'])) { + $this->_host->addOS('0', $attribs['ostype']); + } + break; + case 'osmatch': + $this->_host->addOS($attribs['accuracy'], $attribs['name']); + break; + default: + $this->currentTag = $name; + break; + } + } + + /** + * end handler + * + * @param resource $parser xml parser resource + * @param string $name element name + * + * @return void + * @access public + */ + public function endHandler($parser, $name) + { + switch ($name) { + case 'port': + $this->_host->addService($this->_service); + break; + default: + break; + } + + $this->currentTag = null; + } + + /** + * handle character data + * + * @param resource $parser xml parser resource + * @param string $data data + * + * @return void | true if $data is empty + * @access public + */ + public function cdataHandler($parser, $data) + { + $data = trim($data); + if (empty($data)) { + return true; + } + } + + /** + * Get all the discovered hosts + * + * @return ArrayIterator The discovered hosts + * @access public + */ + public function getHosts() + { + return $this->_hosts; + } +} + + +?> \ No newline at end of file diff --git a/lib/Pear/Net/Nmap/Service.php b/lib/Pear/Net/Nmap/Service.php new file mode 100644 index 0000000..acf3cb9 --- /dev/null +++ b/lib/Pear/Net/Nmap/Service.php @@ -0,0 +1,111 @@ + + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_Nmap + */ + +require_once 'Net/Nmap/Exception.php'; + +/** + * Service object + * + * @property string $protocol The protocol type of the service. + * @property int $port The port number where the service is running on. + * @property string $name The name of the service. + * @property string $product The product information of the service. + * @property string $version The version of the product running as service. + * @property string $extrainfo The additional information about the product + * running as service. + * + * @category Net + * @package Net_Nmap + * @author Luca Corbo + * @copyright 2008 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://www.ortro.net + */ +class Net_Nmap_Service +{ + /** + * The list of properties managed by __set and __get methods + * + * @var array $_properties + * @access private + */ + private $_properties = array('product' => null, + 'protocol' => null, + 'port' => null, + 'name' => null, + 'version' => null, + 'extrainfo' => null); + + /** + * Overloading of the __get method + * + * @param string $key The name of the variable that should be retrieved + * + * @throws Net_Nmap_Exception If trying to get an undefined properties. + * @return mixed The value of the object on success + * @access private + */ + private function __get($key) + { + if (key_exists($key, $this->_properties)) { + return $this->_properties[$key]; + } else { + throw new Net_Nmap_Exception('Trying to get an undefined properties "' . + $key . + '" for the object ' . + __CLASS__); + } + } + + /** + * Overloading of the __set method + * + * @param string $key The name of the properties that should be set + * @param mixed $value parameter specifies the value that the object + * should set the $key + * + * @throws Net_Nmap_Exception If trying to set an undefined properties. + * @return mixed True on success + * @access private + */ + private function __set($key, $value) + { + if (key_exists($key, $this->_properties)) { + $this->_properties[$key] = $value; + return true; + } else { + throw new Net_Nmap_Exception('Trying to set an undefined properties "' . + $key . + '" for the object ' . + __CLASS__); + } + } +} +?> \ No newline at end of file diff --git a/lib/Pear/OS/Guess.php b/lib/Pear/OS/Guess.php new file mode 100644 index 0000000..a378d77 --- /dev/null +++ b/lib/Pear/OS/Guess.php @@ -0,0 +1,344 @@ + + * @author Gregory Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Guess.php,v 1.26 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since PEAR 0.1 + */ + +// {{{ uname examples + +// php_uname() without args returns the same as 'uname -a', or a PHP-custom +// string for Windows. +// PHP versions prior to 4.3 return the uname of the host where PHP was built, +// as of 4.3 it returns the uname of the host running the PHP code. +// +// PC RedHat Linux 7.1: +// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown +// +// PC Debian Potato: +// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown +// +// PC FreeBSD 3.3: +// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.3: +// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5 w/uname from GNU shellutils: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown +// +// HP 9000/712 HP-UX 10: +// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license +// +// HP 9000/712 HP-UX 10 w/uname from GNU shellutils: +// HP-UX host B.10.10 A 9000/712 unknown +// +// IBM RS6000/550 AIX 4.3: +// AIX host 3 4 000003531C00 +// +// AIX 4.3 w/uname from GNU shellutils: +// AIX host 3 4 000003531C00 unknown +// +// SGI Onyx IRIX 6.5 w/uname from GNU shellutils: +// IRIX64 host 6.5 01091820 IP19 mips +// +// SGI Onyx IRIX 6.5: +// IRIX64 host 6.5 01091820 IP19 +// +// SparcStation 20 Solaris 8 w/uname from GNU shellutils: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc +// +// SparcStation 20 Solaris 8: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 +// +// Mac OS X (Darwin) +// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh +// +// Mac OS X early versions +// + +// }}} + +/* TODO: + * - define endianness, to allow matchSignature("bigend") etc. + */ + +/** + * Retrieves information about the current operating system + * + * This class uses php_uname() to grok information about the current OS + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Gregory Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.1 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class OS_Guess +{ + var $sysname; + var $nodename; + var $cpu; + var $release; + var $extra; + + function OS_Guess($uname = null) + { + list($this->sysname, + $this->release, + $this->cpu, + $this->extra, + $this->nodename) = $this->parseSignature($uname); + } + + function parseSignature($uname = null) + { + static $sysmap = array( + 'HP-UX' => 'hpux', + 'IRIX64' => 'irix', + ); + static $cpumap = array( + 'i586' => 'i386', + 'i686' => 'i386', + 'ppc' => 'powerpc', + ); + if ($uname === null) { + $uname = php_uname(); + } + $parts = split('[[:space:]]+', trim($uname)); + $n = count($parts); + + $release = $machine = $cpu = ''; + $sysname = $parts[0]; + $nodename = $parts[1]; + $cpu = $parts[$n-1]; + $extra = ''; + if ($cpu == 'unknown') { + $cpu = $parts[$n-2]; + } + + switch ($sysname) { + case 'AIX' : + $release = "$parts[3].$parts[2]"; + break; + case 'Windows' : + switch ($parts[1]) { + case '95/98': + $release = '9x'; + break; + default: + $release = $parts[1]; + break; + } + $cpu = 'i386'; + break; + case 'Linux' : + $extra = $this->_detectGlibcVersion(); + // use only the first two digits from the kernel version + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + case 'Mac' : + $sysname = 'darwin'; + $nodename = $parts[2]; + $release = $parts[3]; + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + break; + case 'Darwin' : + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + default: + $release = ereg_replace('-.*', '', $parts[2]); + break; + } + + + if (isset($sysmap[$sysname])) { + $sysname = $sysmap[$sysname]; + } else { + $sysname = strtolower($sysname); + } + if (isset($cpumap[$cpu])) { + $cpu = $cpumap[$cpu]; + } + return array($sysname, $release, $cpu, $extra, $nodename); + } + + function _detectGlibcVersion() + { + static $glibc = false; + if ($glibc !== false) { + return $glibc; // no need to run this multiple times + } + $major = $minor = 0; + include_once "System.php"; + // Use glibc's header file to + // get major and minor version number: + if (@file_exists('/usr/include/features.h') && + @is_readable('/usr/include/features.h')) { + if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { + $features_file = fopen('/usr/include/features.h', 'rb'); + while (!feof($features_file)) { + $line = fgets($features_file, 8192); + if (!$line || (strpos($line, '#define') === false)) { + continue; + } + if (strpos($line, '__GLIBC__')) { + // major version number #define __GLIBC__ version + $line = preg_split('/\s+/', $line); + $glibc_major = trim($line[2]); + if (isset($glibc_minor)) { + break; + } + continue; + } + if (strpos($line, '__GLIBC_MINOR__')) { + // got the minor version number + // #define __GLIBC_MINOR__ version + $line = preg_split('/\s+/', $line); + $glibc_minor = trim($line[2]); + if (isset($glibc_major)) { + break; + } + continue; + } + } + fclose($features_file); + if (!isset($glibc_major) || !isset($glibc_minor)) { + return $glibc = ''; + } + return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ; + } // no cpp + $tmpfile = System::mktemp("glibctest"); + $fp = fopen($tmpfile, "w"); + fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); + fclose($fp); + $cpp = popen("/usr/bin/cpp $tmpfile", "r"); + while ($line = fgets($cpp, 1024)) { + if ($line{0} == '#' || trim($line) == '') { + continue; + } + if (list($major, $minor) = explode(' ', trim($line))) { + break; + } + } + pclose($cpp); + unlink($tmpfile); + } // features.h + if (!($major && $minor) && @is_link('/lib/libc.so.6')) { + // Let's try reading the libc.so.6 symlink + if (ereg('^libc-(.*)\.so$', basename(readlink('/lib/libc.so.6')), $matches)) { + list($major, $minor) = explode('.', $matches[1]); + } + } + if (!($major && $minor)) { + return $glibc = ''; + } + return $glibc = "glibc{$major}.{$minor}"; + } + + function getSignature() + { + if (empty($this->extra)) { + return "{$this->sysname}-{$this->release}-{$this->cpu}"; + } + return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; + } + + function getSysname() + { + return $this->sysname; + } + + function getNodename() + { + return $this->nodename; + } + + function getCpu() + { + return $this->cpu; + } + + function getRelease() + { + return $this->release; + } + + function getExtra() + { + return $this->extra; + } + + function matchSignature($match) + { + if (is_array($match)) { + $fragments = $match; + } else { + $fragments = explode('-', $match); + } + $n = count($fragments); + $matches = 0; + if ($n > 0) { + $matches += $this->_matchFragment($fragments[0], $this->sysname); + } + if ($n > 1) { + $matches += $this->_matchFragment($fragments[1], $this->release); + } + if ($n > 2) { + $matches += $this->_matchFragment($fragments[2], $this->cpu); + } + if ($n > 3) { + $matches += $this->_matchFragment($fragments[3], $this->extra); + } + return ($matches == $n); + } + + function _matchFragment($fragment, $value) + { + if (strcspn($fragment, '*?') < strlen($fragment)) { + $reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$'; + return eregi($reg, $value); + } + return ($fragment == '*' || !strcasecmp($fragment, $value)); + } + +} +/* + * Local Variables: + * indent-tabs-mode: nil + * c-basic-offset: 4 + * End: + */ +?> diff --git a/lib/Pear/PEAR.php b/lib/Pear/PEAR.php new file mode 100644 index 0000000..6c5a114 --- /dev/null +++ b/lib/Pear/PEAR.php @@ -0,0 +1,1118 @@ + + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: PEAR.php,v 1.104 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/**#@+ + * ERROR constants + */ +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); +/** + * WARNING: obsolete + * @deprecated + */ +define('PEAR_ERROR_EXCEPTION', 32); +/**#@-*/ +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +// instant backwards compatibility +if (!defined('PATH_SEPARATOR')) { + if (OS_WINDOWS) { + define('PATH_SEPARATOR', ';'); + } else { + define('PATH_SEPARATOR', ':'); + } +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +@ini_set('track_errors', true); + +/** + * Base class for other PEAR classes. Provides rudimentary + * emulation of destructors. + * + * If you want a destructor in your class, inherit PEAR and make a + * destructor method called _yourclassname (same name as the + * constructor, but with a "_" prefix). Also, in your constructor you + * have to call the PEAR constructor: $this->PEAR();. + * The destructor method will be called without parameters. Note that + * at in some SAPI implementations (such as Apache), any output during + * the request shutdown (in which destructors are called) seems to be + * discarded. If you need to get any debug information from your + * destructor, use error_log(), syslog() or something similar. + * + * IMPORTANT! To use the emulated destructors you need to create the + * objects by reference: $obj =& new PEAR_child; + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Greg Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.1 + * @link http://pear.php.net/package/PEAR + * @see PEAR_Error + * @since Class available since PHP 4.0.2 + * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear + */ +class PEAR +{ + // {{{ properties + + /** + * Whether to enable internal debug messages. + * + * @var bool + * @access private + */ + var $_debug = false; + + /** + * Default error mode for this object. + * + * @var int + * @access private + */ + var $_default_error_mode = null; + + /** + * Default error options used for this object when error mode + * is PEAR_ERROR_TRIGGER. + * + * @var int + * @access private + */ + var $_default_error_options = null; + + /** + * Default error handler (callback) for this object, if error mode is + * PEAR_ERROR_CALLBACK. + * + * @var string + * @access private + */ + var $_default_error_handler = ''; + + /** + * Which class to use for error objects. + * + * @var string + * @access private + */ + var $_error_class = 'PEAR_Error'; + + /** + * An array of expected errors. + * + * @var array + * @access private + */ + var $_expected_errors = array(); + + // }}} + + // {{{ constructor + + /** + * Constructor. Registers this object in + * $_PEAR_destructor_object_list for destructor emulation if a + * destructor object exists. + * + * @param string $error_class (optional) which class to use for + * error objects, defaults to PEAR_Error. + * @access public + * @return void + */ + function PEAR($error_class = null) + { + $classname = strtolower(get_class($this)); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + if ($error_class !== null) { + $this->_error_class = $error_class; + } + while ($classname && strcasecmp($classname, "pear")) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + // }}} + // {{{ destructor + + /** + * Destructor (the emulated type of...). Does nothing right now, + * but is included for forward compatibility, so subclass + * destructors should always call it. + * + * See the note in the class desciption about output from + * destructors. + * + * @access public + * @return void + */ + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); + } + } + + // }}} + // {{{ getStaticProperty() + + /** + * If you have a class that's mostly/entirely static, and you need static + * properties, you can use this method to simulate them. Eg. in your method(s) + * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); + * You MUST use a reference, or they will not persist! + * + * @access public + * @param string $class The calling classname, to prevent clashes + * @param string $var The variable to retrieve. + * @return mixed A reference to the variable. If not set it will be + * auto initialised to NULL. + */ + function &getStaticProperty($class, $var) + { + static $properties; + if (!isset($properties[$class])) { + $properties[$class] = array(); + } + if (!array_key_exists($var, $properties[$class])) { + $properties[$class][$var] = null; + } + return $properties[$class][$var]; + } + + // }}} + // {{{ registerShutdownFunc() + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @param mixed $func The function name (or array of class/method) to call + * @param mixed $args The arguments to pass to the function + * @return void + */ + function registerShutdownFunc($func, $args = array()) + { + // if we are called statically, there is a potential + // that no shutdown func is registered. Bug #6445 + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + // }}} + // {{{ isError() + + /** + * Tell whether a value is a PEAR error. + * + * @param mixed $data the value to test + * @param int $code if $data is an error object, return true + * only if $code is a string and + * $obj->getMessage() == $code or + * $code is an integer and $obj->getCode() == $code + * @access public + * @return bool true if parameter is an error + */ + function isError($data, $code = null) + { + if (is_a($data, 'PEAR_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } else { + return $data->getCode() == $code; + } + } + return false; + } + + // }}} + // {{{ setErrorHandling() + + /** + * Sets how errors generated by this object should be handled. + * Can be invoked both in objects and statically. If called + * statically, setErrorHandling sets the default behaviour for all + * PEAR objects. If called in an object, setErrorHandling sets + * the default behaviour for that object. + * + * @param int $mode + * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. + * + * @param mixed $options + * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one + * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * + * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected + * to be the callback function or method. A callback + * function is a string with the name of the function, a + * callback method is an array of two elements: the element + * at index 0 is the object, and the element at index 1 is + * the name of the method to call in the object. + * + * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is + * a printf format string used when printing the error + * message. + * + * @access public + * @return void + * @see PEAR_ERROR_RETURN + * @see PEAR_ERROR_PRINT + * @see PEAR_ERROR_TRIGGER + * @see PEAR_ERROR_DIE + * @see PEAR_ERROR_CALLBACK + * @see PEAR_ERROR_EXCEPTION + * + * @since PHP 4.0.5 + */ + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + // }}} + // {{{ expectError() + + /** + * This method is used to tell which errors you expect to get. + * Expected errors are always returned with error mode + * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, + * and this method pushes a new element onto it. The list of + * expected errors are in effect until they are popped off the + * stack with the popExpect() method. + * + * Note that this method can not be called statically + * + * @param mixed $code a single error code or an array of error codes to expect + * + * @return int the new depth of the "expected errors" stack + * @access public + */ + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return sizeof($this->_expected_errors); + } + + // }}} + // {{{ popExpect() + + /** + * This method pops one element off the expected error codes + * stack. + * + * @return array the list of error codes that were popped + */ + function popExpect() + { + return array_pop($this->_expected_errors); + } + + // }}} + // {{{ _checkDelExpect() + + /** + * This method checks unsets an error code if available + * + * @param mixed error code + * @return bool true if the error code was unset, false otherwise + * @access private + * @since PHP 4.3.0 + */ + function _checkDelExpect($error_code) + { + $deleted = false; + + foreach ($this->_expected_errors AS $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + // clean up empty arrays + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + return $deleted; + } + + // }}} + // {{{ delExpect() + + /** + * This method deletes all occurences of the specified element from + * the expected error codes stack. + * + * @param mixed $error_code error code that should be deleted + * @return mixed list of error codes that were deleted or error + * @access public + * @since PHP 4.3.0 + */ + function delExpect($error_code) + { + $deleted = false; + + if ((is_array($error_code) && (0 != count($error_code)))) { + // $error_code is a non-empty array here; + // we walk through it trying to unset all + // values + foreach($error_code as $key => $error) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = false; + } + } + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + // $error_code comes alone, trying to unset it + if ($this->_checkDelExpect($error_code)) { + return true; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + // }}} + // {{{ raiseError() + + /** + * This method is a wrapper that returns an instance of the + * configured error class with this object's default error + * handling applied. If the $mode and $options parameters are not + * specified, the object's defaults are used. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. + * + * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter + * specifies the PHP-internal error level (one of + * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * If $mode is PEAR_ERROR_CALLBACK, this + * parameter specifies the callback function or + * method. In other error modes this parameter + * is ignored. + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @param string $error_class The returned error object will be + * instantiated from this class, if specified. + * + * @param bool $skipmsg If true, raiseError will only pass error codes, + * the error message parameter will be dropped. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function &raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message->error_message_prefix = ''; + $message = $message->getMessage(); + } + + if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp))) { + $mode = PEAR_ERROR_RETURN; + } + } + // No mode given, try global ones + if ($mode === null) { + // Class error handler + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + // Global error handler + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if (intval(PHP_VERSION) < 5) { + // little non-eval hack to fix bug #12147 + include 'PEAR/FixPHP5PEARWarnings.php'; + return $a; + } + if ($skipmsg) { + $a = new $ec($code, $mode, $options, $userinfo); + } else { + $a = new $ec($message, $code, $mode, $options, $userinfo); + } + return $a; + } + + // }}} + // {{{ throwError() + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param string $message + * + */ + function &throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $a = &$this->raiseError($message, $code, null, null, $userinfo); + return $a; + } else { + $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + return $a; + } + } + + // }}} + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + // class/object method callback + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + + // {{{ pushErrorHandling() + + /** + * Push a new error handler on top of the error handler options stack. With this + * you can easily override the actual error handler for some code and restore + * it later with popErrorHandling. + * + * @param mixed $mode (same as setErrorHandling) + * @param mixed $options (same as setErrorHandling) + * + * @return bool Always true + * + * @see PEAR::setErrorHandling + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + // }}} + // {{{ popErrorHandling() + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + // }}} + // {{{ loadExtension() + + /** + * OS independant PHP extension load. Remember to take care + * on the correct extension name for case sensitive OSes. + * + * @param string $ext The extension name + * @return bool Success or not on the dl() call + */ + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + // if either returns true dl() will produce a FATAL error, stop that + if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) { + return false; + } + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } + return true; + } + + // }}} +} + +// {{{ _PEAR_call_destructors() + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + if (PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + // Empty the object list to ensure that destructors are + // not called more than once. + $_PEAR_destructor_object_list = array(); + } + + // Now call the shutdown functions + if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +// }}} +/** + * Standard PEAR error class for PHP 4 + * + * This class is supserseded by {@link PEAR_Exception} in PHP 5 + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Gregory Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.1 + * @link http://pear.php.net/manual/en/core.pear.pear-error.php + * @see PEAR::raiseError(), PEAR::throwError() + * @since Class available since PHP 4.0.2 + */ +class PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + // }}} + // {{{ constructor + + /** + * PEAR_Error constructor + * + * @param string $message message + * + * @param int $code (optional) error code + * + * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, + * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION + * + * @param mixed $options (optional) error level, _OR_ in the case of + * PEAR_ERROR_CALLBACK, the callback function or object/method + * tuple. + * + * @param string $userinfo (optional) additional user/debug info + * + * @access public + * + */ + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { + unset($this->backtrace[0]['object']); + } + } + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + $this->level = $options; + $this->callback = null; + } + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + printf($format, $this->getMessage()); + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_callable($this->callback)) { + call_user_func($this->callback, $this); + } + } + if ($this->mode & PEAR_ERROR_EXCEPTION) { + trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);throw($e);'); + } + } + + // }}} + // {{{ getMode() + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() { + return $this->mode; + } + + // }}} + // {{{ getCallback() + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() { + return $this->callback; + } + + // }}} + // {{{ getMessage() + + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + + // }}} + // {{{ getCode() + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + // }}} + // {{{ getType() + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + // }}} + // {{{ getUserInfo() + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + // }}} + // {{{ getDebugInfo() + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + // }}} + // {{{ getBacktrace() + + /** + * Get the call backtrace from where the error was generated. + * Supported with PHP 4.3.0 or newer. + * + * @param int $frame (optional) what frame to fetch + * @return array Backtrace, or NULL if not available. + * @access public + */ + function getBacktrace($frame = null) + { + if (defined('PEAR_IGNORE_BACKTRACE')) { + return null; + } + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + // }}} + // {{{ addUserInfo() + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + // }}} + // {{{ toString() + function __toString() + { + return $this->getMessage(); + } + // }}} + // {{{ toString() + + /** + * Make a string representation of this object. + * + * @return string a string with an object summary + * @access public + */ + function toString() { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } + + // }}} +} + +/* + * Local Variables: + * mode: php + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ +?> diff --git a/lib/Pear/PEAR/Exception.php b/lib/Pear/PEAR/Exception.php new file mode 100644 index 0000000..71603a7 --- /dev/null +++ b/lib/Pear/PEAR/Exception.php @@ -0,0 +1,397 @@ + + * @author Hans Lellelid + * @author Bertrand Mansion + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Exception.php,v 1.29 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.3.3 + */ + + +/** + * Base PEAR_Exception Class + * + * 1) Features: + * + * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) + * - Definable triggers, shot when exceptions occur + * - Pretty and informative error messages + * - Added more context info available (like class, method or cause) + * - cause can be a PEAR_Exception or an array of mixed + * PEAR_Exceptions/PEAR_ErrorStack warnings + * - callbacks for specific exception classes and their children + * + * 2) Ideas: + * + * - Maybe a way to define a 'template' for the output + * + * 3) Inherited properties from PHP Exception Class: + * + * protected $message + * protected $code + * protected $line + * protected $file + * private $trace + * + * 4) Inherited methods from PHP Exception Class: + * + * __clone + * __construct + * getMessage + * getCode + * getFile + * getLine + * getTraceSafe + * getTraceSafeAsString + * __toString + * + * 5) Usage example + * + * + * require_once 'PEAR/Exception.php'; + * + * class Test { + * function foo() { + * throw new PEAR_Exception('Error Message', ERROR_CODE); + * } + * } + * + * function myLogger($pear_exception) { + * echo $pear_exception->getMessage(); + * } + * // each time a exception is thrown the 'myLogger' will be called + * // (its use is completely optional) + * PEAR_Exception::addObserver('myLogger'); + * $test = new Test; + * try { + * $test->foo(); + * } catch (PEAR_Exception $e) { + * print $e; + * } + * + * + * @category pear + * @package PEAR + * @author Tomas V.V.Cox + * @author Hans Lellelid + * @author Bertrand Mansion + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.1 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.3.3 + * + */ +class PEAR_Exception extends Exception +{ + const OBSERVER_PRINT = -2; + const OBSERVER_TRIGGER = -4; + const OBSERVER_DIE = -8; + protected $cause; + private static $_observers = array(); + private static $_uniqueid = 0; + private $_trace; + + /** + * Supported signatures: + * - PEAR_Exception(string $message); + * - PEAR_Exception(string $message, int $code); + * - PEAR_Exception(string $message, Exception $cause); + * - PEAR_Exception(string $message, Exception $cause, int $code); + * - PEAR_Exception(string $message, PEAR_Error $cause); + * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); + * - PEAR_Exception(string $message, array $causes); + * - PEAR_Exception(string $message, array $causes, int $code); + * @param string exception message + * @param int|Exception|PEAR_Error|array|null exception cause + * @param int|null exception code or null + */ + public function __construct($message, $p2 = null, $p3 = null) + { + if (is_int($p2)) { + $code = $p2; + $this->cause = null; + } elseif (is_object($p2) || is_array($p2)) { + // using is_object allows both Exception and PEAR_Error + if (is_object($p2) && !($p2 instanceof Exception)) { + if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { + throw new PEAR_Exception('exception cause must be Exception, ' . + 'array, or PEAR_Error'); + } + } + $code = $p3; + if (is_array($p2) && isset($p2['message'])) { + // fix potential problem of passing in a single warning + $p2 = array($p2); + } + $this->cause = $p2; + } else { + $code = null; + $this->cause = null; + } + parent::__construct($message, $code); + $this->signal(); + } + + /** + * @param mixed $callback - A valid php callback, see php func is_callable() + * - A PEAR_Exception::OBSERVER_* constant + * - An array(const PEAR_Exception::OBSERVER_*, + * mixed $options) + * @param string $label The name of the observer. Use this if you want + * to remove it later with removeObserver() + */ + public static function addObserver($callback, $label = 'default') + { + self::$_observers[$label] = $callback; + } + + public static function removeObserver($label = 'default') + { + unset(self::$_observers[$label]); + } + + /** + * @return int unique identifier for an observer + */ + public static function getUniqueId() + { + return self::$_uniqueid++; + } + + private function signal() + { + foreach (self::$_observers as $func) { + if (is_callable($func)) { + call_user_func($func, $this); + continue; + } + settype($func, 'array'); + switch ($func[0]) { + case self::OBSERVER_PRINT : + $f = (isset($func[1])) ? $func[1] : '%s'; + printf($f, $this->getMessage()); + break; + case self::OBSERVER_TRIGGER : + $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; + trigger_error($this->getMessage(), $f); + break; + case self::OBSERVER_DIE : + $f = (isset($func[1])) ? $func[1] : '%s'; + die(printf($f, $this->getMessage())); + break; + default: + trigger_error('invalid observer type', E_USER_WARNING); + } + } + } + + /** + * Return specific error information that can be used for more detailed + * error messages or translation. + * + * This method may be overridden in child exception classes in order + * to add functionality not present in PEAR_Exception and is a placeholder + * to define API + * + * The returned array must be an associative array of parameter => value like so: + *
+     * array('name' => $name, 'context' => array(...))
+     * 
+ * @return array + */ + public function getErrorData() + { + return array(); + } + + /** + * Returns the exception that caused this exception to be thrown + * @access public + * @return Exception|array The context of the exception + */ + public function getCause() + { + return $this->cause; + } + + /** + * Function must be public to call on caused exceptions + * @param array + */ + public function getCauseMessage(&$causes) + { + $trace = $this->getTraceSafe(); + $cause = array('class' => get_class($this), + 'message' => $this->message, + 'file' => 'unknown', + 'line' => 'unknown'); + if (isset($trace[0])) { + if (isset($trace[0]['file'])) { + $cause['file'] = $trace[0]['file']; + $cause['line'] = $trace[0]['line']; + } + } + $causes[] = $cause; + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } elseif ($this->cause instanceof Exception) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => $this->cause->getFile(), + 'line' => $this->cause->getLine()); + } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } elseif ($cause instanceof Exception) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => $cause->getFile(), + 'line' => $cause->getLine()); + } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($cause) && isset($cause['message'])) { + // PEAR_ErrorStack warning + $causes[] = array( + 'class' => $cause['package'], + 'message' => $cause['message'], + 'file' => isset($cause['context']['file']) ? + $cause['context']['file'] : + 'unknown', + 'line' => isset($cause['context']['line']) ? + $cause['context']['line'] : + 'unknown', + ); + } + } + } + } + + public function getTraceSafe() + { + if (!isset($this->_trace)) { + $this->_trace = $this->getTrace(); + if (empty($this->_trace)) { + $backtrace = debug_backtrace(); + $this->_trace = array($backtrace[count($backtrace)-1]); + } + } + return $this->_trace; + } + + public function getErrorClass() + { + $trace = $this->getTraceSafe(); + return $trace[0]['class']; + } + + public function getErrorMethod() + { + $trace = $this->getTraceSafe(); + return $trace[0]['function']; + } + + public function __toString() + { + if (isset($_SERVER['REQUEST_URI'])) { + return $this->toHtml(); + } + return $this->toText(); + } + + public function toHtml() + { + $trace = $this->getTraceSafe(); + $causes = array(); + $this->getCauseMessage($causes); + $html = '' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '\n"; + } + $html .= '' . "\n" + . '' + . '' + . '' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '' + . '' + . '' . "\n"; + } + $html .= '' + . '' + . '' . "\n" + . '
' + . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' + . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' + . 'on line ' . $cause['line'] . '' + . "
Exception trace
#FunctionLocation
' . $k . ''; + if (!empty($v['class'])) { + $html .= $v['class'] . $v['type']; + } + $html .= $v['function']; + $args = array(); + if (!empty($v['args'])) { + foreach ($v['args'] as $arg) { + if (is_null($arg)) $args[] = 'null'; + elseif (is_array($arg)) $args[] = 'Array'; + elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; + elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; + elseif (is_int($arg) || is_double($arg)) $args[] = $arg; + else { + $arg = (string)$arg; + $str = htmlspecialchars(substr($arg, 0, 16)); + if (strlen($arg) > 16) $str .= '…'; + $args[] = "'" . $str . "'"; + } + } + } + $html .= '(' . implode(', ',$args) . ')' + . '' . (isset($v['file']) ? $v['file'] : 'unknown') + . ':' . (isset($v['line']) ? $v['line'] : 'unknown') + . '
' . ($k+1) . '{main} 
'; + return $html; + } + + public function toText() + { + $causes = array(); + $this->getCauseMessage($causes); + $causeMsg = ''; + foreach ($causes as $i => $cause) { + $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' + . $cause['message'] . ' in ' . $cause['file'] + . ' on line ' . $cause['line'] . "\n"; + } + return $causeMsg . $this->getTraceAsString(); + } +} + +?> \ No newline at end of file diff --git a/lib/Pear/System.php b/lib/Pear/System.php new file mode 100644 index 0000000..7695007 --- /dev/null +++ b/lib/Pear/System.php @@ -0,0 +1,606 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: System.php,v 1.62 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR.php'; +require_once 'Console/Getopt.php'; + +$GLOBALS['_System_temp_files'] = array(); + +/** +* System offers cross plattform compatible system functions +* +* Static functions for different operations. Should work under +* Unix and Windows. The names and usage has been taken from its respectively +* GNU commands. The functions will return (bool) false on error and will +* trigger the error with the PHP trigger_error() function (you can silence +* the error by prefixing a '@' sign after the function call, but this +* is not recommended practice. Instead use an error handler with +* {@link set_error_handler()}). +* +* Documentation on this class you can find in: +* http://pear.php.net/manual/ +* +* Example usage: +* if (!@System::rm('-r file1 dir1')) { +* print "could not delete file1 or dir1"; +* } +* +* In case you need to to pass file names with spaces, +* pass the params as an array: +* +* System::rm(array('-r', $file1, $dir1)); +* +* @category pear +* @package System +* @author Tomas V.V. Cox +* @copyright 1997-2006 The PHP Group +* @license http://www.php.net/license/3_0.txt PHP License 3.0 +* @version Release: 1.7.1 +* @link http://pear.php.net/package/PEAR +* @since Class available since Release 0.1 +* @static +*/ +class System +{ + /** + * returns the commandline arguments of a function + * + * @param string $argv the commandline + * @param string $short_options the allowed option short-tags + * @param string $long_options the allowed option long-tags + * @return array the given options and there values + * @static + * @access private + */ + function _parseArgs($argv, $short_options, $long_options = null) + { + if (!is_array($argv) && $argv !== null) { + $argv = preg_split('/\s+/', $argv, -1, PREG_SPLIT_NO_EMPTY); + } + return Console_Getopt::getopt2($argv, $short_options); + } + + /** + * Output errors with PHP trigger_error(). You can silence the errors + * with prefixing a "@" sign to the function call: @System::mkdir(..); + * + * @param mixed $error a PEAR error or a string with the error message + * @return bool false + * @static + * @access private + */ + function raiseError($error) + { + if (PEAR::isError($error)) { + $error = $error->getMessage(); + } + trigger_error($error, E_USER_WARNING); + return false; + } + + /** + * Creates a nested array representing the structure of a directory + * + * System::_dirToStruct('dir1', 0) => + * Array + * ( + * [dirs] => Array + * ( + * [0] => dir1 + * ) + * + * [files] => Array + * ( + * [0] => dir1/file2 + * [1] => dir1/file3 + * ) + * ) + * @param string $sPath Name of the directory + * @param integer $maxinst max. deep of the lookup + * @param integer $aktinst starting deep of the lookup + * @param bool $silent if true, do not emit errors. + * @return array the structure of the dir + * @static + * @access private + */ + + function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) + { + $struct = array('dirs' => array(), 'files' => array()); + if (($dir = @opendir($sPath)) === false) { + if (!$silent) { + System::raiseError("Could not open dir $sPath"); + } + return $struct; // XXX could not open error + } + $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? + $list = array(); + while (false !== ($file = readdir($dir))) { + if ($file != '.' && $file != '..') { + $list[] = $file; + } + } + closedir($dir); + sort($list); + if ($aktinst < $maxinst || $maxinst == 0) { + foreach ($list as $val) { + $path = $sPath . DIRECTORY_SEPARATOR . $val; + if (is_dir($path) && !is_link($path)) { + $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $path; + } + } + } + return $struct; + } + + /** + * Creates a nested array representing the structure of a directory and files + * + * @param array $files Array listing files and dirs + * @return array + * @static + * @see System::_dirToStruct() + */ + function _multipleToStruct($files) + { + $struct = array('dirs' => array(), 'files' => array()); + settype($files, 'array'); + foreach ($files as $file) { + if (is_dir($file) && !is_link($file)) { + $tmp = System::_dirToStruct($file, 0); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $file; + } + } + return $struct; + } + + /** + * The rm command for removing files. + * Supports multiple files and dirs and also recursive deletes + * + * @param string $args the arguments for rm + * @return mixed PEAR_Error or true for success + * @static + * @access public + */ + function rm($args) + { + $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach ($opts[0] as $opt) { + if ($opt[0] == 'r') { + $do_recursive = true; + } + } + $ret = true; + if (isset($do_recursive)) { + $struct = System::_multipleToStruct($opts[1]); + foreach ($struct['files'] as $file) { + if (!@unlink($file)) { + $ret = false; + } + } + foreach ($struct['dirs'] as $dir) { + if (!@rmdir($dir)) { + $ret = false; + } + } + } else { + foreach ($opts[1] as $file) { + $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; + if (!@$delete($file)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Make directories. + * + * The -p option will create parent directories + * @param string $args the name of the director(y|ies) to create + * @return bool True for success + * @static + * @access public + */ + function mkDir($args) + { + $opts = System::_parseArgs($args, 'pm:'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + $mode = 0777; // default mode + foreach ($opts[0] as $opt) { + if ($opt[0] == 'p') { + $create_parents = true; + } elseif ($opt[0] == 'm') { + // if the mode is clearly an octal number (starts with 0) + // convert it to decimal + if (strlen($opt[1]) && $opt[1]{0} == '0') { + $opt[1] = octdec($opt[1]); + } else { + // convert to int + $opt[1] += 0; + } + $mode = $opt[1]; + } + } + $ret = true; + if (isset($create_parents)) { + foreach ($opts[1] as $dir) { + $dirstack = array(); + while ((!file_exists($dir) || !is_dir($dir)) && + $dir != DIRECTORY_SEPARATOR) { + array_unshift($dirstack, $dir); + $dir = dirname($dir); + } + while ($newdir = array_shift($dirstack)) { + if (!is_writeable(dirname($newdir))) { + $ret = false; + break; + } + if (!mkdir($newdir, $mode)) { + $ret = false; + } + } + } + } else { + foreach($opts[1] as $dir) { + if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Concatenate files + * + * Usage: + * 1) $var = System::cat('sample.txt test.txt'); + * 2) System::cat('sample.txt test.txt > final.txt'); + * 3) System::cat('sample.txt test.txt >> final.txt'); + * + * Note: as the class use fopen, urls should work also (test that) + * + * @param string $args the arguments + * @return boolean true on success + * @static + * @access public + */ + function &cat($args) + { + $ret = null; + $files = array(); + if (!is_array($args)) { + $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); + } + + $count_args = count($args); + for ($i = 0; $i < $count_args; $i++) { + if ($args[$i] == '>') { + $mode = 'wb'; + $outputfile = $args[$i+1]; + break; + } elseif ($args[$i] == '>>') { + $mode = 'ab+'; + $outputfile = $args[$i+1]; + break; + } else { + $files[] = $args[$i]; + } + } + $outputfd = false; + if (isset($mode)) { + if (!$outputfd = fopen($outputfile, $mode)) { + $err = System::raiseError("Could not open $outputfile"); + return $err; + } + $ret = true; + } + foreach ($files as $file) { + if (!$fd = fopen($file, 'r')) { + System::raiseError("Could not open $file"); + continue; + } + while ($cont = fread($fd, 2048)) { + if (is_resource($outputfd)) { + fwrite($outputfd, $cont); + } else { + $ret .= $cont; + } + } + fclose($fd); + } + if (is_resource($outputfd)) { + fclose($outputfd); + } + return $ret; + } + + /** + * Creates temporary files or directories. This function will remove + * the created files when the scripts finish its execution. + * + * Usage: + * 1) $tempfile = System::mktemp("prefix"); + * 2) $tempdir = System::mktemp("-d prefix"); + * 3) $tempfile = System::mktemp(); + * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); + * + * prefix -> The string that will be prepended to the temp name + * (defaults to "tmp"). + * -d -> A temporary dir will be created instead of a file. + * -t -> The target dir where the temporary (file|dir) will be created. If + * this param is missing by default the env vars TMP on Windows or + * TMPDIR in Unix will be used. If these vars are also missing + * c:\windows\temp or /tmp will be used. + * + * @param string $args The arguments + * @return mixed the full path of the created (file|dir) or false + * @see System::tmpdir() + * @static + * @access public + */ + function mktemp($args = null) + { + static $first_time = true; + $opts = System::_parseArgs($args, 't:d'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach ($opts[0] as $opt) { + if ($opt[0] == 'd') { + $tmp_is_dir = true; + } elseif ($opt[0] == 't') { + $tmpdir = $opt[1]; + } + } + $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; + if (!isset($tmpdir)) { + $tmpdir = System::tmpdir(); + } + if (!System::mkDir(array('-p', $tmpdir))) { + return false; + } + $tmp = tempnam($tmpdir, $prefix); + if (isset($tmp_is_dir)) { + unlink($tmp); // be careful possible race condition here + if (!mkdir($tmp, 0700)) { + return System::raiseError("Unable to create temporary directory $tmpdir"); + } + } + $GLOBALS['_System_temp_files'][] = $tmp; + if ($first_time) { + PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); + $first_time = false; + } + return $tmp; + } + + /** + * Remove temporary files created my mkTemp. This function is executed + * at script shutdown time + * + * @static + * @access private + */ + function _removeTmpFiles() + { + if (count($GLOBALS['_System_temp_files'])) { + $delete = $GLOBALS['_System_temp_files']; + array_unshift($delete, '-r'); + System::rm($delete); + $GLOBALS['_System_temp_files'] = array(); + } + } + + /** + * Get the path of the temporal directory set in the system + * by looking in its environments variables. + * Note: php.ini-recommended removes the "E" from the variables_order setting, + * making unavaible the $_ENV array, that s why we do tests with _ENV + * + * @static + * @return string The temporary directory on the system + */ + function tmpdir() + { + if (OS_WINDOWS) { + if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { + return $var; + } + if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { + return $var; + } + if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { + return $var; + } + if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { + return $var; + } + return getenv('SystemRoot') . '\temp'; + } + if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { + return $var; + } + return realpath('/tmp'); + } + + /** + * The "which" command (show the full path of a command) + * + * @param string $program The command to search for + * @param mixed $fallback Value to return if $program is not found + * + * @return mixed A string with the full path or false if not found + * @static + * @author Stig Bakken + */ + function which($program, $fallback = false) + { + // enforce API + if (!is_string($program) || '' == $program) { + return $fallback; + } + + // full path given + if (basename($program) != $program) { + $path_elements[] = dirname($program); + $program = basename($program); + } else { + // Honor safe mode + if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) { + $path = getenv('PATH'); + if (!$path) { + $path = getenv('Path'); // some OSes are just stupid enough to do this + } + } + $path_elements = explode(PATH_SEPARATOR, $path); + } + + if (OS_WINDOWS) { + $exe_suffixes = getenv('PATHEXT') + ? explode(PATH_SEPARATOR, getenv('PATHEXT')) + : array('.exe','.bat','.cmd','.com'); + // allow passing a command.exe param + if (strpos($program, '.') !== false) { + array_unshift($exe_suffixes, ''); + } + // is_executable() is not available on windows for PHP4 + $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file'; + } else { + $exe_suffixes = array(''); + $pear_is_executable = 'is_executable'; + } + + foreach ($exe_suffixes as $suff) { + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; + if (@$pear_is_executable($file)) { + return $file; + } + } + } + return $fallback; + } + + /** + * The "find" command + * + * Usage: + * + * System::find($dir); + * System::find("$dir -type d"); + * System::find("$dir -type f"); + * System::find("$dir -name *.php"); + * System::find("$dir -name *.php -name *.htm*"); + * System::find("$dir -maxdepth 1"); + * + * Params implmented: + * $dir -> Start the search at this directory + * -type d -> return only directories + * -type f -> return only files + * -maxdepth -> max depth of recursion + * -name -> search pattern (bash style). Multiple -name param allowed + * + * @param mixed Either array or string with the command line + * @return array Array of found files + * @static + * + */ + function find($args) + { + if (!is_array($args)) { + $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); + } + $dir = realpath(array_shift($args)); + if (!$dir) { + return array(); + } + $patterns = array(); + $depth = 0; + $do_files = $do_dirs = true; + $args_count = count($args); + for ($i = 0; $i < $args_count; $i++) { + switch ($args[$i]) { + case '-type': + if (in_array($args[$i+1], array('d', 'f'))) { + if ($args[$i+1] == 'd') { + $do_files = false; + } else { + $do_dirs = false; + } + } + $i++; + break; + case '-name': + $name = preg_quote($args[$i+1], '#'); + // our magic characters ? and * have just been escaped, + // so now we change the escaped versions to PCRE operators + $name = strtr($name, array('\?' => '.', '\*' => '.*')); + $patterns[] = '('.$name.')'; + $i++; + break; + case '-maxdepth': + $depth = $args[$i+1]; + break; + } + } + $path = System::_dirToStruct($dir, $depth, 0, true); + if ($do_files && $do_dirs) { + $files = array_merge($path['files'], $path['dirs']); + } elseif ($do_dirs) { + $files = $path['dirs']; + } else { + $files = $path['files']; + } + if (count($patterns)) { + $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); + $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; + $ret = array(); + $files_count = count($files); + for ($i = 0; $i < $files_count; $i++) { + // only search in the part of the file below the current directory + $filepart = basename($files[$i]); + if (preg_match($pattern, $filepart)) { + $ret[] = $files[$i]; + } + } + return $ret; + } + return $files; + } +} \ No newline at end of file diff --git a/lib/Pear/XML/Parser.php b/lib/Pear/XML/Parser.php new file mode 100644 index 0000000..4173fbc --- /dev/null +++ b/lib/Pear/XML/Parser.php @@ -0,0 +1,690 @@ + | +// | Tomas V.V.Cox | +// | Stephan Schmidt | +// +----------------------------------------------------------------------+ +// +// $Id: Parser.php,v 1.28 2006/12/01 16:23:22 schst Exp $ + +/** + * XML Parser class. + * + * This is an XML parser based on PHP's "xml" extension, + * based on the bundled expat library. + * + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + */ + +/** + * uses PEAR's error handling + */ +require_once 'PEAR.php'; + +/** + * resource could not be created + */ +define('XML_PARSER_ERROR_NO_RESOURCE', 200); + +/** + * unsupported mode + */ +define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201); + +/** + * invalid encoding was given + */ +define('XML_PARSER_ERROR_INVALID_ENCODING', 202); + +/** + * specified file could not be read + */ +define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203); + +/** + * invalid input + */ +define('XML_PARSER_ERROR_INVALID_INPUT', 204); + +/** + * remote file cannot be retrieved in safe mode + */ +define('XML_PARSER_ERROR_REMOTE', 205); + +/** + * XML Parser class. + * + * This is an XML parser based on PHP's "xml" extension, + * based on the bundled expat library. + * + * Notes: + * - It requires PHP 4.0.4pl1 or greater + * - From revision 1.17, the function names used by the 'func' mode + * are in the format "xmltag_$elem", for example: use "xmltag_name" + * to handle the tags of your xml file. + * + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + * @todo create XML_Parser_Namespace to parse documents with namespaces + * @todo create XML_Parser_Pull + * @todo Tests that need to be made: + * - mixing character encodings + * - a test using all expat handlers + * - options (folding, output charset) + * - different parsing modes + */ +class XML_Parser extends PEAR +{ + // {{{ properties + + /** + * XML parser handle + * + * @var resource + * @see xml_parser_create() + */ + var $parser; + + /** + * File handle if parsing from a file + * + * @var resource + */ + var $fp; + + /** + * Whether to do case folding + * + * If set to true, all tag and attribute names will + * be converted to UPPER CASE. + * + * @var boolean + */ + var $folding = true; + + /** + * Mode of operation, one of "event" or "func" + * + * @var string + */ + var $mode; + + /** + * Mapping from expat handler function to class method. + * + * @var array + */ + var $handler = array( + 'character_data_handler' => 'cdataHandler', + 'default_handler' => 'defaultHandler', + 'processing_instruction_handler' => 'piHandler', + 'unparsed_entity_decl_handler' => 'unparsedHandler', + 'notation_decl_handler' => 'notationHandler', + 'external_entity_ref_handler' => 'entityrefHandler' + ); + + /** + * source encoding + * + * @var string + */ + var $srcenc; + + /** + * target encoding + * + * @var string + */ + var $tgtenc; + + /** + * handler object + * + * @var object + */ + var $_handlerObj; + + /** + * valid encodings + * + * @var array + */ + var $_validEncodings = array('ISO-8859-1', 'UTF-8', 'US-ASCII'); + + // }}} + // {{{ constructor + + /** + * Creates an XML parser. + * + * This is needed for PHP4 compatibility, it will + * call the constructor, when a new instance is created. + * + * @param string $srcenc source charset encoding, use NULL (default) to use + * whatever the document specifies + * @param string $mode how this parser object should work, "event" for + * startelement/endelement-type events, "func" + * to have it call functions named after elements + * @param string $tgenc a valid target encoding + */ + function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null) + { + XML_Parser::__construct($srcenc, $mode, $tgtenc); + } + // }}} + + /** + * PHP5 constructor + * + * @param string $srcenc source charset encoding, use NULL (default) to use + * whatever the document specifies + * @param string $mode how this parser object should work, "event" for + * startelement/endelement-type events, "func" + * to have it call functions named after elements + * @param string $tgenc a valid target encoding + */ + function __construct($srcenc = null, $mode = 'event', $tgtenc = null) + { + $this->PEAR('XML_Parser_Error'); + + $this->mode = $mode; + $this->srcenc = $srcenc; + $this->tgtenc = $tgtenc; + } + // }}} + + /** + * Sets the mode of the parser. + * + * Possible modes are: + * - func + * - event + * + * You can set the mode using the second parameter + * in the constructor. + * + * This method is only needed, when switching to a new + * mode at a later point. + * + * @access public + * @param string mode, either 'func' or 'event' + * @return boolean|object true on success, PEAR_Error otherwise + */ + function setMode($mode) + { + if ($mode != 'func' && $mode != 'event') { + $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + } + + $this->mode = $mode; + return true; + } + + /** + * Sets the object, that will handle the XML events + * + * This allows you to create a handler object independent of the + * parser object that you are using and easily switch the underlying + * parser. + * + * If no object will be set, XML_Parser assumes that you + * extend this class and handle the events in $this. + * + * @access public + * @param object object to handle the events + * @return boolean will always return true + * @since v1.2.0beta3 + */ + function setHandlerObj(&$obj) + { + $this->_handlerObj = &$obj; + return true; + } + + /** + * Init the element handlers + * + * @access private + */ + function _initHandlers() + { + if (!is_resource($this->parser)) { + return false; + } + + if (!is_object($this->_handlerObj)) { + $this->_handlerObj = &$this; + } + switch ($this->mode) { + + case 'func': + xml_set_object($this->parser, $this->_handlerObj); + xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); + break; + + case 'event': + xml_set_object($this->parser, $this->_handlerObj); + xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); + break; + default: + return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + break; + } + + + /** + * set additional handlers for character data, entities, etc. + */ + foreach ($this->handler as $xml_func => $method) { + if (method_exists($this->_handlerObj, $method)) { + $xml_func = 'xml_set_' . $xml_func; + $xml_func($this->parser, $method); + } + } + } + + // {{{ _create() + + /** + * create the XML parser resource + * + * Has been moved from the constructor to avoid + * problems with object references. + * + * Furthermore it allows us returning an error + * if something fails. + * + * @access private + * @return boolean|object true on success, PEAR_Error otherwise + * + * @see xml_parser_create + */ + function _create() + { + if ($this->srcenc === null) { + $xp = @xml_parser_create(); + } else { + $xp = @xml_parser_create($this->srcenc); + } + if (is_resource($xp)) { + if ($this->tgtenc !== null) { + if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, + $this->tgtenc)) { + return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING); + } + } + $this->parser = $xp; + $result = $this->_initHandlers($this->mode); + if ($this->isError($result)) { + return $result; + } + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); + return true; + } + if (!in_array(strtoupper($this->srcenc), $this->_validEncodings)) { + return $this->raiseError('invalid source encoding', XML_PARSER_ERROR_INVALID_ENCODING); + } + return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE); + } + + // }}} + // {{{ reset() + + /** + * Reset the parser. + * + * This allows you to use one parser instance + * to parse multiple XML documents. + * + * @access public + * @return boolean|object true on success, PEAR_Error otherwise + */ + function reset() + { + $result = $this->_create(); + if ($this->isError( $result )) { + return $result; + } + return true; + } + + // }}} + // {{{ setInputFile() + + /** + * Sets the input xml file to be parsed + * + * @param string Filename (full path) + * @return resource fopen handle of the given file + * @throws XML_Parser_Error + * @see setInput(), setInputString(), parse() + * @access public + */ + function setInputFile($file) + { + /** + * check, if file is a remote file + */ + if (eregi('^(http|ftp)://', substr($file, 0, 10))) { + if (!ini_get('allow_url_fopen')) { + return $this->raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE); + } + } + + $fp = @fopen($file, 'rb'); + if (is_resource($fp)) { + $this->fp = $fp; + return $fp; + } + return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE); + } + + // }}} + // {{{ setInputString() + + /** + * XML_Parser::setInputString() + * + * Sets the xml input from a string + * + * @param string $data a string containing the XML document + * @return null + **/ + function setInputString($data) + { + $this->fp = $data; + return null; + } + + // }}} + // {{{ setInput() + + /** + * Sets the file handle to use with parse(). + * + * You should use setInputFile() or setInputString() if you + * pass a string + * + * @param mixed $fp Can be either a resource returned from fopen(), + * a URL, a local filename or a string. + * @access public + * @see parse() + * @uses setInputString(), setInputFile() + */ + function setInput($fp) + { + if (is_resource($fp)) { + $this->fp = $fp; + return true; + } + // see if it's an absolute URL (has a scheme at the beginning) + elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) { + return $this->setInputFile($fp); + } + // see if it's a local file + elseif (file_exists($fp)) { + return $this->setInputFile($fp); + } + // it must be a string + else { + $this->fp = $fp; + return true; + } + + return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT); + } + + // }}} + // {{{ parse() + + /** + * Central parsing function. + * + * @return true|object PEAR error returns true on success, or a PEAR_Error otherwise + * @access public + */ + function parse() + { + /** + * reset the parser + */ + $result = $this->reset(); + if ($this->isError($result)) { + return $result; + } + // if $this->fp was fopened previously + if (is_resource($this->fp)) { + + while ($data = fread($this->fp, 4096)) { + if (!$this->_parseString($data, feof($this->fp))) { + $error = &$this->raiseError(); + $this->free(); + return $error; + } + } + // otherwise, $this->fp must be a string + } else { + if (!$this->_parseString($this->fp, true)) { + $error = &$this->raiseError(); + $this->free(); + return $error; + } + } + $this->free(); + + return true; + } + + /** + * XML_Parser::_parseString() + * + * @param string $data + * @param boolean $eof + * @return bool + * @access private + * @see parseString() + **/ + function _parseString($data, $eof = false) + { + return xml_parse($this->parser, $data, $eof); + } + + // }}} + // {{{ parseString() + + /** + * XML_Parser::parseString() + * + * Parses a string. + * + * @param string $data XML data + * @param boolean $eof If set and TRUE, data is the last piece of data sent in this parser + * @throws XML_Parser_Error + * @return Pear Error|true true on success or a PEAR Error + * @see _parseString() + */ + function parseString($data, $eof = false) + { + if (!isset($this->parser) || !is_resource($this->parser)) { + $this->reset(); + } + + if (!$this->_parseString($data, $eof)) { + $error = &$this->raiseError(); + $this->free(); + return $error; + } + + if ($eof === true) { + $this->free(); + } + return true; + } + + /** + * XML_Parser::free() + * + * Free the internal resources associated with the parser + * + * @return null + **/ + function free() + { + if (isset($this->parser) && is_resource($this->parser)) { + xml_parser_free($this->parser); + unset( $this->parser ); + } + if (isset($this->fp) && is_resource($this->fp)) { + fclose($this->fp); + } + unset($this->fp); + return null; + } + + /** + * XML_Parser::raiseError() + * + * Throws a XML_Parser_Error + * + * @param string $msg the error message + * @param integer $ecode the error message code + * @return XML_Parser_Error + **/ + function raiseError($msg = null, $ecode = 0) + { + $msg = !is_null($msg) ? $msg : $this->parser; + $err = &new XML_Parser_Error($msg, $ecode); + return parent::raiseError($err); + } + + // }}} + // {{{ funcStartHandler() + + function funcStartHandler($xp, $elem, $attribs) + { + $func = 'xmltag_' . $elem; + $func = str_replace(array('.', '-', ':'), '_', $func); + if (method_exists($this->_handlerObj, $func)) { + call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs); + } elseif (method_exists($this->_handlerObj, 'xmltag')) { + call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs); + } + } + + // }}} + // {{{ funcEndHandler() + + function funcEndHandler($xp, $elem) + { + $func = 'xmltag_' . $elem . '_'; + $func = str_replace(array('.', '-', ':'), '_', $func); + if (method_exists($this->_handlerObj, $func)) { + call_user_func(array(&$this->_handlerObj, $func), $xp, $elem); + } elseif (method_exists($this->_handlerObj, 'xmltag_')) { + call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem); + } + } + + // }}} + // {{{ startHandler() + + /** + * + * @abstract + */ + function startHandler($xp, $elem, &$attribs) + { + return NULL; + } + + // }}} + // {{{ endHandler() + + /** + * + * @abstract + */ + function endHandler($xp, $elem) + { + return NULL; + } + + + // }}}me +} + +/** + * error class, replaces PEAR_Error + * + * An instance of this class will be returned + * if an error occurs inside XML_Parser. + * + * There are three advantages over using the standard PEAR_Error: + * - All messages will be prefixed + * - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' ) + * - messages can be generated from the xml_parser resource + * + * @package XML_Parser + * @access public + * @see PEAR_Error + */ +class XML_Parser_Error extends PEAR_Error +{ + // {{{ properties + + /** + * prefix for all messages + * + * @var string + */ + var $error_message_prefix = 'XML_Parser: '; + + // }}} + // {{{ constructor() + /** + * construct a new error instance + * + * You may either pass a message or an xml_parser resource as first + * parameter. If a resource has been passed, the last error that + * happened will be retrieved and returned. + * + * @access public + * @param string|resource message or parser resource + * @param integer error code + * @param integer error handling + * @param integer error level + */ + function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) + { + if (is_resource($msgorparser)) { + $code = xml_get_error_code($msgorparser); + $msgorparser = sprintf('%s at XML input line %d:%d', + xml_error_string($code), + xml_get_current_line_number($msgorparser), + xml_get_current_column_number($msgorparser)); + } + $this->PEAR_Error($msgorparser, $code, $mode, $level); + } + // }}} +} +?> \ No newline at end of file diff --git a/lib/Pear/XML/Parser/Simple.php b/lib/Pear/XML/Parser/Simple.php new file mode 100644 index 0000000..aa60ec9 --- /dev/null +++ b/lib/Pear/XML/Parser/Simple.php @@ -0,0 +1,297 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Simple.php,v 1.6 2005/03/25 17:13:10 schst Exp $ + +/** + * Simple XML parser class. + * + * This class is a simplified version of XML_Parser. + * In most XML applications the real action is executed, + * when a closing tag is found. + * + * XML_Parser_Simple allows you to just implement one callback + * for each tag that will receive the tag with its attributes + * and CData + * + * @category XML + * @package XML_Parser + * @author Stephan Schmidt + */ + +/** + * built on XML_Parser + */ +require_once 'XML/Parser.php'; + +/** + * Simple XML parser class. + * + * This class is a simplified version of XML_Parser. + * In most XML applications the real action is executed, + * when a closing tag is found. + * + * XML_Parser_Simple allows you to just implement one callback + * for each tag that will receive the tag with its attributes + * and CData. + * + * + * require_once '../Parser/Simple.php'; + * + * class myParser extends XML_Parser_Simple + * { + * function myParser() + * { + * $this->XML_Parser_Simple(); + * } + * + * function handleElement($name, $attribs, $data) + * { + * printf('handle %s
', $name); + * } + * } + * + * $p = &new myParser(); + * + * $result = $p->setInputFile('myDoc.xml'); + * $result = $p->parse(); + *
+ * + * @category XML + * @package XML_Parser + * @author Stephan Schmidt + */ +class XML_Parser_Simple extends XML_Parser +{ + /** + * element stack + * + * @access private + * @var array + */ + var $_elStack = array(); + + /** + * all character data + * + * @access private + * @var array + */ + var $_data = array(); + + /** + * element depth + * + * @access private + * @var integer + */ + var $_depth = 0; + + /** + * Mapping from expat handler function to class method. + * + * @var array + */ + var $handler = array( + 'default_handler' => 'defaultHandler', + 'processing_instruction_handler' => 'piHandler', + 'unparsed_entity_decl_handler' => 'unparsedHandler', + 'notation_decl_handler' => 'notationHandler', + 'external_entity_ref_handler' => 'entityrefHandler' + ); + + /** + * Creates an XML parser. + * + * This is needed for PHP4 compatibility, it will + * call the constructor, when a new instance is created. + * + * @param string $srcenc source charset encoding, use NULL (default) to use + * whatever the document specifies + * @param string $mode how this parser object should work, "event" for + * handleElement(), "func" to have it call functions + * named after elements (handleElement_$name()) + * @param string $tgenc a valid target encoding + */ + function XML_Parser_Simple($srcenc = null, $mode = 'event', $tgtenc = null) + { + $this->XML_Parser($srcenc, $mode, $tgtenc); + } + + /** + * inits the handlers + * + * @access private + */ + function _initHandlers() + { + if (!is_object($this->_handlerObj)) { + $this->_handlerObj = &$this; + } + + if ($this->mode != 'func' && $this->mode != 'event') { + return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + } + xml_set_object($this->parser, $this->_handlerObj); + + xml_set_element_handler($this->parser, array(&$this, 'startHandler'), array(&$this, 'endHandler')); + xml_set_character_data_handler($this->parser, array(&$this, 'cdataHandler')); + + /** + * set additional handlers for character data, entities, etc. + */ + foreach ($this->handler as $xml_func => $method) { + if (method_exists($this->_handlerObj, $method)) { + $xml_func = 'xml_set_' . $xml_func; + $xml_func($this->parser, $method); + } + } + } + + /** + * Reset the parser. + * + * This allows you to use one parser instance + * to parse multiple XML documents. + * + * @access public + * @return boolean|object true on success, PEAR_Error otherwise + */ + function reset() + { + $this->_elStack = array(); + $this->_data = array(); + $this->_depth = 0; + + $result = $this->_create(); + if ($this->isError( $result )) { + return $result; + } + return true; + } + + /** + * start handler + * + * Pushes attributes and tagname onto a stack + * + * @access private + * @final + * @param resource xml parser resource + * @param string element name + * @param array attributes + */ + function startHandler($xp, $elem, &$attribs) + { + array_push($this->_elStack, array( + 'name' => $elem, + 'attribs' => $attribs + ) + ); + $this->_depth++; + $this->_data[$this->_depth] = ''; + } + + /** + * end handler + * + * Pulls attributes and tagname from a stack + * + * @access private + * @final + * @param resource xml parser resource + * @param string element name + */ + function endHandler($xp, $elem) + { + $el = array_pop($this->_elStack); + $data = $this->_data[$this->_depth]; + $this->_depth--; + + switch ($this->mode) { + case 'event': + $this->_handlerObj->handleElement($el['name'], $el['attribs'], $data); + break; + case 'func': + $func = 'handleElement_' . $elem; + if (strchr($func, '.')) { + $func = str_replace('.', '_', $func); + } + if (method_exists($this->_handlerObj, $func)) { + call_user_func(array(&$this->_handlerObj, $func), $el['name'], $el['attribs'], $data); + } + break; + } + } + + /** + * handle character data + * + * @access private + * @final + * @param resource xml parser resource + * @param string data + */ + function cdataHandler($xp, $data) + { + $this->_data[$this->_depth] .= $data; + } + + /** + * handle a tag + * + * Implement this in your parser + * + * @access public + * @abstract + * @param string element name + * @param array attributes + * @param string character data + */ + function handleElement($name, $attribs, $data) + { + } + + /** + * get the current tag depth + * + * The root tag is in depth 0. + * + * @access public + * @return integer + */ + function getCurrentDepth() + { + return $this->_depth; + } + + /** + * add some string to the current ddata. + * + * This is commonly needed, when a document is parsed recursively. + * + * @access public + * @param string data to add + * @return void + */ + function addToData( $data ) + { + $this->_data[$this->_depth] .= $data; + } +} +?> diff --git a/lib/Pear/XML/RPC.php b/lib/Pear/XML/RPC.php new file mode 100644 index 0000000..0b3d305 --- /dev/null +++ b/lib/Pear/XML/RPC.php @@ -0,0 +1,2077 @@ + + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version CVS: $Id: RPC.php 222479 2006-10-28 16:42:34Z danielc $ + * @link http://pear.php.net/package/XML_RPC + */ + + +if (!function_exists('xml_parser_create')) { + include_once 'PEAR.php'; + PEAR::loadExtension('xml'); +} + +/**#@+ + * Error constants + */ +/** + * Parameter values don't match parameter types + */ +define('XML_RPC_ERROR_INVALID_TYPE', 101); +/** + * Parameter declared to be numeric but the values are not + */ +define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102); +/** + * Communication error + */ +define('XML_RPC_ERROR_CONNECTION_FAILED', 103); +/** + * The array or struct has already been started + */ +define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104); +/** + * Incorrect parameters submitted + */ +define('XML_RPC_ERROR_INCORRECT_PARAMS', 105); +/** + * Programming error by developer + */ +define('XML_RPC_ERROR_PROGRAMMING', 106); +/**#@-*/ + + +/** + * Data types + * @global string $GLOBALS['XML_RPC_I4'] + */ +$GLOBALS['XML_RPC_I4'] = 'i4'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Int'] + */ +$GLOBALS['XML_RPC_Int'] = 'int'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Boolean'] + */ +$GLOBALS['XML_RPC_Boolean'] = 'boolean'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Double'] + */ +$GLOBALS['XML_RPC_Double'] = 'double'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_String'] + */ +$GLOBALS['XML_RPC_String'] = 'string'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_DateTime'] + */ +$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Base64'] + */ +$GLOBALS['XML_RPC_Base64'] = 'base64'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Array'] + */ +$GLOBALS['XML_RPC_Array'] = 'array'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Struct'] + */ +$GLOBALS['XML_RPC_Struct'] = 'struct'; + + +/** + * Data type meta-types + * @global array $GLOBALS['XML_RPC_Types'] + */ +$GLOBALS['XML_RPC_Types'] = array( + $GLOBALS['XML_RPC_I4'] => 1, + $GLOBALS['XML_RPC_Int'] => 1, + $GLOBALS['XML_RPC_Boolean'] => 1, + $GLOBALS['XML_RPC_String'] => 1, + $GLOBALS['XML_RPC_Double'] => 1, + $GLOBALS['XML_RPC_DateTime'] => 1, + $GLOBALS['XML_RPC_Base64'] => 1, + $GLOBALS['XML_RPC_Array'] => 2, + $GLOBALS['XML_RPC_Struct'] => 3, +); + + +/** + * Error message numbers + * @global array $GLOBALS['XML_RPC_err'] + */ +$GLOBALS['XML_RPC_err'] = array( + 'unknown_method' => 1, + 'invalid_return' => 2, + 'incorrect_params' => 3, + 'introspect_unknown' => 4, + 'http_error' => 5, + 'not_response_object' => 6, + 'invalid_request' => 7, +); + +/** + * Error message strings + * @global array $GLOBALS['XML_RPC_str'] + */ +$GLOBALS['XML_RPC_str'] = array( + 'unknown_method' => 'Unknown method', + 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload', + 'incorrect_params' => 'Incorrect parameters passed to method', + 'introspect_unknown' => 'Can\'t introspect: method unknown', + 'http_error' => 'Didn\'t receive 200 OK from remote server.', + 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.', + 'invalid_request' => 'Invalid request payload', +); + + +/** + * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII) + * @global string $GLOBALS['XML_RPC_defencoding'] + */ +$GLOBALS['XML_RPC_defencoding'] = 'UTF-8'; + +/** + * User error codes start at 800 + * @global int $GLOBALS['XML_RPC_erruser'] + */ +$GLOBALS['XML_RPC_erruser'] = 800; + +/** + * XML parse error codes start at 100 + * @global int $GLOBALS['XML_RPC_errxml'] + */ +$GLOBALS['XML_RPC_errxml'] = 100; + + +/** + * Compose backslashes for escaping regexp + * @global string $GLOBALS['XML_RPC_backslash'] + */ +$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92); + + +/**#@+ + * Which functions to use, depending on whether mbstring is enabled or not. + */ +if (function_exists('mb_ereg')) { + /** @global string $GLOBALS['XML_RPC_func_ereg'] */ + $GLOBALS['XML_RPC_func_ereg'] = 'mb_eregi'; + /** @global string $GLOBALS['XML_RPC_func_ereg_replace'] */ + $GLOBALS['XML_RPC_func_ereg_replace'] = 'mb_eregi_replace'; + /** @global string $GLOBALS['XML_RPC_func_split'] */ + $GLOBALS['XML_RPC_func_split'] = 'mb_split'; +} else { + /** @ignore */ + $GLOBALS['XML_RPC_func_ereg'] = 'eregi'; + /** @ignore */ + $GLOBALS['XML_RPC_func_ereg_replace'] = 'eregi_replace'; + /** @ignore */ + $GLOBALS['XML_RPC_func_split'] = 'split'; +} +/**#@-*/ + + +/** + * Should we automatically base64 encode strings that contain characters + * which can cause PHP's SAX-based XML parser to break? + * @global boolean $GLOBALS['XML_RPC_auto_base64'] + */ +$GLOBALS['XML_RPC_auto_base64'] = false; + + +/** + * Valid parents of XML elements + * @global array $GLOBALS['XML_RPC_valid_parents'] + */ +$GLOBALS['XML_RPC_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'), +); + + +/** + * Stores state during parsing + * + * quick explanation of components: + * + ac = accumulates values + * + qt = decides if quotes are needed for evaluation + * + cm = denotes struct or array (comma needed) + * + isf = indicates a fault + * + lv = indicates "looking for a value": implements the logic + * to allow values with no types to be strings + * + params = stores parameters in method calls + * + method = stores method name + * + * @global array $GLOBALS['XML_RPC_xh'] + */ +$GLOBALS['XML_RPC_xh'] = array(); + + +/** + * Start element handler for the XML parser + * + * @return void + */ +function XML_RPC_se($parser_resource, $name, $attrs) +{ + global $XML_RPC_xh, $XML_RPC_valid_parents; + + $parser = (int) $parser_resource; + + // if invalid xmlrpc already detected, skip all processing + if ($XML_RPC_xh[$parser]['isf'] >= 2) { + return; + } + + // check for correct element nesting + // top level element can only be of 2 types + if (count($XML_RPC_xh[$parser]['stack']) == 0) { + if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') { + $XML_RPC_xh[$parser]['isf'] = 2; + $XML_RPC_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element'; + return; + } + } else { + // not top level element: see if parent is OK + if (!in_array($XML_RPC_xh[$parser]['stack'][0], $XML_RPC_valid_parents[$name])) { + $name = $GLOBALS['XML_RPC_func_ereg_replace']('[^a-zA-Z0-9._-]', '', $name); + $XML_RPC_xh[$parser]['isf'] = 2; + $XML_RPC_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$XML_RPC_xh[$parser]['stack'][0]}"; + return; + } + } + + switch ($name) { + case 'STRUCT': + $XML_RPC_xh[$parser]['cm']++; + + // turn quoting off + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array(); + $cur_val['value'] = array(); + $cur_val['members'] = 1; + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + break; + + case 'ARRAY': + $XML_RPC_xh[$parser]['cm']++; + + // turn quoting off + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array(); + $cur_val['value'] = array(); + $cur_val['members'] = 0; + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + break; + + case 'NAME': + $XML_RPC_xh[$parser]['ac'] = ''; + break; + + case 'FAULT': + $XML_RPC_xh[$parser]['isf'] = 1; + break; + + case 'PARAM': + $XML_RPC_xh[$parser]['valuestack'] = array(); + break; + + case 'VALUE': + $XML_RPC_xh[$parser]['lv'] = 1; + $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_String']; + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + // look for a value: if this is still 1 by the + // time we reach the first data segment then the type is string + // by implication and we need to add in a quote + break; + + case 'I4': + case 'INT': + case 'STRING': + case 'BOOLEAN': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator + + if ($name == 'DATETIME.ISO8601' || $name == 'STRING') { + $XML_RPC_xh[$parser]['qt'] = 1; + + if ($name == 'DATETIME.ISO8601') { + $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_DateTime']; + } + + } elseif ($name == 'BASE64') { + $XML_RPC_xh[$parser]['qt'] = 2; + } else { + // No quoting is required here -- but + // at the end of the element we must check + // for data format errors. + $XML_RPC_xh[$parser]['qt'] = 0; + } + break; + + case 'MEMBER': + $XML_RPC_xh[$parser]['ac'] = ''; + break; + + case 'DATA': + case 'METHODCALL': + case 'METHODNAME': + case 'METHODRESPONSE': + case 'PARAMS': + // valid elements that add little to processing + break; + } + + + // Save current element to stack + array_unshift($XML_RPC_xh[$parser]['stack'], $name); + + if ($name != 'VALUE') { + $XML_RPC_xh[$parser]['lv'] = 0; + } +} + +/** + * End element handler for the XML parser + * + * @return void + */ +function XML_RPC_ee($parser_resource, $name) +{ + global $XML_RPC_xh; + + $parser = (int) $parser_resource; + + if ($XML_RPC_xh[$parser]['isf'] >= 2) { + return; + } + + // push this element from stack + // NB: if XML validates, correct opening/closing is guaranteed and + // we do not have to check for $name == $curr_elem. + // we also checked for proper nesting at start of elements... + $curr_elem = array_shift($XML_RPC_xh[$parser]['stack']); + + switch ($name) { + case 'STRUCT': + case 'ARRAY': + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + $XML_RPC_xh[$parser]['value'] = $cur_val['value']; + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + $XML_RPC_xh[$parser]['cm']--; + break; + + case 'NAME': + $XML_RPC_xh[$parser]['valuestack'][0]['name'] = $XML_RPC_xh[$parser]['ac']; + break; + + case 'BOOLEAN': + // special case here: we translate boolean 1 or 0 into PHP + // constants true or false + if ($XML_RPC_xh[$parser]['ac'] == '1') { + $XML_RPC_xh[$parser]['ac'] = 'true'; + } else { + $XML_RPC_xh[$parser]['ac'] = 'false'; + } + + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + // Drop through intentionally. + + case 'I4': + case 'INT': + case 'STRING': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + if ($XML_RPC_xh[$parser]['qt'] == 1) { + // we use double quotes rather than single so backslashification works OK + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } elseif ($XML_RPC_xh[$parser]['qt'] == 2) { + $XML_RPC_xh[$parser]['value'] = base64_decode($XML_RPC_xh[$parser]['ac']); + } elseif ($name == 'BOOLEAN') { + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } else { + // we have an I4, INT or a DOUBLE + // we must check that only 0123456789-. are characters here + if (!$GLOBALS['XML_RPC_func_ereg']("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) { + XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE', + XML_RPC_ERROR_NON_NUMERIC_FOUND); + $XML_RPC_xh[$parser]['value'] = XML_RPC_ERROR_NON_NUMERIC_FOUND; + } else { + // it's ok, add it on + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } + } + + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value + break; + + case 'VALUE': + if ($XML_RPC_xh[$parser]['vt'] == $GLOBALS['XML_RPC_String']) { + if (strlen($XML_RPC_xh[$parser]['ac']) > 0) { + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } elseif ($XML_RPC_xh[$parser]['lv'] == 1) { + // The element was empty. + $XML_RPC_xh[$parser]['value'] = ''; + } + } + + $temp = new XML_RPC_Value($XML_RPC_xh[$parser]['value'], $XML_RPC_xh[$parser]['vt']); + + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + if (is_array($cur_val)) { + if ($cur_val['members']==0) { + $cur_val['value'][] = $temp; + } else { + $XML_RPC_xh[$parser]['value'] = $temp; + } + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + } else { + $XML_RPC_xh[$parser]['value'] = $temp; + } + break; + + case 'MEMBER': + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + if (is_array($cur_val)) { + if ($cur_val['members']==1) { + $cur_val['value'][$cur_val['name']] = $XML_RPC_xh[$parser]['value']; + } + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + } + break; + + case 'DATA': + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + break; + + case 'PARAM': + $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['value']; + break; + + case 'METHODNAME': + case 'RPCMETHODNAME': + $XML_RPC_xh[$parser]['method'] = $GLOBALS['XML_RPC_func_ereg_replace']("^[\n\r\t ]+", '', + $XML_RPC_xh[$parser]['ac']); + break; + } + + // if it's a valid type name, set the type + if (isset($GLOBALS['XML_RPC_Types'][strtolower($name)])) { + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + } +} + +/** + * Character data handler for the XML parser + * + * @return void + */ +function XML_RPC_cd($parser_resource, $data) +{ + global $XML_RPC_xh, $XML_RPC_backslash; + + $parser = (int) $parser_resource; + + if ($XML_RPC_xh[$parser]['lv'] != 3) { + // "lookforvalue==3" means that we've found an entire value + // and should discard any further character data + + if ($XML_RPC_xh[$parser]['lv'] == 1) { + // if we've found text and we're just in a then + // turn quoting on, as this will be a string + $XML_RPC_xh[$parser]['qt'] = 1; + // and say we've found a value + $XML_RPC_xh[$parser]['lv'] = 2; + } + + // replace characters that eval would + // do special things with + if (!isset($XML_RPC_xh[$parser]['ac'])) { + $XML_RPC_xh[$parser]['ac'] = ''; + } + $XML_RPC_xh[$parser]['ac'] .= $data; + } +} + +/** + * The common methods and properties for all of the XML_RPC classes + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Base { + + /** + * PEAR Error handling + * + * @return object PEAR_Error object + */ + function raiseError($msg, $code) + { + include_once 'PEAR.php'; + if (is_object(@$this)) { + return PEAR::raiseError(get_class($this) . ': ' . $msg, $code); + } else { + return PEAR::raiseError('XML_RPC: ' . $msg, $code); + } + } + + /** + * Tell whether something is a PEAR_Error object + * + * @param mixed $value the item to check + * + * @return bool whether $value is a PEAR_Error object or not + * + * @access public + */ + function isError($value) + { + return is_a($value, 'PEAR_Error'); + } +} + +/** + * The methods and properties for submitting XML RPC requests + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Client extends XML_RPC_Base { + + /** + * The path and name of the RPC server script you want the request to go to + * @var string + */ + var $path = ''; + + /** + * The name of the remote server to connect to + * @var string + */ + var $server = ''; + + /** + * The protocol to use in contacting the remote server + * @var string + */ + var $protocol = 'http://'; + + /** + * The port for connecting to the remote server + * + * The default is 80 for http:// connections + * and 443 for https:// and ssl:// connections. + * + * @var integer + */ + var $port = 80; + + /** + * A user name for accessing the RPC server + * @var string + * @see XML_RPC_Client::setCredentials() + */ + var $username = ''; + + /** + * A password for accessing the RPC server + * @var string + * @see XML_RPC_Client::setCredentials() + */ + var $password = ''; + + /** + * The name of the proxy server to use, if any + * @var string + */ + var $proxy = ''; + + /** + * The protocol to use in contacting the proxy server, if any + * @var string + */ + var $proxy_protocol = 'http://'; + + /** + * The port for connecting to the proxy server + * + * The default is 8080 for http:// connections + * and 443 for https:// and ssl:// connections. + * + * @var integer + */ + var $proxy_port = 8080; + + /** + * A user name for accessing the proxy server + * @var string + */ + var $proxy_user = ''; + + /** + * A password for accessing the proxy server + * @var string + */ + var $proxy_pass = ''; + + /** + * The error number, if any + * @var integer + */ + var $errno = 0; + + /** + * The error message, if any + * @var string + */ + var $errstr = ''; + + /** + * The current debug mode (1 = on, 0 = off) + * @var integer + */ + var $debug = 0; + + /** + * The HTTP headers for the current request. + * @var string + */ + var $headers = ''; + + + /** + * Sets the object's properties + * + * @param string $path the path and name of the RPC server script + * you want the request to go to + * @param string $server the URL of the remote server to connect to. + * If this parameter doesn't specify a + * protocol and $port is 443, ssl:// is + * assumed. + * @param integer $port a port for connecting to the remote server. + * Defaults to 80 for http:// connections and + * 443 for https:// and ssl:// connections. + * @param string $proxy the URL of the proxy server to use, if any. + * If this parameter doesn't specify a + * protocol and $port is 443, ssl:// is + * assumed. + * @param integer $proxy_port a port for connecting to the remote server. + * Defaults to 8080 for http:// connections and + * 443 for https:// and ssl:// connections. + * @param string $proxy_user a user name for accessing the proxy server + * @param string $proxy_pass a password for accessing the proxy server + * + * @return void + */ + function XML_RPC_Client($path, $server, $port = 0, + $proxy = '', $proxy_port = 0, + $proxy_user = '', $proxy_pass = '') + { + $this->path = $path; + $this->proxy_user = $proxy_user; + $this->proxy_pass = $proxy_pass; + + $GLOBALS['XML_RPC_func_ereg']('^(http://|https://|ssl://)?(.*)$', $server, $match); + if ($match[1] == '') { + if ($port == 443) { + $this->server = $match[2]; + $this->protocol = 'ssl://'; + $this->port = 443; + } else { + $this->server = $match[2]; + if ($port) { + $this->port = $port; + } + } + } elseif ($match[1] == 'http://') { + $this->server = $match[2]; + if ($port) { + $this->port = $port; + } + } else { + $this->server = $match[2]; + $this->protocol = 'ssl://'; + if ($port) { + $this->port = $port; + } else { + $this->port = 443; + } + } + + if ($proxy) { + $GLOBALS['XML_RPC_func_ereg']('^(http://|https://|ssl://)?(.*)$', $proxy, $match); + if ($match[1] == '') { + if ($proxy_port == 443) { + $this->proxy = $match[2]; + $this->proxy_protocol = 'ssl://'; + $this->proxy_port = 443; + } else { + $this->proxy = $match[2]; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } + } + } elseif ($match[1] == 'http://') { + $this->proxy = $match[2]; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } + } else { + $this->proxy = $match[2]; + $this->proxy_protocol = 'ssl://'; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } else { + $this->proxy_port = 443; + } + } + } + } + + /** + * Change the current debug mode + * + * @param int $in where 1 = on, 0 = off + * + * @return void + */ + function setDebug($in) + { + if ($in) { + $this->debug = 1; + } else { + $this->debug = 0; + } + } + + /** + * Sets whether strings that contain characters which may cause PHP's + * SAX-based XML parser to break should be automatically base64 encoded + * + * This is is a workaround for systems that don't have PHP's mbstring + * extension available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + */ + function setAutoBase64($in) + { + if ($in) { + $GLOBALS['XML_RPC_auto_base64'] = true; + } else { + $GLOBALS['XML_RPC_auto_base64'] = false; + } + } + + /** + * Set username and password properties for connecting to the RPC server + * + * @param string $u the user name + * @param string $p the password + * + * @return void + * + * @see XML_RPC_Client::$username, XML_RPC_Client::$password + */ + function setCredentials($u, $p) + { + $this->username = $u; + $this->password = $p; + } + + /** + * Transmit the RPC request via HTTP 1.0 protocol + * + * @param object $msg the XML_RPC_Message object + * @param int $timeout how many seconds to wait for the request + * + * @return object an XML_RPC_Response object. 0 is returned if any + * problems happen. + * + * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(), + * XML_RPC_Client::setCredentials() + */ + function send($msg, $timeout = 0) + { + if (!is_a($msg, 'XML_RPC_Message')) { + $this->errstr = 'send()\'s $msg parameter must be an' + . ' XML_RPC_Message object.'; + $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING); + return 0; + } + $msg->debug = $this->debug; + return $this->sendPayloadHTTP10($msg, $this->server, $this->port, + $timeout, $this->username, + $this->password); + } + + /** + * Transmit the RPC request via HTTP 1.0 protocol + * + * Requests should be sent using XML_RPC_Client send() rather than + * calling this method directly. + * + * @param object $msg the XML_RPC_Message object + * @param string $server the server to send the request to + * @param int $port the server port send the request to + * @param int $timeout how many seconds to wait for the request + * before giving up + * @param string $username a user name for accessing the RPC server + * @param string $password a password for accessing the RPC server + * + * @return object an XML_RPC_Response object. 0 is returned if any + * problems happen. + * + * @access protected + * @see XML_RPC_Client::send() + */ + function sendPayloadHTTP10($msg, $server, $port, $timeout = 0, + $username = '', $password = '') + { + /* + * If we're using a proxy open a socket to the proxy server + * instead to the xml-rpc server + */ + if ($this->proxy) { + if ($this->proxy_protocol == 'http://') { + $protocol = ''; + } else { + $protocol = $this->proxy_protocol; + } + if ($timeout > 0) { + $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, + $this->errno, $this->errstr, $timeout); + } else { + $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, + $this->errno, $this->errstr); + } + } else { + if ($this->protocol == 'http://') { + $protocol = ''; + } else { + $protocol = $this->protocol; + } + if ($timeout > 0) { + $fp = @fsockopen($protocol . $server, $port, + $this->errno, $this->errstr, $timeout); + } else { + $fp = @fsockopen($protocol . $server, $port, + $this->errno, $this->errstr); + } + } + + /* + * Just raising the error without returning it is strange, + * but keep it here for backwards compatibility. + */ + if (!$fp && $this->proxy) { + $this->raiseError('Connection to proxy server ' + . $this->proxy . ':' . $this->proxy_port + . ' failed. ' . $this->errstr, + XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } elseif (!$fp) { + $this->raiseError('Connection to RPC server ' + . $server . ':' . $port + . ' failed. ' . $this->errstr, + XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } + + if ($timeout) { + /* + * Using socket_set_timeout() because stream_set_timeout() + * was introduced in 4.3.0, but we need to support 4.2.0. + */ + socket_set_timeout($fp, $timeout); + } + + // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly + if ($username != $this->username) { + $this->setCredentials($username, $password); + } + + // Only create the payload if it was not created previously + if (empty($msg->payload)) { + $msg->createPayload(); + } + $this->createHeaders($msg); + + $op = $this->headers . "\r\n\r\n"; + $op .= $msg->payload; + + if (!fputs($fp, $op, strlen($op))) { + $this->errstr = 'Write error'; + return 0; + } + $resp = $msg->parseResponseFile($fp); + + $meta = socket_get_status($fp); + if ($meta['timed_out']) { + fclose($fp); + $this->errstr = 'RPC server did not send response before timeout.'; + $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } + + fclose($fp); + return $resp; + } + + /** + * Determines the HTTP headers and puts it in the $headers property + * + * @param object $msg the XML_RPC_Message object + * + * @return boolean TRUE if okay, FALSE if the message payload isn't set. + * + * @access protected + */ + function createHeaders($msg) + { + if (empty($msg->payload)) { + return false; + } + if ($this->proxy) { + $this->headers = 'POST ' . $this->protocol . $this->server; + if ($this->proxy_port) { + $this->headers .= ':' . $this->port; + } + } else { + $this->headers = 'POST '; + } + $this->headers .= $this->path. " HTTP/1.0\r\n"; + + $this->headers .= "User-Agent: PEAR XML_RPC\r\n"; + $this->headers .= 'Host: ' . $this->server . "\r\n"; + + if ($this->proxy && $this->proxy_user) { + $this->headers .= 'Proxy-Authorization: Basic ' + . base64_encode("$this->proxy_user:$this->proxy_pass") + . "\r\n"; + } + + // thanks to Grant Rauscher for this + if ($this->username) { + $this->headers .= 'Authorization: Basic ' + . base64_encode("$this->username:$this->password") + . "\r\n"; + } + + $this->headers .= "Content-Type: text/xml\r\n"; + $this->headers .= 'Content-Length: ' . strlen($msg->payload); + return true; + } +} + +/** + * The methods and properties for interpreting responses to XML RPC requests + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Response extends XML_RPC_Base +{ + var $xv; + var $fn; + var $fs; + var $hdrs; + + /** + * @return void + */ + function XML_RPC_Response($val, $fcode = 0, $fstr = '') + { + if ($fcode != 0) { + $this->fn = $fcode; + $this->fs = htmlspecialchars($fstr); + } else { + $this->xv = $val; + } + } + + /** + * @return int the error code + */ + function faultCode() + { + if (isset($this->fn)) { + return $this->fn; + } else { + return 0; + } + } + + /** + * @return string the error string + */ + function faultString() + { + return $this->fs; + } + + /** + * @return mixed the value + */ + function value() + { + return $this->xv; + } + + /** + * @return string the error message in XML format + */ + function serialize() + { + $rs = "\n"; + if ($this->fn) { + $rs .= " + + + + faultCode + " . $this->fn . " + + + faultString + " . $this->fs . " + + + +"; + } else { + $rs .= "\n\n" . $this->xv->serialize() . + "\n"; + } + $rs .= "\n"; + return $rs; + } +} + +/** + * The methods and properties for composing XML RPC messages + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Message extends XML_RPC_Base +{ + /** + * Should the payload's content be passed through mb_convert_encoding()? + * + * @see XML_RPC_Message::setConvertPayloadEncoding() + * @since Property available since Release 1.5.1 + * @var boolean + */ + var $convert_payload_encoding = false; + + /** + * The current debug mode (1 = on, 0 = off) + * @var integer + */ + var $debug = 0; + + /** + * The encoding to be used for outgoing messages + * + * Defaults to the value of $GLOBALS['XML_RPC_defencoding'] + * + * @var string + * @see XML_RPC_Message::setSendEncoding(), + * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header() + */ + var $send_encoding = ''; + + /** + * The method presently being evaluated + * @var string + */ + var $methodname = ''; + + /** + * @var array + */ + var $params = array(); + + /** + * The XML message being generated + * @var string + */ + var $payload = ''; + + /** + * Should extra line breaks be removed from the payload? + * @since Property available since Release 1.4.6 + * @var boolean + */ + var $remove_extra_lines = true; + + /** + * The XML response from the remote server + * @since Property available since Release 1.4.6 + * @var string + */ + var $response_payload = ''; + + + /** + * @return void + */ + function XML_RPC_Message($meth, $pars = 0) + { + $this->methodname = $meth; + if (is_array($pars) && sizeof($pars) > 0) { + for ($i = 0; $i < sizeof($pars); $i++) { + $this->addParam($pars[$i]); + } + } + } + + /** + * Produces the XML declaration including the encoding attribute + * + * The encoding is determined by this class' $send_encoding + * property. If the $send_encoding property is not set, use + * $GLOBALS['XML_RPC_defencoding']. + * + * @return string the XML declaration and element + * + * @see XML_RPC_Message::setSendEncoding(), + * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding'] + */ + function xml_header() + { + global $XML_RPC_defencoding; + + if (!$this->send_encoding) { + $this->send_encoding = $XML_RPC_defencoding; + } + return 'send_encoding . '"?>' + . "\n\n"; + } + + /** + * @return string the closing tag + */ + function xml_footer() + { + return "\n"; + } + + /** + * Fills the XML_RPC_Message::$payload property + * + * Part of the process makes sure all line endings are in DOS format + * (CRLF), which is probably required by specifications. + * + * If XML_RPC_Message::setConvertPayloadEncoding() was set to true, + * the payload gets passed through mb_convert_encoding() + * to ensure the payload matches the encoding set in the + * XML declaration. The encoding type can be manually set via + * XML_RPC_Message::setSendEncoding(). + * + * @return void + * + * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer() + * @see XML_RPC_Message::setSendEncoding(), $GLOBALS['XML_RPC_defencoding'], + * XML_RPC_Message::setConvertPayloadEncoding() + */ + function createPayload() + { + $this->payload = $this->xml_header(); + $this->payload .= '' . $this->methodname . "\n"; + $this->payload .= "\n"; + for ($i = 0; $i < sizeof($this->params); $i++) { + $p = $this->params[$i]; + $this->payload .= "\n" . $p->serialize() . "\n"; + } + $this->payload .= "\n"; + $this->payload .= $this->xml_footer(); + if ($this->remove_extra_lines) { + $this->payload = $GLOBALS['XML_RPC_func_ereg_replace']("[\r\n]+", "\r\n", $this->payload); + } else { + $this->payload = $GLOBALS['XML_RPC_func_ereg_replace']("\r\n|\n|\r|\n\r", "\r\n", $this->payload); + } + if ($this->convert_payload_encoding) { + $this->payload = mb_convert_encoding($this->payload, $this->send_encoding); + } + } + + /** + * @return string the name of the method + */ + function method($meth = '') + { + if ($meth != '') { + $this->methodname = $meth; + } + return $this->methodname; + } + + /** + * @return string the payload + */ + function serialize() + { + $this->createPayload(); + return $this->payload; + } + + /** + * @return void + */ + function addParam($par) + { + $this->params[] = $par; + } + + /** + * Obtains an XML_RPC_Value object for the given parameter + * + * @param int $i the index number of the parameter to obtain + * + * @return object the XML_RPC_Value object. + * If the parameter doesn't exist, an XML_RPC_Response object. + * + * @since Returns XML_RPC_Response object on error since Release 1.3.0 + */ + function getParam($i) + { + global $XML_RPC_err, $XML_RPC_str; + + if (isset($this->params[$i])) { + return $this->params[$i]; + } else { + $this->raiseError('The submitted request did not contain this parameter', + XML_RPC_ERROR_INCORRECT_PARAMS); + return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], + $XML_RPC_str['incorrect_params']); + } + } + + /** + * @return int the number of parameters + */ + function getNumParams() + { + return sizeof($this->params); + } + + /** + * Sets whether the payload's content gets passed through + * mb_convert_encoding() + * + * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + * + * @see XML_RPC_Message::setSendEncoding() + * @since Method available since Release 1.5.1 + */ + function setConvertPayloadEncoding($in) + { + if ($in && !function_exists('mb_convert_encoding')) { + return $this->raiseError('mb_convert_encoding() is not available', + XML_RPC_ERROR_PROGRAMMING); + } + $this->convert_payload_encoding = $in; + } + + /** + * Sets the XML declaration's encoding attribute + * + * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII) + * + * @return void + * + * @see XML_RPC_Message::setConvertPayloadEncoding(), XML_RPC_Message::xml_header() + * @since Method available since Release 1.2.0 + */ + function setSendEncoding($type) + { + $this->send_encoding = $type; + } + + /** + * Determine the XML's encoding via the encoding attribute + * in the XML declaration + * + * If the encoding parameter is not set or is not ISO-8859-1, UTF-8 + * or US-ASCII, $XML_RPC_defencoding will be returned. + * + * @param string $data the XML that will be parsed + * + * @return string the encoding to be used + * + * @link http://php.net/xml_parser_create + * @since Method available since Release 1.2.0 + */ + function getEncoding($data) + { + global $XML_RPC_defencoding; + + if ($GLOBALS['XML_RPC_func_ereg']('<\?xml[^>]*[:space:]*encoding[:space:]*=[:space:]*[\'"]([^"\']*)[\'"]', + $data, $match)) + { + $match[1] = trim(strtoupper($match[1])); + switch ($match[1]) { + case 'ISO-8859-1': + case 'UTF-8': + case 'US-ASCII': + return $match[1]; + break; + + default: + return $XML_RPC_defencoding; + } + } else { + return $XML_RPC_defencoding; + } + } + + /** + * @return object a new XML_RPC_Response object + */ + function parseResponseFile($fp) + { + $ipd = ''; + while ($data = @fread($fp, 8192)) { + $ipd .= $data; + } + return $this->parseResponse($ipd); + } + + /** + * @return object a new XML_RPC_Response object + */ + function parseResponse($data = '') + { + global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding; + + $encoding = $this->getEncoding($data); + $parser_resource = xml_parser_create($encoding); + $parser = (int) $parser_resource; + + $XML_RPC_xh = array(); + $XML_RPC_xh[$parser] = array(); + + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = ''; + $XML_RPC_xh[$parser]['stack'] = array(); + $XML_RPC_xh[$parser]['valuestack'] = array(); + + xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); + xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); + + $hdrfnd = 0; + if ($this->debug) { + print "\n
---GOT---\n";
+            print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
+            print "\n---END---
\n"; + } + + // See if response is a 200 or a 100 then a 200, else raise error. + // But only do this if we're using the HTTP protocol. + if ($GLOBALS['XML_RPC_func_ereg']('^HTTP', $data) && + !$GLOBALS['XML_RPC_func_ereg']('^HTTP/[0-9\.]+ 200 ', $data) && + !$GLOBALS['XML_RPC_func_ereg']('^HTTP/[0-9\.]+ 10[0-9]([A-Z ]+)?[\r\n]+HTTP/[0-9\.]+ 200', $data)) + { + $errstr = substr($data, 0, strpos($data, "\n") - 1); + error_log('HTTP error, got response: ' . $errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'], + $XML_RPC_str['http_error'] . ' (' . + $errstr . ')'); + xml_parser_free($parser_resource); + return $r; + } + + // gotta get rid of headers here + if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) { + $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos); + $data = substr($data, $brpos + 4); + $hdrfnd = 1; + } + + /* + * be tolerant of junk after methodResponse + * (e.g. javascript automatically inserted by free hosts) + * thanks to Luca Mariano + */ + $data = substr($data, 0, strpos($data, "") + 17); + $this->response_payload = $data; + + if (!xml_parse($parser_resource, $data, sizeof($data))) { + // thanks to Peter Kocks + if (xml_get_current_line_number($parser_resource) == 1) { + $errstr = 'XML error at line 1, check URL'; + } else { + $errstr = sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser_resource)), + xml_get_current_line_number($parser_resource)); + } + error_log($errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return']); + xml_parser_free($parser_resource); + return $r; + } + + xml_parser_free($parser_resource); + + if ($this->debug) { + print "\n
---PARSED---\n";
+            var_dump($XML_RPC_xh[$parser]['value']);
+            print "---END---
\n"; + } + + if ($XML_RPC_xh[$parser]['isf'] > 1) { + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return'].' '.$XML_RPC_xh[$parser]['isf_reason']); + } elseif (!is_object($XML_RPC_xh[$parser]['value'])) { + // then something odd has happened + // and it's time to generate a client side error + // indicating something odd went on + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return']); + } else { + $v = $XML_RPC_xh[$parser]['value']; + if ($XML_RPC_xh[$parser]['isf']) { + $f = $v->structmem('faultCode'); + $fs = $v->structmem('faultString'); + $r = new XML_RPC_Response($v, $f->scalarval(), + $fs->scalarval()); + } else { + $r = new XML_RPC_Response($v); + } + } + $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]); + return $r; + } +} + +/** + * The methods and properties that represent data in XML RPC format + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Value extends XML_RPC_Base +{ + var $me = array(); + var $mytype = 0; + + /** + * @return void + */ + function XML_RPC_Value($val = -1, $type = '') + { + $this->me = array(); + $this->mytype = 0; + if ($val != -1 || $type != '') { + if ($type == '') { + $type = 'string'; + } + if (!array_key_exists($type, $GLOBALS['XML_RPC_Types'])) { + // XXX + // need some way to report this error + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 1) { + $this->addScalar($val, $type); + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 2) { + $this->addArray($val); + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 3) { + $this->addStruct($val); + } + } + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addScalar($val, $type = 'string') + { + if ($this->mytype == 1) { + $this->raiseError('Scalar can have only one value', + XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + $typeof = $GLOBALS['XML_RPC_Types'][$type]; + if ($typeof != 1) { + $this->raiseError("Not a scalar type (${typeof})", + XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + + if ($type == $GLOBALS['XML_RPC_Boolean']) { + if (strcasecmp($val, 'true') == 0 + || $val == 1 + || ($val == true && strcasecmp($val, 'false'))) + { + $val = 1; + } else { + $val = 0; + } + } + + if ($this->mytype == 2) { + // we're adding to an array here + $ar = $this->me['array']; + $ar[] = new XML_RPC_Value($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; + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addArray($vals) + { + if ($this->mytype != 0) { + $this->raiseError( + 'Already initialized as a [' . $this->kindOf() . ']', + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $GLOBALS['XML_RPC_Types']['array']; + $this->me['array'] = $vals; + return 1; + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addStruct($vals) + { + if ($this->mytype != 0) { + $this->raiseError( + 'Already initialized as a [' . $this->kindOf() . ']', + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $GLOBALS['XML_RPC_Types']['struct']; + $this->me['struct'] = $vals; + return 1; + } + + /** + * @return void + */ + function dump($ar) + { + reset($ar); + foreach ($ar as $key => $val) { + echo "$key => $val
"; + if ($key == 'array') { + foreach ($val as $key2 => $val2) { + echo "-- $key2 => $val2
"; + } + } + } + } + + /** + * @return string the data type of the current value + */ + function kindOf() + { + switch ($this->mytype) { + case 3: + return 'struct'; + + case 2: + return 'array'; + + case 1: + return 'scalar'; + + default: + return 'undef'; + } + } + + /** + * @return string the data in XML format + */ + function serializedata($typ, $val) + { + $rs = ''; + if (!array_key_exists($typ, $GLOBALS['XML_RPC_Types'])) { + // XXX + // need some way to report this error + return; + } + switch ($GLOBALS['XML_RPC_Types'][$typ]) { + case 3: + // struct + $rs .= "\n"; + reset($val); + foreach ($val as $key2 => $val2) { + $rs .= "${key2}\n"; + $rs .= $this->serializeval($val2); + $rs .= "\n"; + } + $rs .= ''; + break; + + case 2: + // array + $rs .= "\n\n"; + for ($i = 0; $i < sizeof($val); $i++) { + $rs .= $this->serializeval($val[$i]); + } + $rs .= "\n"; + break; + + case 1: + switch ($typ) { + case $GLOBALS['XML_RPC_Base64']: + $rs .= "<${typ}>" . base64_encode($val) . ""; + break; + case $GLOBALS['XML_RPC_Boolean']: + $rs .= "<${typ}>" . ($val ? '1' : '0') . ""; + break; + case $GLOBALS['XML_RPC_String']: + $rs .= "<${typ}>" . htmlspecialchars($val). ""; + break; + default: + $rs .= "<${typ}>${val}"; + } + } + return $rs; + } + + /** + * @return string the data in XML format + */ + function serialize() + { + return $this->serializeval($this); + } + + /** + * @return string the data in XML format + */ + function serializeval($o) + { + if (!is_object($o) || empty($o->me) || !is_array($o->me)) { + return ''; + } + $ar = $o->me; + reset($ar); + list($typ, $val) = each($ar); + return '' . $this->serializedata($typ, $val) . "\n"; + } + + /** + * @return mixed the contents of the element requested + */ + function structmem($m) + { + return $this->me['struct'][$m]; + } + + /** + * @return void + */ + function structreset() + { + reset($this->me['struct']); + } + + /** + * @return the key/value pair of the struct's current element + */ + function structeach() + { + return each($this->me['struct']); + } + + /** + * @return mixed the current value + */ + function getval() + { + // UNSTABLE + + reset($this->me); + $b = current($this->me); + + // contributed by I Sofer, 2001-03-24 + // add support for nested arrays to scalarval + // i've created a new method here, so as to + // preserve back compatibility + + if (is_array($b)) { + foreach ($b as $id => $cont) { + $b[$id] = $cont->scalarval(); + } + } + + // add support for structures directly encoding php objects + if (is_object($b)) { + $t = get_object_vars($b); + foreach ($t as $id => $cont) { + $t[$id] = $cont->scalarval(); + } + foreach ($t as $id => $cont) { + $b->$id = $cont; + } + } + + // end contrib + return $b; + } + + /** + * @return mixed the current element's scalar value. If the value is + * not scalar, FALSE is returned. + */ + function scalarval() + { + reset($this->me); + $v = current($this->me); + if (!is_scalar($v)) { + $v = false; + } + return $v; + } + + /** + * @return string + */ + function scalartyp() + { + reset($this->me); + $a = key($this->me); + if ($a == $GLOBALS['XML_RPC_I4']) { + $a = $GLOBALS['XML_RPC_Int']; + } + return $a; + } + + /** + * @return mixed the struct's current element + */ + function arraymem($m) + { + return $this->me['array'][$m]; + } + + /** + * @return int the number of elements in the array + */ + function arraysize() + { + reset($this->me); + list($a, $b) = each($this->me); + return sizeof($b); + } + + /** + * Determines if the item submitted is an XML_RPC_Value object + * + * @param mixed $val the variable to be evaluated + * + * @return bool TRUE if the item is an XML_RPC_Value object + * + * @static + * @since Method available since Release 1.3.0 + */ + function isValue($val) + { + return (strtolower(get_class($val)) == 'xml_rpc_value'); + } +} + +/** + * Return an ISO8601 encoded string + * + * While timezones ought to be supported, the XML-RPC spec says: + * + * "Don't assume a timezone. It should be specified by the server in its + * documentation what assumptions it makes about timezones." + * + * This routine always assumes localtime unless $utc is set to 1, in which + * case UTC is assumed and an adjustment for locale is made when encoding. + * + * @return string the formatted date + */ +function XML_RPC_iso8601_encode($timet, $utc = 0) +{ + if (!$utc) { + $t = strftime('%Y%m%dT%H:%M:%S', $timet); + } else { + if (function_exists('gmstrftime')) { + // gmstrftime doesn't exist in some versions + // of PHP + $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet); + } else { + $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z')); + } + } + return $t; +} + +/** + * Convert a datetime string into a Unix timestamp + * + * While timezones ought to be supported, the XML-RPC spec says: + * + * "Don't assume a timezone. It should be specified by the server in its + * documentation what assumptions it makes about timezones." + * + * This routine always assumes localtime unless $utc is set to 1, in which + * case UTC is assumed and an adjustment for locale is made when encoding. + * + * @return int the unix timestamp of the date submitted + */ +function XML_RPC_iso8601_decode($idate, $utc = 0) +{ + $t = 0; + if ($GLOBALS['XML_RPC_func_ereg']('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) { + if ($utc) { + $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } else { + $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } + } + return $t; +} + +/** + * Converts an XML_RPC_Value object into native PHP types + * + * @param object $XML_RPC_val the XML_RPC_Value object to decode + * + * @return mixed the PHP values + */ +function XML_RPC_decode($XML_RPC_val) +{ + $kind = $XML_RPC_val->kindOf(); + + if ($kind == 'scalar') { + return $XML_RPC_val->scalarval(); + + } elseif ($kind == 'array') { + $size = $XML_RPC_val->arraysize(); + $arr = array(); + for ($i = 0; $i < $size; $i++) { + $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i)); + } + return $arr; + + } elseif ($kind == 'struct') { + $XML_RPC_val->structreset(); + $arr = array(); + while (list($key, $value) = $XML_RPC_val->structeach()) { + $arr[$key] = XML_RPC_decode($value); + } + return $arr; + } +} + +/** + * Converts native PHP types into an XML_RPC_Value object + * + * @param mixed $php_val the PHP value or variable you want encoded + * + * @return object the XML_RPC_Value object + */ +function XML_RPC_encode($php_val) +{ + $type = gettype($php_val); + $XML_RPC_val = new XML_RPC_Value; + + switch ($type) { + case 'array': + if (empty($php_val)) { + $XML_RPC_val->addArray($php_val); + break; + } + $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1)); + if (empty($tmp)) { + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addArray($arr); + break; + } + // fall though if it's not an enumerated array + + case 'object': + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addStruct($arr); + break; + + case 'integer': + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Int']); + break; + + case 'double': + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Double']); + break; + + case 'string': + case 'NULL': + if ($GLOBALS['XML_RPC_func_ereg']('^[0-9]{8}\T{1}[0-9]{2}\:[0-9]{2}\:[0-9]{2}$', $php_val)) { + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_DateTime']); + } elseif ($GLOBALS['XML_RPC_auto_base64'] + && $GLOBALS['XML_RPC_func_ereg']("[^ -~\t\r\n]", $php_val)) + { + // Characters other than alpha-numeric, punctuation, SP, TAB, + // LF and CR break the XML parser, encode value via Base 64. + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Base64']); + } else { + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_String']); + } + break; + + case 'boolean': + // Add support for encoding/decoding of booleans, since they + // are supported in PHP + // by + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Boolean']); + break; + + case 'unknown type': + default: + $XML_RPC_val = false; + } + return $XML_RPC_val; +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/lib/Pear/XML/RPC/Dump.php b/lib/Pear/XML/RPC/Dump.php new file mode 100644 index 0000000..34ebde6 --- /dev/null +++ b/lib/Pear/XML/RPC/Dump.php @@ -0,0 +1,187 @@ + + * @version CVS: $Id: Dump.php 178076 2005-01-24 03:47:55Z danielc $ + * @link http://pear.php.net/package/XML_RPC + */ + + +/** + * Pull in the XML_RPC class + */ +require_once 'XML/RPC.php'; + + +/** + * Generates the dump of the XML_RPC_Value and echoes it + * + * @param object $value the XML_RPC_Value object to dump + * + * @return void + */ +function XML_RPC_Dump($value) +{ + $dumper = new XML_RPC_Dump(); + echo $dumper->generateDump($value); +} + + +/** + * Class which generates a dump of a XML_RPC_Value object + * + * @category Web Services + * @package XML_RPC + * @author Christian Weiske + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Dump +{ + /** + * The indentation array cache + * @var array + */ + var $arIndent = array(); + + /** + * The spaces used for indenting the XML + * @var string + */ + var $strBaseIndent = ' '; + + /** + * Returns the dump in XML format without printing it out + * + * @param object $value the XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string the dump + */ + function generateDump($value, $nLevel = 0) + { + if (!is_object($value) && get_class($value) != 'xml_rpc_value') { + require_once 'PEAR.php'; + PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n", + 0, PEAR_ERROR_PRINT); + if (is_object($value)) { + $strType = get_class($value); + } else { + $strType = gettype($value); + } + return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: ' + . $strType . "\r\n"; + } + + switch ($value->kindOf()) { + case 'struct': + $ret = $this->genStruct($value, $nLevel); + break; + case 'array': + $ret = $this->genArray($value, $nLevel); + break; + case 'scalar': + $ret = $this->genScalar($value->scalarval(), $nLevel); + break; + default: + require_once 'PEAR.php'; + PEAR::raiseError('Illegal type "' . $value->kindOf() + . '" in XML_RPC_Value' . "\r\n", 0, + PEAR_ERROR_PRINT); + } + + return $ret; + } + + /** + * Returns the scalar value dump + * + * @param object $value the scalar XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genScalar($value, $nLevel) + { + if (gettype($value) == 'object') { + $strClass = ' ' . get_class($value); + } else { + $strClass = ''; + } + return $this->getIndent($nLevel) . gettype($value) . $strClass + . ' ' . $value . "\r\n"; + } + + /** + * Returns the dump of a struct + * + * @param object $value the struct XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genStruct($value, $nLevel) + { + $value->structreset(); + $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n"; + while (list($key, $keyval) = $value->structeach()) { + $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n"; + $strOutput .= $this->generateDump($keyval, $nLevel + 2); + } + return $strOutput; + } + + /** + * Returns the dump of an array + * + * @param object $value the array XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genArray($value, $nLevel) + { + $nSize = $value->arraysize(); + $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n"; + for($nA = 0; $nA < $nSize; $nA++) { + $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n"; + $strOutput .= $this->generateDump($value->arraymem($nA), + $nLevel + 2); + } + return $strOutput; + } + + /** + * Returns the indent for a specific level and caches it for faster use + * + * @param int $nLevel the level + * + * @return string the indented string + */ + function getIndent($nLevel) + { + if (!isset($this->arIndent[$nLevel])) { + $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel); + } + return $this->arIndent[$nLevel]; + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/lib/Pear/XML/RPC/Server.php b/lib/Pear/XML/RPC/Server.php new file mode 100644 index 0000000..f6fb117 --- /dev/null +++ b/lib/Pear/XML/RPC/Server.php @@ -0,0 +1,685 @@ + + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version CVS: $Id: Server.php 222479 2006-10-28 16:42:34Z danielc $ + * @link http://pear.php.net/package/XML_RPC + */ + + +/** + * Pull in the XML_RPC class + */ +require_once 'XML/RPC.php'; + + +/** + * signature for system.listMethods: return = array, + * parameters = a string or nothing + * @global array $GLOBALS['XML_RPC_Server_listMethods_sig'] + */ +$GLOBALS['XML_RPC_Server_listMethods_sig'] = array( + array($GLOBALS['XML_RPC_Array'], + $GLOBALS['XML_RPC_String'] + ), + array($GLOBALS['XML_RPC_Array']) +); + +/** + * docstring for system.listMethods + * @global string $GLOBALS['XML_RPC_Server_listMethods_doc'] + */ +$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the' + . ' methods that the XML-RPC server knows how to dispatch'; + +/** + * signature for system.methodSignature: return = array, + * parameters = string + * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig'] + */ +$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array( + array($GLOBALS['XML_RPC_Array'], + $GLOBALS['XML_RPC_String'] + ) +); + +/** + * docstring for system.methodSignature + * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc'] + */ +$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known' + . ' signatures (an array of arrays) for the method name passed. If' + . ' no signatures are known, returns a none-array (test for type !=' + . ' array to detect missing signature)'; + +/** + * signature for system.methodHelp: return = string, + * parameters = string + * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig'] + */ +$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array( + array($GLOBALS['XML_RPC_String'], + $GLOBALS['XML_RPC_String'] + ) +); + +/** + * docstring for methodHelp + * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc'] + */ +$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined' + . ' for the method passed, otherwise returns an empty string'; + +/** + * dispatch map for the automatically declared XML-RPC methods. + * @global array $GLOBALS['XML_RPC_Server_dmap'] + */ +$GLOBALS['XML_RPC_Server_dmap'] = array( + 'system.listMethods' => array( + 'function' => 'XML_RPC_Server_listMethods', + 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc'] + ), + 'system.methodHelp' => array( + 'function' => 'XML_RPC_Server_methodHelp', + 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc'] + ), + 'system.methodSignature' => array( + 'function' => 'XML_RPC_Server_methodSignature', + 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc'] + ) +); + +/** + * @global string $GLOBALS['XML_RPC_Server_debuginfo'] + */ +$GLOBALS['XML_RPC_Server_debuginfo'] = ''; + + +/** + * Lists all the methods that the XML-RPC server knows how to dispatch + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_listMethods($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $v = new XML_RPC_Value(); + $outAr = array(); + foreach ($server->dmap as $key => $val) { + $outAr[] = new XML_RPC_Value($key, 'string'); + } + foreach ($XML_RPC_Server_dmap as $key => $val) { + $outAr[] = new XML_RPC_Value($key, 'string'); + } + $v->addArray($outAr); + return new XML_RPC_Response($v); +} + +/** + * Returns an array of known signatures (an array of arrays) + * for the given method + * + * If no signatures are known, returns a none-array + * (test for type != array to detect missing signature) + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_methodSignature($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + // print "\n"; + if (isset($dmap[$methName])) { + if ($dmap[$methName]['signature']) { + $sigs = array(); + $thesigs = $dmap[$methName]['signature']; + for ($i = 0; $i < sizeof($thesigs); $i++) { + $cursig = array(); + $inSig = $thesigs[$i]; + for ($j = 0; $j < sizeof($inSig); $j++) { + $cursig[] = new XML_RPC_Value($inSig[$j], 'string'); + } + $sigs[] = new XML_RPC_Value($cursig, 'array'); + } + $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array')); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string')); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], + $XML_RPC_str['introspect_unknown']); + } + return $r; +} + +/** + * Returns help text if defined for the method passed, otherwise returns + * an empty string + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_methodHelp($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + + if (isset($dmap[$methName])) { + if ($dmap[$methName]['docstring']) { + $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']), + 'string'); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value('', 'string')); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], + $XML_RPC_str['introspect_unknown']); + } + return $r; +} + +/** + * @return void + */ +function XML_RPC_Server_debugmsg($m) +{ + global $XML_RPC_Server_debuginfo; + $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n"; +} + + +/** + * A server for receiving and replying to XML RPC requests + * + * + * $server = new XML_RPC_Server( + * array( + * 'isan8' => + * array( + * 'function' => 'is_8', + * 'signature' => + * array( + * array('boolean', 'int'), + * array('boolean', 'int', 'boolean'), + * array('boolean', 'string'), + * array('boolean', 'string', 'boolean'), + * ), + * 'docstring' => 'Is the value an 8?' + * ), + * ), + * 1, + * 0 + * ); + * + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.2 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Server +{ + /** + * Should the payload's content be passed through mb_convert_encoding()? + * + * @see XML_RPC_Server::setConvertPayloadEncoding() + * @since Property available since Release 1.5.1 + * @var boolean + */ + var $convert_payload_encoding = false; + + /** + * The dispatch map, listing the methods this server provides. + * @var array + */ + var $dmap = array(); + + /** + * The present response's encoding + * @var string + * @see XML_RPC_Message::getEncoding() + */ + var $encoding = ''; + + /** + * Debug mode (0 = off, 1 = on) + * @var integer + */ + var $debug = 0; + + /** + * The response's HTTP headers + * @var string + */ + var $server_headers = ''; + + /** + * The response's XML payload + * @var string + */ + var $server_payload = ''; + + + /** + * Constructor for the XML_RPC_Server class + * + * @param array $dispMap the dispatch map. An associative array + * explaining each function. The keys of the main + * array are the procedure names used by the + * clients. The value is another associative array + * that contains up to three elements: + * + The 'function' element's value is the name + * of the function or method that gets called. + * To define a class' method: 'class::method'. + * + The 'signature' element (optional) is an + * array describing the return values and + * parameters + * + The 'docstring' element (optional) is a + * string describing what the method does + * @param int $serviceNow should the HTTP response be sent now? + * (1 = yes, 0 = no) + * @param int $debug should debug output be displayed? + * (1 = yes, 0 = no) + * + * @return void + */ + function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0) + { + global $HTTP_RAW_POST_DATA; + + if ($debug) { + $this->debug = 1; + } else { + $this->debug = 0; + } + + $this->dmap = $dispMap; + + if ($serviceNow) { + $this->service(); + } else { + $this->createServerPayload(); + $this->createServerHeaders(); + } + } + + /** + * @return string the debug information if debug debug mode is on + */ + function serializeDebug() + { + global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA; + + if ($this->debug) { + XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n" + . $HTTP_RAW_POST_DATA + . "\n" . '^^^ END POST DATA ^^^'); + } + + if ($XML_RPC_Server_debuginfo != '') { + return "\n"; + } else { + return ''; + } + } + + /** + * Sets whether the payload's content gets passed through + * mb_convert_encoding() + * + * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + * + * @see XML_RPC_Message::getEncoding() + * @since Method available since Release 1.5.1 + */ + function setConvertPayloadEncoding($in) + { + if ($in && !function_exists('mb_convert_encoding')) { + return $this->raiseError('mb_convert_encoding() is not available', + XML_RPC_ERROR_PROGRAMMING); + } + $this->convert_payload_encoding = $in; + } + + /** + * Sends the response + * + * The encoding and content-type are determined by + * XML_RPC_Message::getEncoding() + * + * @return void + * + * @uses XML_RPC_Server::createServerPayload(), + * XML_RPC_Server::createServerHeaders() + */ + function service() + { + if (!$this->server_payload) { + $this->createServerPayload(); + } + if (!$this->server_headers) { + $this->createServerHeaders(); + } + + /* + * $server_headers needs to remain a string for compatibility with + * old scripts using this package, but PHP 4.4.2 no longer allows + * line breaks in header() calls. So, we split each header into + * an individual call. The initial replace handles the off chance + * that someone composed a single header with multiple lines, which + * the RFCs allow. + */ + $this->server_headers = $GLOBALS['XML_RPC_func_ereg_replace']("[\r\n]+[ \t]+", + ' ', trim($this->server_headers)); + $headers = $GLOBALS['XML_RPC_func_split']("[\r\n]+", $this->server_headers); + foreach ($headers as $header) + { + header($header); + } + + print $this->server_payload; + } + + /** + * Generates the payload and puts it in the $server_payload property + * + * If XML_RPC_Server::setConvertPayloadEncoding() was set to true, + * the payload gets passed through mb_convert_encoding() + * to ensure the payload matches the encoding set in the + * XML declaration. The encoding type can be manually set via + * XML_RPC_Message::setSendEncoding(). + * + * @return void + * + * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding, + * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug() + * @see XML_RPC_Server::setConvertPayloadEncoding() + */ + function createServerPayload() + { + $r = $this->parseRequest(); + $this->server_payload = 'encoding . '"?>' . "\n" + . $this->serializeDebug() + . $r->serialize(); + if ($this->convert_payload_encoding) { + $this->server_payload = mb_convert_encoding($this->server_payload, + $this->encoding); + } + } + + /** + * Determines the HTTP headers and puts them in the $server_headers + * property + * + * @return boolean TRUE if okay, FALSE if $server_payload isn't set. + * + * @uses XML_RPC_Server::createServerPayload(), + * XML_RPC_Server::$server_headers + */ + function createServerHeaders() + { + if (!$this->server_payload) { + return false; + } + $this->server_headers = 'Content-Length: ' + . strlen($this->server_payload) . "\r\n" + . 'Content-Type: text/xml;' + . ' charset=' . $this->encoding; + return true; + } + + /** + * @return array + */ + function verifySignature($in, $sig) + { + for ($i = 0; $i < sizeof($sig); $i++) { + // check each possible signature in turn + $cursig = $sig[$i]; + if (sizeof($cursig) == $in->getNumParams() + 1) { + $itsOK = 1; + for ($n = 0; $n < $in->getNumParams(); $n++) { + $p = $in->getParam($n); + // print "\n"; + if ($p->kindOf() == 'scalar') { + $pt = $p->scalartyp(); + } else { + $pt = $p->kindOf(); + } + // $n+1 as first type of sig is return type + if ($pt != $cursig[$n+1]) { + $itsOK = 0; + $pno = $n+1; + $wanted = $cursig[$n+1]; + $got = $pt; + break; + } + } + if ($itsOK) { + return array(1); + } + } + } + if (isset($wanted)) { + return array(0, "Wanted ${wanted}, got ${got} at param ${pno}"); + } else { + $allowed = array(); + foreach ($sig as $val) { + end($val); + $allowed[] = key($val); + } + $allowed = array_unique($allowed); + $last = count($allowed) - 1; + if ($last > 0) { + $allowed[$last] = 'or ' . $allowed[$last]; + } + return array(0, + 'Signature permits ' . implode(', ', $allowed) + . ' parameters but the request had ' + . $in->getNumParams()); + } + } + + /** + * @return object a new XML_RPC_Response object + * + * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding + */ + function parseRequest($data = '') + { + global $XML_RPC_xh, $HTTP_RAW_POST_DATA, + $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, + $XML_RPC_defencoding, $XML_RPC_Server_dmap; + + if ($data == '') { + $data = $HTTP_RAW_POST_DATA; + } + + $this->encoding = XML_RPC_Message::getEncoding($data); + $parser_resource = xml_parser_create($this->encoding); + $parser = (int) $parser_resource; + + $XML_RPC_xh[$parser] = array(); + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['params'] = array(); + $XML_RPC_xh[$parser]['method'] = ''; + $XML_RPC_xh[$parser]['stack'] = array(); + $XML_RPC_xh[$parser]['valuestack'] = array(); + + $plist = ''; + + // decompose incoming XML into request structure + + xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); + xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); + if (!xml_parse($parser_resource, $data, 1)) { + // return XML error as a faultCode + $r = new XML_RPC_Response(0, + $XML_RPC_errxml+xml_get_error_code($parser_resource), + sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser_resource)), + xml_get_current_line_number($parser_resource))); + xml_parser_free($parser_resource); + } elseif ($XML_RPC_xh[$parser]['isf']>1) { + $r = new XML_RPC_Response(0, + $XML_RPC_err['invalid_request'], + $XML_RPC_str['invalid_request'] + . ': ' + . $XML_RPC_xh[$parser]['isf_reason']); + xml_parser_free($parser_resource); + } else { + xml_parser_free($parser_resource); + $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']); + // now add parameters in + for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { + // print '\n"; + $plist .= "$i - " . var_export($XML_RPC_xh[$parser]['params'][$i], true) . " \n"; + $m->addParam($XML_RPC_xh[$parser]['params'][$i]); + } + + if ($this->debug) { + XML_RPC_Server_debugmsg($plist); + } + + // now to deal with the method + $methName = $XML_RPC_xh[$parser]['method']; + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $this->dmap; + $sysCall = 0; + } + + if (isset($dmap[$methName]['function']) + && is_string($dmap[$methName]['function']) + && strpos($dmap[$methName]['function'], '::') !== false) + { + $dmap[$methName]['function'] = + explode('::', $dmap[$methName]['function']); + } + + if (isset($dmap[$methName]['function']) + && is_callable($dmap[$methName]['function'])) + { + // dispatch if exists + if (isset($dmap[$methName]['signature'])) { + $sr = $this->verifySignature($m, + $dmap[$methName]['signature'] ); + } + if (!isset($dmap[$methName]['signature']) || $sr[0]) { + // if no signature or correct signature + if ($sysCall) { + $r = call_user_func($dmap[$methName]['function'], $this, $m); + } else { + $r = call_user_func($dmap[$methName]['function'], $m); + } + if (!is_a($r, 'XML_RPC_Response')) { + $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'], + $XML_RPC_str['not_response_object']); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], + $XML_RPC_str['incorrect_params'] + . ': ' . $sr[1]); + } + } else { + // else prepare error response + $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'], + $XML_RPC_str['unknown_method']); + } + } + return $r; + } + + /** + * Echos back the input packet as a string value + * + * @return void + * + * Useful for debugging. + */ + function echoInput() + { + global $HTTP_RAW_POST_DATA; + + $r = new XML_RPC_Response(0); + $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string'); + print $r->serialize(); + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/lib/authUtil.php b/lib/authUtil.php new file mode 100644 index 0000000..55dafc8 --- /dev/null +++ b/lib/authUtil.php @@ -0,0 +1,372 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'dbUtil.php'; +require_once 'logUtil.php'; + +/** + * Authentication Class + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class AuthUtil +{ + + //The default authentication method to use + private $_auth_default; + + //Enable fallback authentication + private $_auth_fallback; + + // {{{ constructor + /** + * ldapUtil Class constructor. + * This flavour of the constructor only enable logging + * identifying it by the name of the class file. + * + * @access public + */ + function authUtil() + { + $this->logger = new LogUtil('authUtil.php'); + //Roles in according with the values defined in the db + if (isset($GLOBALS['conf']['xmlrpc']['timeout'])) { + $this->session_expire = $GLOBALS['conf']['xmlrpc']['timeout']; + } else { + $this->session_expire = 3600; + } + + if (isset($GLOBALS['conf']['auth'])) { + $this->_auth_default = $GLOBALS['conf']['auth']['default']; + $this->_auth_fallback = $GLOBALS['conf']['auth']['fallback']; + } + $this->_id = $GLOBALS['conf']['id']; + + define('ADMIN', '1'); + define('SYSTEM_ADMIN', '2'); + define('GUEST', '3'); + define('SYSTEM_GUEST', '4'); + } + // }}} + + /** + * Return the default authentication method + * + * @return string + * @access public + */ + public function getDefaultAuthMethod() { + return $this->_auth_default; + } + + /** + * Retrieve the list of available methods for authenticate user in ortro + * + * @return array Available methods + */ + public static function getAvailableAuthMethods() { + $ortro_auth_methods['MDB2'] = 'MDB2'; + if (extension_loaded('ldap')) { + $ortro_auth_methods['LDAP'] = 'LDAP'; + } + if (@include_once 'CAS.php') { + $ortro_auth_methods['CAS'] = 'CAS'; + } + return $ortro_auth_methods; + } + + /** + * Register additional information that is to be stored + * in the session. + * + * @param string Name of the data field + * @param mixed Value of the data field + * @return void + * @access public + */ + public static function isAuthorized() { + if (isset($_SESSION[$GLOBALS['conf']['id']]['userid'])) { + return true; + } + return false; + } + + /** + * Register additional information that is to be stored + * in the session. + * + * @param string Name of the data field + * @param mixed Value of the data field + * @return void + * @access public + */ + public static function setSessionData($key, $value) { + $_SESSION[$GLOBALS['conf']['id']][$key] = $value; + } + + /** + * Get information that is stored in the session. + * + * @param string Name of the data field + * @return mixed Value of the data field. + * @access public + */ + public static function getSessionData($key) { + if (isset($_SESSION[$GLOBALS['conf']['id']][$key])) { + return $_SESSION[$GLOBALS['conf']['id']][$key]; + } + return false; + } + + /** + * Logout function + * + * @return void + */ + function logout() + { + unset($_SESSION[$this->_id]); + } + + /** + * Login function + * + * @param string $username The username + * @param string $password The password + * + * @return mixed return an array with the user info on success or a PEAR_Error + */ + function login($username, $password) + { + require_once 'Pear/Auth.php'; + + $this->logger->trace('DEBUG', "Trying login for user: " . $username); + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConnOrtro(); + + $options = array(); + + $options_default = array('sessionName'=>$this->_id); + + $options_mdb2 = array('dsn' => $dbUtil->getDSN(), + 'table' => $dbUtil->setTablePrefix('users'), + 'usernamecol' => 'username', + 'passwordcol' => 'password', + ); + + switch ($this->_auth_default) { + case 'MDB2': + $options = array_merge($options_mdb2, $options_default); + break; + + case 'LDAP': + require_once ORTRO_CONF . 'configure_ldap.php'; + $options_ldap = array('url' => $conf['ldap']['server'], + 'version' => 3, + 'basedn' => $conf['ldap']['base_dn'], + 'binddn' => $conf['ldap']['bind_dn'], + 'bindpw' => $conf['ldap']['bind_password'], + 'userattr' => $conf['ldap']['search_attribute_uid'], + 'userfilter' => '', + 'groupattr' => $conf['ldap']['search_attribute_cn'], + 'groupfilter' => '', + ); + $options = array_merge($options_ldap, $options_default); + break; + case 'CAS': + require_once ORTRO_CONF . 'configure_cas.php'; + $options_cas = array( + 'server_hostname' => $conf['cas']['server_hostname'], + 'server_port' => $conf['cas']['server_port'], + 'server_uri' => $conf['cas']['server_uri'], + 'curl_opt_ssl_version' => $conf['cas']['curl_opt_ssl_version'], + 'cas_server_validation' => $conf['cas']['cas_server_validation'], + ); + + $options = array_merge($options_cas, $options_default); + break; + } + + //Override $_POST variables required by Auth pear package. + $_POST['username'] = $username; + $_POST['password'] = $password; + + $_auth = new Auth($this->_auth_default, $options, '', false); + $_auth->start(); + + $login_result = false; + + if ($_auth->getAuth()) { + $login_result = true; + $username = $_auth->getUsername(); + } elseif ($this->_auth_default != 'MDB2' && $this->_auth_fallback) { + unset($_auth); + $this->logger->trace('DEBUG', "Trying db authentication for user: " . + $username); + $_auth = new Auth('MDB2', array_merge($options_mdb2, $options_default),'',false); + $_auth->start(); + if ($_auth->getAuth()) { + $login_result = true; + } + } + + if ($login_result){ + // Store the last access time + $dbUtil->dbExec($dbh, $dbUtil->setUserLastLogin($username, time())); + + $userInfo = $dbUtil->dbQuery($dbh, $dbUtil->getUserInfo($username), + MDB2_FETCHMODE_ASSOC); + if (count($userInfo) > 0) { + $this->setSessionData('userid', $userInfo[0]['id_user']); + if ($userInfo[0]['language'] != 'none') { + //Enable the user language preference. + $this->setSessionData('language', $userInfo[0]['language']); + } + $this->setSessionData('policy', $this->getPolicyRoles($userInfo)); + $login_result = true; + } else { + $login_result = false; + $this->logout(); + } + } + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + return $login_result; + } + + /** + * Get policy roles for the current user + * + * @param array $userInfos The infos for the current user + * + * @return array return an array with the correct policies + */ + function getPolicyRoles($userInfos) + { + $policy = array(); + $sys_admin = ''; + $sys_guest = ''; + foreach ($userInfos as $row) { + switch ($row['id_role']) { + case ADMIN: + $policy['ADMIN'] = '1'; + break; + break; + case SYSTEM_ADMIN: + if ($sys_admin == '') { + $sys_admin = $row['id_systems']; + } else { + $sys_admin .= ',' . $row['id_systems']; + } + break; + case GUEST: + $policy['GUEST'] = '1'; + break; + case SYSTEM_GUEST: + if ($sys_guest == '') { + $sys_guest = $row['id_systems']; + } else { + $sys_guest .= ',' . $row['id_systems']; + } + break; + } + } + + if ($policy['ADMIN'] != '1') { + if ($sys_admin != '') { + $policy['SYSTEM_ADMIN'] = $sys_admin; + } + if ($policy['GUEST'] != '1') { + $policy['SYSTEM_GUEST'] = $sys_guest; + } + } + + return $policy; + } + + /** + * Create a valid session id. + * + * @return string The session id + * + */ + function createSessionId() + { + session_start(); + $session_id = session_id(); + $auth_session_save_path = ORTRO_CONF . 'auth . DS'; + if (!is_dir(ORTRO_SESSION_SAVE_PATH)) { + @mkdir(ORTRO_SESSION_SAVE_PATH, 0700); + } + @touch(ORTRO_SESSION_SAVE_PATH . $session_id); + $this->destroySessionId(); + return $session_id; + } + + /** + * Check for a valid session id. + * + * @param string $session_id The session id + * + * @return boolean true on success + */ + function checkSessionId($session_id) + { + if (is_file(ORTRO_SESSION_SAVE_PATH . $session_id) && + fileatime(ORTRO_SESSION_SAVE_PATH . $session_id) > + time()-$this->session_expire) { + @touch(ORTRO_SESSION_SAVE_PATH . $session_id); + return true; + } else { + $this->destroySessionId(); + return false; + } + } + + /** + * Destroy a session id. + * + * @param string $session_id The session id (optional) + * + * @return boolean true on success + */ + function destroySessionId($session_id='') + { + if ($session_id == '') { + $dir_contents = scandir(ORTRO_SESSION_SAVE_PATH); + foreach ($dir_contents as $item) { + if (is_file(ORTRO_SESSION_SAVE_PATH.$item) && + fileatime(ORTRO_SESSION_SAVE_PATH . $item) < + time()-$this->session_expire && $item != '.' && $item != '..') { + @unlink(ORTRO_SESSION_SAVE_PATH.$item); + } + } + } else { + @unlink(ORTRO_SESSION_SAVE_PATH . $session_id); + } + return true; + } +} +?> diff --git a/lib/cronUtil.php b/lib/cronUtil.php new file mode 100644 index 0000000..29c40a7 --- /dev/null +++ b/lib/cronUtil.php @@ -0,0 +1,1076 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; +require_once 'dbUtil.php'; +require_once 'notifyUtil.php'; + +/** + * CronUtil Class + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class CronUtil +{ + private $requestType; + + /** + * CronUtil Class constructor. + * + * @param string $requestType The request type + * + * @return void + */ + function cronUtil($requestType = 'CRONTAB') + { + $this->logger = new LogUtil('cronUtil.php'); + $this->wf_logger = new LogUtil('cronUtil.php', ORTRO_LOG.'workflow'); + $this->requestType = $requestType; + } + + /** + * Get all info for the job requested by an XML-RPC call and execute it + * + * @param string $label The job label to execute + * + * @return string The job output + */ + function runJobRPC($label) + { + $this->logger->trace('DEBUG', + 'Start RPC job execution ' . $this->requestType); + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConnOrtro(); + + $rows = $dbUtil->dbQuery($dbh, + $dbUtil->getJobsToExecRPC($label), + MDB2_FETCHMODE_ASSOC); + + $ret = $this->execJob($rows[0]['id_job'], + $rows[0]['label'], + $rows[0]['category'], + 'XML-RPC'); + + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + $this->logger->trace('DEBUG', 'End RPC job execution'); + return $dbUtil->dbUnserialize($ret); + } + + /** + * Get all the scheduled jobs that must be executed and execute them + * + * @return void + */ + function runCron() + { + $this->logger->trace('DEBUG', '######################################'); + $this->logger->trace('DEBUG', 'Start crontab'); + $dbUtil = new DbUtil(); + + $dbh = $dbUtil->dbOpenConnOrtro(); + //Get all long running jobs + if ($GLOBALS['conf']['env']['job_timeout'] > 0) { + $long_run_jobs = $dbUtil->dbQuery($dbh, $dbUtil->getJobsTimeout()); + if (count($long_run_jobs) > 0) { + foreach ($long_run_jobs as $key=>$row) { + $this->logger->trace('DEBUG', + $log_prefix . + 'Attempt to kill zombie job: ' . $row[0]); + $this->killJob($row[0]); + $timeout_msg = 'Job execution timeout. Please contact administrator.'; + $dbUtil->dbExec($dbh, $dbUtil->setJobEnd($row[0], 0, $timeout_msg)); + } + } + } + //Get all available shd + $locked_shd_result = $dbUtil->dbQuery($dbh, $dbUtil->getLockedSystemHostDb()); + + $locked_shd = 0; + if (count($locked_shd_result)>0) { + foreach ($locked_shd_result as $key=>$row) { + $locked_shd_arr[] = $row[0]; + } + $locked_shd = implode(',', $locked_shd_arr); + } + + //Get all scheduled jobs as part of workwflow ready for execution + $rows_job_workflows = $dbUtil->dbQuery($dbh, + $dbUtil->getJobsWorkflowToExec($locked_shd), + MDB2_FETCHMODE_ASSOC); + //Get all scheduled workwflows ready for execution + $rows_workflows = $dbUtil->dbQuery($dbh, + $dbUtil->getWorkflowsToExec($locked_shd), + MDB2_FETCHMODE_ASSOC); + $executed_jobs = array(); + $rows_workflows_to_exec = $rows_workflows + $rows_job_workflows; + foreach ($rows_workflows_to_exec as $key=>$row) { + $job_id_executed = $this->execWorkflowNode($row['id_workflow'], $row['id_node']); + //Add the job to $executed_jobs array + array_push($executed_jobs, $job_id_executed); + } + $executed_jobs_values = array_values($executed_jobs); + unset($rows_workflows); + unset($executed_jobs); + + //Get all scheduled jobs ready for execution + $rows = $dbUtil->dbQuery($dbh, + $dbUtil->getJobsToExec($locked_shd), + MDB2_FETCHMODE_ASSOC); + + foreach ($rows as $key=>$row) { + if (!in_array($row['id_job'], $executed_jobs_values)) { + //This job is not a workflow step execute it! + $this->execJob($row['id_job'], $row['label'], $row['category']); + } else { + $this->logger->trace('DEBUG', + 'Job already executed as workflow step' . + $row['id_job']); + } + } + + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + $this->logger->trace('DEBUG', 'End crontab'); + $this->logger->trace('DEBUG', '######################################'); + } + + function execWorkflowNode($id_wf, $id_node) { + $dbUtil = new DbUtil(); + + $dbh = $dbUtil->dbOpenConnOrtro(); + $rows = $dbUtil->dbQuery($dbh, + $dbUtil->getWorkflowNodeInfo($id_wf, $id_node), + MDB2_FETCHMODE_ASSOC); + + $this->wf_logger->trace('DEBUG', print_r(array($id_wf, $id_node),true)); + + $node = $rows[0]; + unset($rows); + + + //Update the workflow status to running + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowStatus($id_wf, + 'R')); + //Update the step status for this workflow as undefined + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowNodeStatus($id_wf, + '*', + '-')); + //Update the status of the first step as running + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowNodeStatus($id_wf, + $id_node, + 'R')); + + + $log_prefix = '[workflow: ' . $node['id_workflow'] . + '][node: ' . $node['id_node'] . + '][id_to_exec: ' . $node['id_to_exec'] . ']'; + '][type_to_exec: ' . $node['type_to_exec'] . ']'; + + $this->wf_logger->trace('DEBUG', print_r($node,true)); + $this->wf_logger->trace('DEBUG', + $log_prefix . + '[mode: crontab] workflow started...'); + + switch ($node['type_to_exec']) { + case 'J': + $job_id = $node['id_to_exec']; + $job_info = $dbUtil->dbQuery($dbh, + $dbUtil->getJobType($job_id), + MDB2_FETCHMODE_ASSOC); + + //Execute the job + $this->execJob($job_id, $job_info[0]['label'], $job_info[0]['category']); + unset($job_info); + break; + case 'W': + //getWorkflowInfoById($row['id_to_exec'], 0); + //Execute the workflow + //TODO + break; + default: + //Strange value... exit + continue; + break; + } + + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + return $job_id; + } + + /** + * Kill the specified process and all children + * + * @param int $pid The pid of the process to kill + * + * @return void + */ + function killProcess($pid) + { + $pid_kill = array($pid); + while ($pid > 0) { + $cmd = 'ps -ef| awk \'$3 == \'' . $pid . '\' { print $2 }\''; + exec($cmd, $std_out, $exit_code); + if (count($std_out) > 0) { + $pid = $std_out[0]; + array_unshift($pid_kill,$pid); + } else { + $pid = 0; + } + unset($std_out); + } + //print_r($pid_kill); + foreach ($pid_kill as $pid) { + posix_kill($pid, 9); + } + } + + /** + * Verify if process process associated with the ortro job is running. + * + * @param int $pid The pid of the process to kill + * @param int $jobId The ortro id of the job to kill + * + * @return bool + */ + function killJobCheck($pid, $jobId) + { + $cmd = 'ps -ef | awk \'$2 == \'' . $pid . '\' { print $10 }\''; + exec($cmd, $std_out, $exit_code); + if (count($std_out)>0 && $std_out[0] == $jobId) { + return true; + } else { + return false; + } + } + + /** + * Kill the specified job + * + * @param int $job_id The id of the job to kill + * + * @return boolean true on success + */ + function killJob($id_job) + { + $result = false; + $killLogger = new LogUtil('killJob'); + $killLogger->trace('DEBUG', 'Trying to kill job: ' . $id_job); + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConnOrtro(); + //Retrieve msg_exec contains info about pid + $jobs_infos = $dbUtil->dbQuery($dbh, $dbUtil->getJobStatusDetail($id_job), + MDB2_FETCHMODE_ASSOC); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + if ($jobs_infos[0]['status'] == 'R') { + $temp = explode('pid=',rawurldecode($jobs_infos[0]['msg_exec'])); + $pid = $temp[1]; + if ($this->killJobCheck($pid, $id_job)) { + $killLogger->trace('DEBUG', 'Job ' . $id_job . + ' is running with pid: ' . $pid); + $this->killProcess($pid); + $killLogger->trace('DEBUG', 'Processes for Job ' . + $id_job . ' killed.'); + } else { + $killLogger->trace('DEBUG', 'No process running for Job ' . + $id_job); + } + unset($temp); + $result = true; + } else { + $killLogger->trace('DEBUG', 'Job ' . $id_job . ' is not running. Skip.'); + } + unset($jobs_infos); + return $result; + } + + /** + * Execute the job using php-cli in background + * + * @param int $id_job The job id to execute + * @param string $type The type of the the plugin + * @param string $category The category of the the plugin + * @param string $requestType The type of request (Crontab, xml-rpc,...) + * + * @return void + */ + function execJob ($id_job, $type, $category, $requestType='CRONTAB') + { + $execLogger = new LogUtil('execJob'); + $execLogger->trace('DEBUG', "request type: " . $requestType); + $script = '"' . ORTRO_PLUGINS . $category . DS . $type . DS .'core.php"'; + + // Create the cmd line + $cmdLine = $GLOBALS['conf']['env']['php_path'] . + 'php' . ' ' . + $script . ' ' . + $id_job . ' ' . + $requestType; + + $execLogger->trace('DEBUG', 'Executing job: ' . $cmdLine); + + switch ($requestType) { + case 'XML-RPC': + $bg_command = ' 1>' . ORTRO_LOG . 'ortro_error_XML_RPC_' . + date($GLOBALS['conf']['env']['dateFormat']) . + '.log 2>&1'; + exec($cmdLine . $bg_command, $output, $exit_code); + return implode($output); //return a serialized output + break; + default: // Type request: CRONTAB + $bg_command = ' 1>>' . ORTRO_LOG . 'ortro_error_' . + date($GLOBALS['conf']['env']['dateFormat']) . + '.log 2>&1 &'; + //execute the command in background + system($cmdLine . $bg_command); + break; + } + } + + /** + * Perform the actions on the job start event + * + * @param string $pluginName The name of the plugin + * @param string $id_job The job id + * + * @return array The parameters required for the job execution + */ + + function startJobEvent($pluginName, $id_job) + { + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConnOrtro(); + // Get all the info required for the job execution + $jobs_infos = $dbUtil->dbQuery($dbh, + $dbUtil->getJobToExecInfo($id_job), + MDB2_FETCHMODE_ASSOC); + + if ($jobs_infos[0]['identity'] != 0) { + //get the identity credential + $identity = $dbUtil->dbQuery($dbh, + $dbUtil->getIdentityById($jobs_infos[0]['identity']), + MDB2_FETCHMODE_ASSOC); + + $identity[0]['password'] = + $dbUtil->dbUnserialize($identity[0]['password']); + $jobs_infos[0]['identity'] = $identity[0]; + } + + switch ($this->requestType) { + case 'XML-RPC': + $this->logger->trace('INFO', 'Executing job ' . $pluginName . + ' with id=' . $id_job . + ' requested via xml-rpc'); + break; + default: // Type request: CRONTAB + // Update the job start time and lock the process + $msg_exec = 'Running with: id=' . $id_job . ' ,pid=' . getmypid(); + $dbUtil->dbExec($dbh, $dbUtil->setJobStart($id_job, $msg_exec)); + $this->logger->trace('INFO', 'Executing job ' . $pluginName . + '. ' . $msg_exec); + break; + } + + //Get dynamic info used eventually if the job is a workflow step + /* TODO + $dynamic_params = $dbUtil->dbQuery($dbh, + $dbUtil->getWorkflowStepDynamicParams($id_job)); + if (isset($dynamic_params[0])) { + $jobs_infos[0]['dynamic_params'] = + $dbUtil->dbUnserialize($dynamic_params[0][0]); + } + + * */ + + //Get all notifications for this job + $resultSet = $dbUtil->dbQuery($dbh, + $dbUtil->getNotifyInfoByJobId($id_job, 3), + MDB2_FETCHMODE_ASSOC); + for ($i = 0; $i < sizeof($resultSet); $i++) { + $row = $resultSet[$i]; + $row['parameters'] = $dbUtil->dbUnserialize($row['parameters']); + if ($row['identity'] != 0) { + //get the identity credential + $identity = $dbUtil->dbQuery($dbh, + $dbUtil->getIdentityById($row['identity']), + MDB2_FETCHMODE_ASSOC); + + $identity[0]['password'] = $dbUtil->dbUnserialize($identity[0]['password']); + + $row['parameters']['identity'] = $identity[0]; + //Add the id_job to able to create a unique notify + $row['parameters']['id_job'] = $row['id_job']; + } + include_once 'notifyUtil.php'; + // Send notify + $notify = new NotifyUtil(); + $notify->sendNotify($row['label'], $row['parameters'], $attachments); + } + + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + // Unserialize the parameters + $jobs_infos[0]['parameters'] = + $dbUtil->dbUnserialize($jobs_infos[0]['parameters']); + + return $jobs_infos[0]; + } + + /** + * Perform the actions on the job end event: + * - Update database job info + * - Send notification + * + * @param string $pluginName The name of the plugin + * @param string $id_job The job id + * @param string $result The job result (0 = error, 1 = success) + * @param string $msg_exec The job message result + * @param array $attachments The job info used as attachements by the + * notification plugins + * @param string $dynamic_params Job output fields serialized used eventually + * as parameters in a job step if required + * + * @return void + */ + function endJobEvent($pluginName, $id_job, $result, $msg_exec, + $attachments, $dynamic_params='', $enable_notification=true) + { + //Inserts HTML line breaks before all newlines for message + $msg_exec = nl2br($msg_exec); + + $dbUtil = new DbUtil(); + $this->logger->trace('DEBUG', 'Result for job ' . $id_job . ' -> ' . $result); + $this->logger->trace('INFO', 'Job ' . $pluginName . ' with id=' . $id_job . ' done.'); + switch ($this->requestType) { + case 'XML-RPC': + include_once 'XML/RPC/Server.php'; + $output = array( + 'result' => new XML_RPC_Value($result, "boolean"), + 'msg_exec' => new XML_RPC_Value($msg_exec, "string"), + 'txt_attachment' => new XML_RPC_Value($attachments['txt'], + "string"), + 'html_attachment' => new XML_RPC_Value($attachments['html'], + "string") + ); + + $serialized_output = $dbUtil->dbSerialize($output); + echo $serialized_output; //return a serialized output + break; + default: // Type request: CRONTAB + + $dbh = $dbUtil->dbOpenConnOrtro(); + //Check for retry on job failure + $resultSet = $dbUtil->dbQuery($dbh, + $dbUtil->getJobProperties($id_job), + MDB2_FETCHMODE_ASSOC); + $properties = $dbUtil->dbUnserialize($resultSet[0]['properties']); + $num_failures = $resultSet[0]['num_failures']; + if ($properties['max_check_attempts'] > $num_failures && $result == 0) { + $num_failures = $num_failures + 1; + $this->logger->trace('DEBUG', 'Job ' . $id_job . + ' retry on failure attempt ' . + $num_failures . ' of ' . + $properties['max_check_attempts']); + + $dbUtil->dbExec($dbh, $dbUtil->setJobEnd($id_job, + $result, + $msg_exec, + $num_failures)); + + $this->logger->trace('DEBUG', 'Job ' . $id_job . + ' : Wait for retry execution ' . + $properties['delay_retry'] . + ' seconds'); + + sleep($properties['delay_retry']); + //Check for lock status + $rows = $dbUtil->dbQuery($dbh, $dbUtil->getJobStatus($id_job)); + + $job_status = $rows[0][0]; + if ($job_status == 'W') { + $resultSet = $dbUtil->dbQuery($dbh, + $dbUtil->getJobType($id_job), + MDB2_FETCHMODE_ASSOC); + } + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + if ($job_status == 'W') { + $this->execJob($id_job, + $resultSet[0]['label'], + $resultSet[0]['category']); + } else { + $this->logger->trace('DEBUG', '[id_job: ' . $id_job . + '] Job status is: ' . $job_status. + ' -> skip execution'); + } + } else { + $dbUtil->dbExec($dbh, $dbUtil->setJobEnd($id_job, + $result, + $msg_exec)); + + if ($enable_notification === true) { + //Get all notifications for this job + $resultSet = $dbUtil->dbQuery($dbh, + $dbUtil->getNotifyInfoByJobId($id_job), + MDB2_FETCHMODE_ASSOC); + + + + for ($i = 0; $i < sizeof($resultSet); $i++) { + $row = $resultSet[$i]; + + $notify_on = explode('-', $row['notify_on']); + array_shift($notify_on); + array_pop($notify_on); + + if (sizeof(array_intersect($notify_on, array($result, '2'))) > 0) { + $row['parameters'] = $dbUtil->dbUnserialize($row['parameters']); + if ($row['identity'] != 0) { + //get the identity credential + $identity = $dbUtil->dbQuery($dbh, + $dbUtil->getIdentityById($row['identity']), + MDB2_FETCHMODE_ASSOC); + + $identity[0]['password'] = $dbUtil->dbUnserialize($identity[0]['password']); + + $row['parameters']['identity'] = $identity[0]; + //Add the id_job to able to create a unique notify + $row['parameters']['id_job'] = $row['id_job']; + } + include_once 'notifyUtil.php'; + // Send notify + $notify = new NotifyUtil(); + $notify->sendNotify($row['label'], $row['parameters'], $attachments); + } + } + } + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + } + break; + } + + /* WORKFLOW ACTIONS */ + // Check if the job is a workflow step + $dbh = $dbUtil->dbOpenConnOrtro(); + //Get all steps with this $id_job with status R or W (if exist one) + $workflowNode = $dbUtil->dbQuery($dbh, + $dbUtil->checkWorkflowNodeInfoByIdJob($id_job), + MDB2_FETCHMODE_ASSOC); + + if (count($workflowNode) != 0) { + //$this->logger->trace('DEBUG', print_r($workflowNode, true)); + //The job is a step of at least a workflow + + $id_workflow = $workflowNode[0]['id_workflow']; + $id_node = $workflowNode[0]['id_node']; + $log_prefix = '[workflow: ' . $id_workflow . ']'; + + $this->wf_logger->trace('DEBUG', $log_prefix . '[id_node: ' . $id_node . '] Done.'); + + // Update the step status in accord to $result + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowNodeStatus($id_workflow, + $id_node, + $result)); + $exec_condition = 0; + if ($result == '0') { + $exec_condition = 1; + } + + $this->wf_logger->trace('DEBUG', $log_prefix . '[id_node: ' . $id_node . '] Check for child node to execute...'); + + $nodes_to_exec = $dbUtil->dbQuery($dbh, + $dbUtil->getWorkflowInfoById($id_workflow, + $id_node, + $exec_condition), + MDB2_FETCHMODE_ASSOC); + + if (count($nodes_to_exec) != 0 ) { + //There is a next step + + $log_prefix .= '[id_parent_node: ' . $id_node . ']'; + $this->wf_logger->trace('DEBUG', print_r($nodes_to_exec, true)); + $this->wf_logger->trace('DEBUG', $log_prefix . ' Nodes found'); + + foreach ($nodes_to_exec as $node) { + switch ($node['exec_properties']) { + case 'W': + //Wait for define schedule + //Update the status of the node + $this->wf_logger->trace('DEBUG', $log_prefix . '[id_node: ' . $node['id_node'] . '] Waiting for schedule'); + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowNodeStatus($node['id_workflow'], + $node['id_node'], + 'W')); + break; + case 'I': + //Run immediately + //Update the status of the node + $this->wf_logger->trace('DEBUG', $log_prefix . '[id_node: ' . $node['id_node'] . '] Executing immediately'); + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowNodeStatus($node['id_workflow'], + $node['id_node'], + 'R')); + + switch ($node['type_to_exec']) { + case 'J': + $job_id = $node['id_to_exec']; + $job_info = $dbUtil->dbQuery($dbh, + $dbUtil->getJobType($job_id), + MDB2_FETCHMODE_ASSOC); + + //Execute the job + $this->execJob($job_id, $job_info[0]['label'], $job_info[0]['category']); + unset($job_info); + break; + case 'W': + //Execute the workflow node + $id_wf = $node['id_to_exec']; + $wf_info_root_node = $dbUtil->dbQuery($dbh, + $dbUtil->getWorkflowInfoById($id_wf, '0'), + MDB2_FETCHMODE_ASSOC); + $id_root_node = $wf_info_root_node[0]['id_node']; + $this->execWorkflowNode($id_wf, $id_root_node); + break; + default: + //Strange value... exit + continue; + break; + } + } + } + } else { + $this->wf_logger->trace('DEBUG', $log_prefix . '[id_node: ' . $id_node . '] has no child.'); + $this->wf_logger->trace('DEBUG', $log_prefix . 'Checking for running/waiting nodes...'); + + $active_nodes = $dbUtil->dbQuery($dbh, + $dbUtil->checkWorkflowRunningNodes(), + MDB2_FETCHMODE_ASSOC); + if(count($active_nodes) == 0) { + //There are not other nodes to execute... workflow completed! + $this->wf_logger->trace('DEBUG', $log_prefix . 'Workflow completed.'); + $dbUtil->dbExec($dbh, + $dbUtil->updateWorkflowStatus($id_workflow, 'W',time()) + ); + } else { + $this->wf_logger->trace('DEBUG', $log_prefix . 'There are active nodes...'); + $this->wf_logger->trace('DEBUG', $log_prefix . print_r($active_nodes,true)); + } + } + //Close DB connection used for workflow actions + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + } + } + + /** + * Allows to achive and handle the retention of the job results + * + * @param string $id_job The job id (i.e. filesystem, db, ...) + * @param array $data Archivation info. + * + * @return void + */ + function archiveJobResult($id_job, $data) + { + + $logger = new LogUtil('Archive'); + $logger->trace('DEBUG', 'Apply retention policy for job: ' . $id_job); + switch ($this->requestType) { + case 'XML-RPC': + $logger->trace('DEBUG', + 'Skipped the job is executed via xml-rpc'); + break; + default: // Type request: CRONTAB + $log_label = '[' . $id_job . ']'; + $logger->trace('DEBUG', $log_label . ' -> mode: ' . + $data['archive_mode']); + $logger->trace('DEBUG', $log_label . ' -> retention: ' . + $data['retention']); + switch ($data['archive_mode']) { + case 'FILESYSTEM': + //apply retention policy + $handle = opendir($data['path']); + if ($handle) { + while (false !== ($file = readdir($handle))) { + $pos = strpos($file, $data['filename']); + if ($pos !== false && $pos=='0') { + if (filectime($data['path'] . $file) < + (time() - $data['retention'] * 60 * 60 * 24)) { + $logger->trace('DEBUG', + $log_label . + 'Trying to remove ' . + $data['path'] . + $file . ' ...'); + unlink($data['path'] . $file); + $logger->trace('DEBUG', + $log_label . 'Removed.'); + } + } + } + } + break; + default: + //store in the database + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConnOrtro(); + //archive the job result + $dbUtil->dbExec($dbh, $dbUtil->archiveJobResult($id_job)); + //apply retention + + $date = time() - ($data['retention'] * 60 * 60 * 24); + $result = $dbUtil->dbExec($dbh, + $dbUtil->applyRetentionPolicy($id_job, $date)); + $logger->trace('DEBUG', $log_label . + ' deleted records -> ' . + $result); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + break; + } + $logger->trace('DEBUG', $log_label . ' -> Done.'); + break; + } + } + + /** + * Trace the exception occorred in the plugin in the error file + * + * @param string $file_name The name of the plugin + * @param object $e The exception object + * + * @return void + */ + function traceError($file_name, $e) + { + $loggerError = new LogUtil($file_name, ORTRO_LOG . 'error'); + $loggerError->trace('ERROR', "Exception catched:"); + $loggerError->trace('ERROR', "File: ".$e->getFile().""); + $loggerError->trace('ERROR', "Message: ".$e->getMessage().""); + $loggerError->trace('ERROR', "Line: ".$e->getLine().""); + $loggerError->trace('ERROR', "Code: ".$e->getCode().""); + $loggerError->trace('ERROR', "Trace: ".$e->getTraceAsString()); + } + + /** + * The purpose of this method is to calculate the next execution time + * from a specified crontab entry + * + * @param string $m The cron value for minute in the Ortro format + * @param string $h The cron value for hour in the Ortro format + * @param string $dom The cron value for day of month in the Ortro format + * @param string $mon The cron value for month of year in the Ortro format + * @param string $dow The cron value for day of week in the Ortro format + * @param int $ref_time The reference time for which the next time should be + * searched which matches. By default, take the current time + * + * @return int $date The unix timestamp of the next matched date for cron. + */ + function calcNextCronDate($m, $h, $dom, $mon, $dow, $ref_time=0) + { + $expanded = array($this->getCronEntries($m, 'minute'), + $this->getCronEntries($h, 'hour'), + $this->getCronEntries($dom, 'day_of_month'), + $this->getCronEntries($mon, 'month'), + $this->getCronEntries($dow, 'day_of_week') + ); + + //Calculating time: + // ================= + if ($ref_time == 0) { + $ref_time = time(); + } + if ($expanded[2][0] != '*' && $expanded[4][0] != '*') { + // Special check for which time is lower (Month-day or Week-day spec): + $bak = $expanded[4]; + $expanded[4] = '*'; + $t1 = $this->calcTime($ref_time, $expanded); + $expanded[4] = $bak; + $expanded[2] = '*'; + $t2 = $this->calcTime($ref_time, $expanded); + return $t1 < $t2 ? $t1 : $t2; + } else { + // No conflicts possible: + return $this->calcTime($ref_time, $expanded); + } + } + + /** + * This method parse the Ortro crontab string and return the crontab entries + * + * @param string $cronString The Ortro crontab string to parse + * @param string $typeCron The crontab field we are parsing + * + * @return array $cronValues Contains the values for the specified entry. + */ + function getCronEntries($cronString, $typeCron){ + + $cronValues = split('-', $cronString); + array_shift($cronValues); + array_pop($cronValues); + + switch ($typeCron) { + case 'minute': + if (count($cronValues) == 60) { + $cronValues = array('*'); + } + break; + case 'hour': + if (count($cronValues) == 24) { + $cronValues = array('*'); + } + break; + case 'day_of_month': + if (count($cronValues) == 31) { + $cronValues = array('*'); + } + break; + case 'month': + if (count($cronValues) == 12) { + $cronValues = array('*'); + } + break; + case 'day_of_week': + if (count($cronValues) == 7) { + $cronValues = array('*'); + } + break; + } + return $cronValues; + } + + /** + * Get the next entry in list + * + * @param string $x The value for test + * @param array $to_check The entries to test + * + * @return mixed Next entry in list or false if is the highest entry found + */ + function getNearest($x, $to_check) { + for ($i = 0; $i < count($to_check); $i++) { + if ($to_check[$i] >= $x) { + return $to_check[$i] ; + } + } + return false; + } + + /** + * Calculate the next concrete date for execution from a crontab entry + * + * @param int $ref_time + * @param array $expanded + * + * @return int The next concrete date in the Unix timestamp format + */ + function calcTime($ref_time, $expanded) + { + + $dayweek['0'] = 'Sunday'; + $dayweek['1'] = 'Monday'; + $dayweek['2'] = 'Tuesday'; + $dayweek['3'] = 'Wednesday'; + $dayweek['4'] = 'Thursday'; + $dayweek['5'] = 'Friday'; + $dayweek['6'] = 'Saturday'; + + $now_min = (int) date('i', $ref_time); + $now_hour = date('H', $ref_time); + $now_mday = date('d', $ref_time); + $now_mon = date('m', $ref_time); + $now_wday = date('w', $ref_time); + $now_year = date('Y', $ref_time); + + // Notes on variables set: + // $now_... : the current date, fixed at call time + // $dest_...: date used for backtracking. At the end, it contains + // the desired lowest matching date + + $dest_mon = $now_mon; + $dest_mday = $now_mday; + $dest_wday = $now_wday; + $dest_hour = $now_hour; + $dest_min = $now_min + 1; + $dest_year = $now_year; + + $dest_mon_error = 0; + $dest_mday_error = 0; + $dest_year_error = 0; + + while ($dest_year <= ($now_year + 1)){ + // Check month: + if ($expanded[3][0] != '*') { + $dest_mon = $this->getNearest($dest_mon, $expanded[3]); + if ($dest_mon === false) { + $dest_mon = $expanded[3][0]; + $dest_year++; + } + } + // Check for day of month: + if ($expanded[2][0] != '*') { + if ($dest_mon != $now_mon) { + $dest_mday = $expanded[2][0]; + } else { + $dest_mday = $this->getNearest($dest_mday,$expanded[2]); + if ($dest_mday === false) { + // Next day matched is within the next month. ==> redo it + $dest_mday = $expanded[2][0]; + $dest_mon++; + if ($dest_mon > 12) { + $dest_mon = 1; + $dest_year++; + } + + continue; + } + } + } else { + $dest_mday = ($dest_mon == $now_mon ? $dest_mday : 1); + } + // Check for day of week: + if ($expanded[4][0] != '*') { + $dest_wday = $this->getNearest($dest_wday,$expanded[4]); + + if ($dest_wday === false) { + $dest_wday = $expanded[4][0]; + } + if ($dest_mon != $now_mon) { + $dest_mday = 1; + } + + $t = mktime(0,0,0,$dest_mon,$dest_mday,$dest_year); + + $nt = strtotime($dayweek[$dest_wday],$t); + + foreach ($expanded[4] as $available_day) { + $nt_tmp = strtotime("next $dayweek[$available_day]",$t); + if ($nt_tmp < $nt) { + $nt = $nt_tmp; + } + } + $mday = date('d', $nt); + $mon = date('m', $nt); + $year = date('Y', $nt); + + if ($mon != $dest_mon || $year != $dest_year) { + //backtracking; + $dest_mon = $mon; + $dest_year = $year; + $dest_mday = 1; + $dest_wday = date('w', mktime(0,0,0,$dest_mon,$dest_mday,$dest_year)); + continue; + } + + $dest_mday = $mday; + } else { + if (!$dest_mday) { + $dest_mday = ($dest_mon == $now_mon ? $dest_mday : 1); + } + } + + // Check for hour + if ($expanded[1][0] != '*') { + if ($dest_mday != $now_mday) { + $dest_hour = $expanded[1][0]; + } else { + // Checking for next hour $dest_hour + if (($dest_hour = $this->getNearest($dest_hour,$expanded[1])) === false) { + // Hour to match is at the next day ==> redo it + $dest_hour = $expanded[1][0]; + + $t = mktime($dest_hour, $dest_min, 0, $dest_mon, $dest_mday, $dest_year); + $nt = strtotime("+ 1 day", $t); + + $dest_mday = date('d', $nt); + $dest_mon = date('m', $nt); + $dest_year = date('Y', $nt); + $dest_wday = date('w', $nt); + + continue; + } + } + } else { + $dest_hour = ($dest_mday == $now_mday ? $dest_hour : 0); + } + + // Check for minute + if ($expanded[0][0] != '*') { + if ($dest_hour != $now_hour) { + $dest_min = $expanded[0][0]; + } else { + if (($dest_min = $this->getNearest($dest_min,$expanded[0])) === false) { + // Minute to match is at the next hour ==> redo it + if ($dest_mday <= $now_mday){ + $dest_min = $expanded[0][0]; + $t = mktime($dest_hour, $dest_min, 0, $dest_mon, $dest_mday, $dest_year); + $nt = strtotime("+ 1 hour",$t); + + $dest_hour = date('H', $nt); + $dest_mday = date('d', $nt); + $dest_mon = date('m', $nt); + $dest_year = date('Y', $nt); + $dest_wday = date('w', $nt); + continue; + } + } + } + } else { + $dest_min = ($dest_hour == $now_hour ? $dest_min : 0); + } + + // We did it !! + if (checkdate($dest_mon,$dest_mday,$dest_year)){ + $date = mktime($dest_hour,$dest_min,0,$dest_mon,$dest_mday,$dest_year); + } else { + if ($dest_mon_error != $dest_mon && $dest_mday_error != $dest_mday && $dest_year_error != $dest_year){ + $dest_mon_error = $dest_mon; + $dest_mday_error = $dest_mday; + $dest_year_error = $dest_year; + $nt = mktime($dest_hour,$dest_min,0,$dest_mon,$dest_mday,$dest_year); + + $dest_hour = date('H', $nt); + $dest_mday = date('d', $nt); + $dest_mon = date('m', $nt); + $dest_year = date('Y', $nt); + $dest_wday = date('w', $nt); + continue; + } else { + $date = 0; + } + } + return $date; + } + } +} +?> \ No newline at end of file diff --git a/lib/dbUtil.php b/lib/dbUtil.php new file mode 100644 index 0000000..aa3d24b --- /dev/null +++ b/lib/dbUtil.php @@ -0,0 +1,3293 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'Pear/MDB2.php'; +require_once 'logUtil.php'; +require_once 'cronUtil.php'; + +/** + * DbUtil Class + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class DbUtil +{ + var $_dsn=''; + + /** + * DbUtil Class constructor. + * + * @return void + */ + function dbUtil() + { + $this->logger = new LogUtil('dbUtil.php'); + } + + /** + * Add the custom prefix to the specified table + * + * @param string $tableName The table name + * + * @return string The table name with prefix + */ + function setTablePrefix($tableName) + { + return $GLOBALS['conf']['db']['tableprefix'] . $tableName; + } + + /** + * Set the DSN resource + * + * @param array $dsnArray The dsn array + * + * @return string The dsn string + */ + function setDSN($dsnArray) + { + switch ($dsnArray['phptype']) { + case 'oci8': + $hostspec = split(':', $dsnArray['hostspec']); + $ip = $hostspec['0']; + $port = $hostspec['1']; + $sid = $dsnArray['database']; + $tnsnames = "(DESCRIPTION = (ADDRESS = (PROTOCOL = tcp)(Host = $ip)" . + "(Port = $port))(CONNECT_DATA =(SID = $sid)))"; + $dsn = $dsnArray['phptype'] . '://' . $dsnArray['username'] . ':' . + $dsnArray['password'] . '@' . $tnsnames; + break; + case 'sqlite': + $dsn = $dsnArray['phptype'] . ':///' . ORTRO_SQLITE_DB . + $dsnArray['database'] . '?mode=0600'; + break; + /* + * Add here dsn different by default case if needed + case mysql: + $dsn= $dsnArray['phptype'] . '://' . $dsnArray['user'] . ':' . + $dsnArray['password'] . '@' . $dsnArray['hostspec'] . '/' . + $dsnArray['database']; + break; + */ + default: + $dsn = $dsnArray['phptype'] . '://' . $dsnArray['username'] . ':' . + $dsnArray['password'] . '@' . $dsnArray['hostspec'] . '/' . + $dsnArray['database']; + break; + } + $this->_dsn = $dsn; + return $this->_dsn; + } + + /** + * Get the DSN resource + * + * @return string The DSN string + */ + function getDSN() + { + return $this->_dsn; + } + + /** + * Create a new MDB2 connection object and connect + * to the Ortro database + * + * @return object The connection object + */ + function dbOpenConnOrtro() + { + $dsn = $this->setDSN(array('phptype' => $GLOBALS['conf']['db']['phptype'], + 'hostspec' => $GLOBALS['conf']['db']['host'] . + ':' . + $GLOBALS['conf']['db']['port'], + 'database' => $GLOBALS['conf']['db']['database'], + 'username' => $GLOBALS['conf']['db']['username'], + 'password' => $GLOBALS['conf']['db']['password'])); + + $dbh =& MDB2 :: connect($dsn); + if (MDB2 :: isError($dbh)) { + $this->logger->trace('DEBUG', 'Database connection failed: '); + $this->logger->trace('DEBUG', $dbh->getDebugInfo()); + exit; + } + $dbh->setErrorHandling(PEAR_ERROR_DIE); + return $dbh; + } + + /** + * Create a new MDB2 connection object and connect + * to the specified database + * + * @param string $dbType Database back end type + * @param string $hostname Host + * @param string $port Port + * @param string $dbName Database name + * @param string $user Username + * @param string $password Password + * + * @return object The connection object + */ + function dbOpenConn($dbType, $hostname, $port, $dbName, $user, $password) + { + $dsn = $this->setDSN(array('phptype' => $dbType, + 'hostspec' => $hostname . ':' . $port, + 'database' => $dbName, + 'username' => $user, + 'password' => $password)); + try { + $dbh =& MDB2 :: connect($dsn); + } catch (Exception $e) { + if ($dbType == 'oci8' && + (!(strpos($e->getMessage(), 'ORA-12505') === false))) { + //Trying to use SERVICE_NAME instead of SID + $dsn = str_replace('=(SID', '=(SERVICE_NAME', $dsn); + $this->_dsn = $dsn; + $dbh =& MDB2 :: connect($dsn); + if (MDB2 :: isError($dbh)) { + $error_msg = "\nDatabase connection failed: \n" . + $dbh->getDebugInfo(); + $this->logger->trace('ERROR', $error_msg); + throw new Exception($error_msg); + } + } else { + $error_msg = "\nDatabase connection failed: \n" . $e->getMessage(); + $this->logger->trace('ERROR', $error_msg); + throw new Exception($error_msg); + } + } + return $dbh; + } + + /** + * Execute the specified query, fetch all the rows + * of the result set into a two dimensional array + * and then frees the result set. + * + * @param Object $dbh the MDB2 object connection + * @param string $stmt the SQL query + * @param int $mode how the array data should be indexed + * + * @return mixed MDB2_OK or data array on success, a MDB2 error on failure + */ + function dbQuery($dbh, $stmt, $mode=MDB2_FETCHMODE_ORDERED) + { + $stmt_log = preg_replace('/password=\'\S+\'/', 'password=******', $stmt); + $this->logger->trace('DEBUG', $stmt_log); + $result = $dbh->queryAll($stmt, null, $mode); + // Always check that result is not an error + if (PEAR::isError($result)) { + $error_msg = "\nQuery failed: " . $stmt_log . + "\n" . $result->getMessage(); + $this->logger->trace('ERROR', $error_msg); + throw new Exception($error_msg); + } + return $result; + } + + /** + * Execute a manipulation query to the database and + * return the number of affected rows + * + * @param Object $dbh the MDB2 object connection + * @param string $stmt the SQL query + * + * @return mixed number of affected rows on success, a MDB2 error on failure + */ + function dbExec($dbh, $stmt) + { + $stmt_log = preg_replace('/password=\'\S+\'/', 'password=******', $stmt); + $this->logger->trace('DEBUG', $stmt_log); + $affected =& $dbh->exec($stmt); + // Always check that result is not an error + if (PEAR::isError($affected)) { + $error_msg = "\nQuery failed: " . $stmt_log . "\n" . + $affected->getMessage(); + $this->logger->trace('ERROR', $error_msg); + throw new Exception($error_msg); + exit; + } + return $affected; + } + + /** + * Execute multiple manipulation queries to the database + * + * @param Object $dbh the MDB2 object connection + * @param array $stmt an array with the SQL queries + * + * @return void + */ + function dbExecMulti($dbh, $stmt) + { + for ($i = 0; $i < sizeof($stmt); $i++) { + $this->dbExec($dbh, $stmt[$i]); + } + } + + /** + * Execute a sql script from file + * + * @param Object $dbh the MDB2 object connection + * @param string the SQL file + * + * @return mixed true on success, a MDB2 error on failure + * + * @access public + */ + function dbExecFromFile($dbh, $sql_file) + { + $contents = file_get_contents($sql_file); + + // Remove C style and inline comments + $comment_patterns = array('/\/\*.*(\n)*.*(\*\/)?/', //C comments + '/\s*--.*\n/', //inline comments start with -- + '/\s*#.*\n/', //inline comments start with # + ); + $contents = preg_replace($comment_patterns, "\n", $contents); + + //Retrieve sql statements + $statements = explode(";\n", $contents); + $statements = preg_replace("/\s/", ' ', $statements); + + foreach ($statements as $query) { + if (trim($query) != '') { + $this->logger->trace('DEBUG','Executing query: ' . $query); + $this->dbExec($dbh, $query); + } + } + return true; + } + + + + /** + * Log out and disconnect from the database. + * + * @param Object $dbh the MDB2 object connection + * + * @return true on success, false if not connected and error object on error + */ + function dbCloseConn($dbh) + { + $dbh->disconnect(); + return $dbh; + } + + /** + * Encodes a string representation of variable using MIME base64 algorithm. + * + * @param string $string2serialize The string to serialize + * + * @return string + */ + function dbSerialize($string2serialize) + { + return base64_encode(serialize($string2serialize)); + } + + /** + * Takes a string representation of variable decoded using MIME base64 + * algorithm and recreates it + * + * @param string $string2unserialize The string to unserialize + * + * @return mixed + */ + function dbUnserialize($string2unserialize) + { + return unserialize(base64_decode($string2unserialize)); + } + + /** + * SQL query to add a System + * + * @param string $system the system label + * + * @return string the sql statement + */ + function setSystem($system) + { + $stmt = 'insert into ' . $this->setTablePrefix('system') . + " (name, status) values ('". $system . "', 'W')"; + return $stmt; + } + + /** + * SQL query to get all systems + * + * @return string the sql statement + */ + function getSystems() + { + $stmt = 'select * from ' . $this->setTablePrefix('system') . + ' order by name'; + return $stmt; + } + + /** + * SQL query to get the system by aspecified id + * + * @param int $id_system the system id + * + * @return string the sql statement + */ + function getSystemById($id_system) + { + $stmt = 'select * from ' . $this->setTablePrefix('system') . + ' where id_system=' . $id_system; + return $stmt; + } + + /** + * SQL query to update the system values + * + * @param int $id_system the system id + * @param string $systemName the system name + * + * @return string the sql statement + */ + function updateSystem($id_system, $systemName) + { + $stmt = 'update ' . $this->setTablePrefix('system') . + " set name='" . $systemName . "'" . + ' where id_system=' . $id_system; + return $stmt; + } + + /** + * SQL query to check if the system name is already defined + * + * @param string $label the system name + * + * @return string the sql statement + */ + function checkExistsSystem($label) + { + $stmt = 'select count(*) from ' . $this->setTablePrefix('system') . + " where name='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to set the relation between system, host and db + * + * @param int $id_system the system id + * @param int $id_host the host id + * @param int $id_db the database id + * + * @return string the sql statement + */ + function setSystemHostDb($id_system, $id_host, $id_db) + { + $stmt = 'insert into ' . $this->setTablePrefix('system_host_db') . + ' (id_system,id_host,id_db)' . + ' values ('. $id_system . ',' . + $id_host .','. + $id_db. ')'; + return $stmt; + } + + /** + * SQL query to get all hosts with associated systems + * + * @param string $filter_system the system id used to filter result (optional) + * + * @return string the sql statement + */ + function getSystemHost($filter_system = '') + { + $filter_stmt = ''; + if ($filter_system != '' && $filter_system != '*') { + $filter_stmt .= ' and a.id_system=' . $filter_system; + } + + $stmt = 'select distinct a.id_system, a.name, b.id_host, b.ip, b.hostname, b.status ' . + 'from ' . $this->setTablePrefix('system') . ' as a, ' . + $this->setTablePrefix('host') . ' as b, '. + $this->setTablePrefix('system_host_db') . ' as c ' . + ' where a.id_system=c.id_system and b.id_host=c.id_host ' . + $filter_stmt . + ' order by a.name,a.id_system,b.hostname'; + return $stmt; + } + + /** + * SQL query to get all jobs with associated systems + * + * @param int $id_system the system id used to filter result (optional) + * + * @return string the sql statement + */ + function getSystemJob($id_system = '') + { + $filter_stmt = ''; + if ($id_system != '') { + $system_filter = ' and b.id_system=' . $id_system; + } + $stmt = 'select a.id_job, a.label, b.id_system, b.name ' . + ' from ' . $this->setTablePrefix('jobs') . ' as a, ' + . $this->setTablePrefix('system') . ' as b, ' + . $this->setTablePrefix('system_host_db') . ' as c ' + . ' where a.id_shd=c.id_shd and b.id_system=c.id_system ' + . $filter_stmt + . ' order by b.name,a.label'; + return $stmt; + } + + /** + * SQL query to check if host name is already defined + * + * @param string $ip the ip address + * @param string $hostname the hostname + * + * @return string the sql statement + */ + function checkExistsHost($ip, $hostname) + { + $stmt = 'select count(*) ' . + 'from ' . $this->setTablePrefix('host') . + " where ip='" . $ip . "'" . + " and hostname='" . $hostname . "'"; + return $stmt; + } + + /** + * SQL query to check if identity label is already defined + * + * @param string $label the identity label + * + * @return string the sql statement + */ + function checkExistsIdentity($label) + { + $stmt = 'select id_identity ' . + 'from ' . $this->setTablePrefix('identity_management') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to check for matching password + * + * @param int $id_identity the identity id + * @param string $password the passwrd + * + * @return string the sql statement + */ + function checkIdentityPassword($id_identity, $password) + { + $stmt = 'select count(*) ' . + 'from ' . $this->setTablePrefix('identity_management') . + ' where id_identity=' . $id_identity . + " and password='" . $password . "'"; + return $stmt; + } + + /** + * SQL query to check if already exists a relation + * between system, host and database + * + * @param int $id_system the system id + * @param int $id_host the host id + * @param int $id_db the database id + * + * @return string the sql statement + */ + function checkExistsSystemHostDb($id_system, $id_host, $id_db) + { + $stmt = 'select count(*) ' . + 'from ' . $this->setTablePrefix('system_host_db') . + ' where id_system=' . $id_system . + ' and id_host=' . $id_host . + ' and id_db=' . $id_db; + return $stmt; + } + + /** + * SQL query to get the system, host, db relation id + * + * @param int $id_system the system id + * @param int $id_host the host id + * @param int $id_db the database id + * + * @return string the sql statement + */ + function getSystemHostDbId($id_system, $id_host, $id_db) + { + $stmt = 'select id_shd ' . + 'from ' . $this->setTablePrefix('system_host_db') . + ' where id_system=' . $id_system . + ' and id_host=' . $id_host . + ' and id_db=' . $id_db; + return $stmt; + } + + /** + * SQL query to get the locked system, host, db relation id + * + * @return string the sql statement + */ + function getLockedSystemHostDb() + { + $stmt = 'select a.id_shd ' . + 'from ' . + $this->setTablePrefix('system_host_db') . ' as a, ' . + $this->setTablePrefix('system') . ' as b, ' . + $this->setTablePrefix('host') . ' as c ' . + " where (b.status != 'W' and a.id_system=b.id_system)" . + " or (a.id_host=c.id_host and c.status != 'W')"; + return $stmt; + } + + + /** + * SQL query to get the system, host, db labels by job id + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function getSystemHostDbInfoById($id_job) + { + $stmt = 'select a.name,b.hostname, c.label ' . + 'from ' . $this->setTablePrefix('system') . ' as a, ' + . $this->setTablePrefix('host') . ' as b, ' + . $this->setTablePrefix('db') . ' as c, ' + . $this->setTablePrefix('system_host_db') . ' as d, ' + . $this->setTablePrefix('jobs') . ' as e ' . + ' where d.id_system=a.id_system and d.id_host=b.id_host and ' . + ' d.id_db=c.id_db and d.id_shd=e.id_shd and ' . + ' e.id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to add a host + * + * @param string $ip the ip address + * @param string $hostname the hostname + * + * @return string the sql statement + */ + function setHost($ip, $hostname) + { + $stmt = 'insert into ' . $this->setTablePrefix('host') . + " (ip,hostname,status) values ('" . $ip . "','" . $hostname . "', 'W')"; + return $stmt; + } + + /** + * SQL query to change the host status + * + * @param string $id_host the host id + * @param string $status the status to set + * + * @return string the sql statement + */ + function setHostStatus($id_host, $status) + { + $stmt = 'update ' . $this->setTablePrefix('host') . + " set status='" . $status . "' " . + " where id_host=" . $id_host; + return $stmt; + } + + /** + * SQL query to change the system status + * + * @param string $id_system the system id + * @param string $status the status to set + * + * @return string the sql statement + */ + function setSystemStatus($id_system, $status) + { + $stmt = 'update ' . $this->setTablePrefix('system') . + " set status='" . $status . "' " . + " where id_system=" . $id_system; + return $stmt; + } + + + /** + * SQL query to add an identity + * + * @param string $label the identity label + * @param string $username the username + * @param string $password the password + * @param int $id_system the system id + * @param int $id_shared_systems the systems id to share with + * + * @return string the sql statement + */ + function setIdentity($label, + $username, + $password, + $id_system, + $id_shared_systems) + { + $stmt = "insert into " . $this->setTablePrefix('identity_management') . + " (label,username,password,system,share_with) " . + " values ('" . $label . "','" . + $username . "','" . + $password . "'," . + $id_system . ",'" . + $id_shared_systems . "')"; + return $stmt; + } + + /** + * SQL query to get identities starting from system id + * + * @param string $id_system the system id + * + * @return string the sql statement + */ + function getIdentityBySystem($id_system) + { + $stmt = 'select id_identity,label from ' . + $this->setTablePrefix('identity_management') . + ' where system=' . $id_system . + ' or share_with like \'%#' . $id_system . '#%\''; + return $stmt; + } + + /** + * SQL query to get all identities + * a filter for system id may be used + * + * @param string $filter_system the system id + * + * @return string the sql statement + */ + function getIdentities($filter_system = '') + { + $filter_stmt = ''; + if ($filter_system != '' && $filter_system != '*') { + $filter_stmt .= ' where system=' . $filter_system; + } + $stmt = 'select id_identity,label,system,share_with from ' . + $this->setTablePrefix('identity_management') . + $filter_stmt . + ' order by system'; + return $stmt; + } + + /** + * SQL query to get an identity by label + * + * @param string $label the identity label + * + * @return string the sql statement + */ + function getIdentity($label) + { + $stmt = 'select * from ' . $this->setTablePrefix('identity_management') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to get an identity by id + * + * @param string $id_identity the identity id + * + * @return string the sql statement + */ + function getIdentityById($id_identity) + { + $stmt = 'select * from ' . $this->setTablePrefix('identity_management') . + ' where id_identity=' . $id_identity; + return $stmt; + } + + /** + * SQL query to all hosts + * + * @return string the sql statement + */ + function getHosts() + { + $stmt = 'select * from ' . $this->setTablePrefix('host') . + ' order by hostname'; + return $stmt; + } + + /** + * SQL query to get a host by id + * + * @param string $id_host the host id + * + * @return string the sql statement + */ + function getHostById($id_host) + { + $stmt = 'select * from ' . $this->setTablePrefix('host') . + ' where id_host=' . $id_host; + return $stmt; + } + + /** + * SQL query to update the host values + * + * @param int $id_host the host id + * @param string $ip the ip address + * @param string $hostname the hostname + * + * @return string the sql statement + */ + function updateHost($id_host, $ip, $hostname) + { + $stmt = 'update ' . $this->setTablePrefix('host') . + " set ip='" . $ip . "', " . + " hostname='" . $hostname . "' " . + ' where id_host=' . $id_host; + return $stmt; + } + + /** + * SQL query to update identity properties + * + * @param int $id_identity the identity id + * @param string $label the identity label + * @param string $username the username + * @param string $password the password + * + * @return string the sql statement + */ + function updateIdentity($id_identity, $label, $username, $password) + { + $stmt = 'update ' . $this->setTablePrefix('identity_management') . + " set label='" . $label . "', " . + " username='" . $username . "', " . + " password='" . $password . "' " . + ' where id_identity=' . $id_identity; + return $stmt; + } + + /** + * SQL query to update the info to share identity across systems + * + * @param int $id_identity the identity id + * @param string $shared_systems the system that share this identity + * + * @return string the sql statement + */ + function updateIdentityShare($id_identity, $shared_systems) + { + $stmt = 'update ' . $this->setTablePrefix('identity_management') . + " set share_with='" . $shared_systems . "' " . + ' where id_identity=' . $id_identity; + return $stmt; + } + + /** + * SQL query to get the system, host, db info's + * + * @param string $filter_system filter on system id + * + * @return string the sql statement + */ + function getSystemHostDb($filter_system = '') + { + $filter_stmt = ''; + if ($filter_system != '' && $filter_system != '*') { + $filter_stmt .= ' and a.id_system=' . $filter_system; + } + $stmt = 'select a.id_system, a.name, b.id_host, b.ip, b.hostname, ' . + 'c.id_db, c.label as db_label ' . + 'from ' . $this->setTablePrefix('system') . ' as a, ' . + $this->setTablePrefix('host') . ' as b, ' . + $this->setTablePrefix('db') . ' as c, ' . + $this->setTablePrefix('system_host_db') . ' as d ' . + ' where a.id_system=d.id_system and ' . + 'b.id_host=d.id_host and c.id_db=d.id_db ' . + $filter_stmt . + ' order by a.name,a.id_system,b.hostname,db_label'; + return $stmt; + } + + /** + * SQL query to remove a database by id + * + * @param int $id_db database id + * + * @return string the sql statement + */ + function deleteDatabase($id_db) + { + $stmt = array(); + $stmt[0] = 'delete from ' . $this->setTablePrefix('db') . + ' where id_db=' . $id_db; + $stmt[1] = 'delete from ' . $this->setTablePrefix('system_host_db') . + ' where id_db=' . $id_db; + return $stmt; + } + + /** + * SQL query to remove a host by id + * + * @param int $id_system the system id + * @param int $id_host the host id + * + * @return string the sql statement + */ + function deleteHost($id_system, $id_host) + { + $stmt = array(); + $stmt[0] = 'delete from ' . $this->setTablePrefix('system_host_db') . + ' where id_host=' . $id_host . + ' and id_system=' . $id_system; + $stmt[1] = 'delete from ' . $this->setTablePrefix('host') . + ' where id_host=' . $id_host . + ' and ((select count(*) from ' . + $this->setTablePrefix('system_host_db') . + ' where id_host=' . $id_host . ') = 0)'; + return $stmt; + } + + /** + * SQL query to delete a system by id + * + * @param int $id_system the system id + * + * @return string the sql statement + */ + function deleteSystem($id_system) + { + $stmt = 'delete from ' . + $this->setTablePrefix('system') . + ' where ' . + ' id_system=' . $id_system; + return $stmt; + } + + /** + * SQL query delete an identity by id + * + * @param int $id_identity the identity id + * + * @return string the sql statement + */ + function deleteIdentity($id_identity) + { + $stmt = 'delete from ' . + $this->setTablePrefix('identity_management') . + ' where ' . + ' id_identity=' . $id_identity; + return $stmt; + } + + /** + * SQL query to remove the system, host, db relation by system id + * + * @param int $id_system the system id + * + * @return string the sql statement + */ + function deleteSystemHostDb($id_system) + { + $stmt = 'delete from ' . + $this->setTablePrefix('system_host_db') . + ' where ' . + ' id_system=' . $id_system; + return $stmt; + } + + /** + * SQL query to get all db info's + * + * @return string the sql statement + */ + function getDb() + { + $stmt = 'select id_db, sid from ' . $this->setTablePrefix('db'); + return $stmt; + } + + /** + * SQL query to get minimal db info's by id + * + * @param int $id_db the database id + * + * @return string the sql statement + */ + function getDbById($id_db) + { + $stmt = 'select * from ' . $this->setTablePrefix('db') . + ' where id_db=' . $id_db; + return $stmt; + } + + /** + * SQL query to get all db info's by id + * + * @param int $id_db the database id + * + * @return string the sql statement + */ + function getDbInfo($id_db) + { + $stmt = 'select a.label,a.sid,a.port,b.description from ' . + $this->setTablePrefix('db') . ' as a,' . + $this->setTablePrefix('dbms_type') . ' as b' . + ' where a.id_db=' . $id_db . + ' and a.id_dbms_type=b.id_dbms_type'; + return $stmt; + } + + /** + * SQL query to get dbms lists + * + * @return string the sql statement + */ + function getdbmsList() + { + $stmt = 'select * from ' . $this->setTablePrefix('dbms_type'); + return $stmt; + } + + /** + * SQL query to add a database + * + * @param int $dbmsId the dbms id + * @param string $label the database label + * @param string $sid the database sid + * @param int $port the port + * + * @return string the sql statement + */ + function setDb($dbmsId, $label, $sid, $port) + { + $stmt = 'insert into ' . $this->setTablePrefix('db') . + ' (id_dbms_type, label, sid, port) values (' + . $dbmsId . ",'" + . $label . "','" + . $sid . "'," + . $port . ')'; + return $stmt; + } + + /** + * SQL query to update the database info's + * + * @param int $id_db the db id + * @param int $dbmsId the dbms id + * @param string $label the database label + * @param string $sid the database sid + * @param int $port the port + * + * @return string the sql statement + */ + function updateDb($id_db, $dbmsId, $label, $sid, $port) + { + $stmt = 'update ' . $this->setTablePrefix('db') . + ' set id_dbms_type=' . $dbmsId . + ", label='" . $label . "'," . + " sid='" . $sid . "'," . + ' port='. $port . + ' where id_db=' . $id_db; + return $stmt; + } + + /** + * SQL query to check if a database with the same label is already defined + * + * @param string $label the database name + * + * @return string the sql statement + */ + function checkExistsDb($label) + { + $stmt = "select id_db " . + "from " . $this->setTablePrefix('db') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to add a job + * + * @param int $shdId the system/host/db id + * @param int $jobTypeId the job type id + * @param string $label the job label + * @param string $description the description + * @param string $priority the priority + * @param string $parameters the parameters + * @param string $identity the identity + * @param string $properties the properties + * @param string $num_failures the number of failures + * + * @return string the sql statement + */ + function setJob($shdId, $jobTypeId, $label, $description, + $priority, $parameters, $identity, + $properties, $num_failures, $calendar) + { + $status = 'W'; + $msgExec = ''; + + $stmt = 'insert into ' . $this->setTablePrefix('jobs') + . ' (id_shd, id_job_type, label, description, status, priority,' + . ' msg_exec, parameters, identity, properties, num_failures, calendar) ' + . ' values (' + . $shdId . ',' + . $jobTypeId . ",'" + . $label . "','" + . rawurlencode(stripslashes($description)) . "','" + . $status . "'," + . $priority . ",'" + . $msgExec . "','" + . $parameters . "'," + . $identity . ",'" + . $properties . "'," + . $num_failures . "," + . $calendar . ')'; + return $stmt; + } + + /** + * SQL query to add a workflow + * + * @param string $label the workflow label + * @param string $description the description + * @param string $status the status + * @param int $id_system the system id + * @param int $id_calendar the calendar id + * + * @return string the sql statement + */ + function setWorkflow($label, $description, $status, $id_system, $id_calendar) + { + $stmt = 'insert into ' . $this->setTablePrefix('workflows') . + " (label,description,status,id_system,calendar) values ('" . + $label . "','" . $description . "','" . $status . + "'," . $id_system . "," . $id_calendar . ")"; + return $stmt; + } + + /** + * SQL query to update workflow properties + * + * @param int $id_workflow the workflow id + * @param string $label the workflow label + * @param string $description the description + * @param int $id_calendar the calendar id + * + * @return string the sql statement + */ + function updateWorkflow($id_workflow,$label,$description,$id_calendar) + { + $stmt = 'update ' . $this->setTablePrefix('workflows') . + ' set ' . + "label='" . $label . "', " . + "description='" . $description . "', " . + "calendar=" . $id_calendar . + ' where id_workflow=' . $id_workflow; + return $stmt; + } + + /** + * SQL query to set a workflow node + * + * @param int $id_workflow the wokflow id + * @param int $id_parent_node the node parent id (root = 0) + * @param int $id_to_exec the job or workflow id to execute + * @param int $type_to_exec the typology to execute (J=job, W=workflow) + * @param string $exec_condition the condition to be satisfied + * @param int $exec_properties the properties uses in object execution + * @param string $status the status of the node + * + * @return string the sql statement + */ + function setWorkflowNode($id_workflow, $id_parent_node, $id_to_exec, + $type_to_exec, $exec_condition, $exec_properties, $status) + { + $stmt = 'insert into ' . $this->setTablePrefix('workflow_nodes') . + ' (id_workflow,id_parent_node,id_to_exec, type_to_exec, ' . + ' exec_condition,exec_properties, status) values (' . + $id_workflow . "," . + $id_parent_node . "," . + $id_to_exec . ",'" . + $type_to_exec . "','" . + $exec_condition . "','" . + $exec_properties . "','" . + $status . "')"; + return $stmt; + } + + /** + * SQL query to update the workflow step properties + * + * @param int $id_workflow workflow id + * @param int $step step + * @param string $on_result define if the action must be performed + * on success or error + * @param int $go_to_step step to execute + * @param string $when define when execute the step + * + * @return string the sql statement + */ + function updateWorkflowNodeInfo($id_workflow, $id_node, $exec_condition, $exec_properties) + { + $stmt = 'update ' . $this->setTablePrefix('workflow_nodes') . ' set ' . + 'exec_condition="' . $exec_condition . '",' . + 'exec_properties="' . $exec_properties . '"' . + ' where id_workflow=' . $id_workflow . + ' and id_node=' . $id_node; + return $stmt; + } + + /** + * SQL query to update the workflow step on deleting action + * + * @param int $id_workflow workflow id + * @param int $step step + * @param string $on_result define if the action must be performed + * on success or error + * + * @return string the sql statement + */ + function updateWorkflowStepWorkflowOnDelete($id_workflow, $step, $on_result) + { + $stmt = 'update ' . $this->setTablePrefix('workflows_step') . ' set ' . + $on_result . '=0' . ',' . + $on_result . "_when='R'" . + ' where id_workflow=' . $id_workflow . + ' and ' . $on_result . '=' . $step; + return $stmt; + } + + /** + * SQL query to update the workflow step properties + * + * @param int $id_workflow workflow id + * @param int $id_job job id + * @param int $step step + * + * @return string the sql statement + */ + function updateWorkflowStepActions($id_workflow, $id_job, $step) + { + $stmt = 'update ' . $this->setTablePrefix('workflows_step') . ' set ' . + 'id_job=' . $id_job . + ' where id_workflow=' . $id_workflow . + ' and step=' . $step; + return $stmt; + } + + /** + * SQL query to update the workflow status + * + * @param int $id_workflow workflow id + * @param string $status status + * @param int $end_exec end execution time + * + * @return string the sql statement + */ + function updateWorkflowStatus($id_workflow, $status, $end_exec='') + { + $stmt = 'update ' . $this->setTablePrefix('workflows') . ' set ' . + "status='" . $status . "'"; + if ($end_exec != '') { + $stmt .= ',end_exec=' . $end_exec; + } + $stmt .= ' where id_workflow=' . $id_workflow; + return $stmt; + } + + /** + * SQL query to update the workflow step status + * + * @param int $id_workflow workflow id + * @param string $step step + * @param int $status status + * + * @return string the sql statement + */ + function updateWorkflowNodeStatus($id_workflow, $id_node, $status) + { + $stmt = 'update ' . $this->setTablePrefix('workflow_nodes') . ' set ' . + "status='" . $status . "'" . + ' where id_workflow=' . $id_workflow; + if ($id_node != '*') { + $stmt .= ' and id_node=' . $id_node; + } + return $stmt; + } + + /** + * SQL query to set the dynamic parameters ti use in the next workflow step + * + * @param int $id_workflow workflow id + * @param int $step step + * @param string $dynamic_params dynamic parameters + * + * @return string the sql statement + */ + function setWorkflowStepDynamicParams($id_workflow, $step, $dynamic_params) + { + $stmt = 'update ' . $this->setTablePrefix('workflows_step') . ' set ' . + "dynamic_params='" . $dynamic_params . "'" . + ' where id_workflow=' . $id_workflow . + ' and step=' . $step; + return $stmt; + } + + /** + * SQL query to retrieve the dynamic parameters for step + * + * @param int $id_job job id + * + * @return string the sql statement + */ + function getWorkflowStepDynamicParams($id_job) + { + $stmt = 'select dynamic_params from ' . + $this->setTablePrefix('workflows_step') . + ' where id_job=' . $id_job . + " and status='R'"; + return $stmt; + } + + /** + * SQL query to get info about a wf node + * + * @param int $id_workflow workflow id + * @param int $id_node node id + * + * @return string the sql statement + */ + function getWorkflowNodeInfo($id_workflow, $id_node) + { + $stmt = 'select * ' . + 'from ' . $this->setTablePrefix('workflow_nodes') . + ' where id_workflow=' . $id_workflow . + ' and id_node=' . $id_node; + return $stmt; + } + + /** + * SQL query to check for running workflow + * + * @param int $id_job job id + * + * @return string the sql statement + */ + function checkWorkflowNodeInfoByIdJob($id_job) + { + $stmt = 'select * ' . + 'from ' . $this->setTablePrefix('workflow_nodes') . + ' where id_to_exec=' . $id_job . + " and status='R' and type_to_exec = 'J'"; + return $stmt; + } + + /** + * SQL query to check for running nodes in workflow + * + * + * @return string the sql statement + */ + function checkWorkflowRunningNodes() + { + $stmt = 'select * ' . + 'from ' . $this->setTablePrefix('workflow_nodes') . + " where status in ('R','W')"; + return $stmt; + } + + /** + * SQL query to delete worklow node + * + * @param int $id_workflow workflow id + * @param int $id_node node_id + * + * @return string the sql statement + */ + function deleteWorkflowNode($id_workflow, $id_node) + { + $stmt = 'delete from ' . $this->setTablePrefix('workflow_nodes') . + ' where id_workflow=' . $id_workflow; + if ($id_node != '*') { + $stmt .=' and id_node=' . $id_node; + } + return $stmt; + } + + /** + * SQL query to delete a worklow + * + * @param int $id_workflow workflow id + * + * @return string the sql statement + */ + function deleteWorkflow($id_workflow) + { + $stmt = 'delete from ' . $this->setTablePrefix('workflows') . + ' where id_workflow=' . $id_workflow; + return $stmt; + } + + /** + * SQL query to delete the defined crontab for the specified worklow + * + * @param int $id_workflow workflow id + * + * @return string the sql statement + */ + function deleteWorkflowCrontab($id_workflow) + { + $stmt = 'delete from ' . $this->setTablePrefix('workflow_crontab') . + ' where id_workflow=' . $id_workflow; + return $stmt; + } + + /** + * SQL query to copy a job + * + * @param string $jobId the job id + * @param string $new_label the new label + * + * @return string the sql statement + */ + function copyJob($jobId, $new_label) + { + $stmt = "insert into " . $this->setTablePrefix('jobs') + . ' (id_shd, id_job_type, label, description, status, priority,' + . ' msg_exec, parameters, identity, properties, num_failures) ' + . " select id_shd,id_job_type,'" + . $new_label + . "',description,'L',priority,''," + . 'parameters,identity,properties,num_failures from ' + . $this->setTablePrefix('jobs') + . ' where id_job =' + . $jobId; + return $stmt; + } + + /** + * SQL query to copy a workflow + * + * @param string $id_workflow the workflow id + * @param string $new_label the new label + * + * @return string the sql statement + */ + function copyWorkflow($id_workflow, $new_label) + { + $stmt = 'insert into ' . $this->setTablePrefix('workflows') + . ' (label, description, status, id_system) ' + . " select '" + . $new_label + . "',description, status, id_system from " + . $this->setTablePrefix('workflows') + . ' where id_workflow =' + . $id_workflow; + return $stmt; + } + + /** + * SQL query to copy a workflow step + * + * @param string $id_workflow the workflow id + * @param string $new_id_workflow the new workflow id + * + * @return string the sql statement + */ + function copyWorkflowStep($id_workflow, $new_id_workflow) + { + $stmt = 'insert into ' . $this->setTablePrefix('workflows_step') + . ' (id_workflow,id_job,step,on_success,on_success_when,on_error,' + . 'on_error_when,status,dynamic_params) ' + . ' select ' + . $new_id_workflow + . ',id_job,step,on_success,on_success_when,on_error,on_error_when,' + .'status,dynamic_params from ' + . $this->setTablePrefix('workflows_step') + . ' where id_workflow =' + . $id_workflow; + return $stmt; + } + + /** + * SQL query to copy a workflow crontab + * + * @param string $id_workflow the workflow id + * @param string $new_id_workflow the new workflow id + * + * @return string the sql statement + */ + function copyWorkflowCrontab($id_workflow, $new_id_workflow) + { + $stmt = 'insert into ' . $this->setTablePrefix('workflow_crontab') + . ' (id_workflow,crontab_m,crontab_h,crontab_dom,' + .'crontab_mon,crontab_dow,schedule_type) ' + . ' select ' + . $new_id_workflow + . ',crontab_m,crontab_h,crontab_dom,crontab_mon,' + .'crontab_dow,schedule_type from ' + . $this->setTablePrefix('workflow_crontab') + . ' where id_workflow =' + . $id_workflow; + return $stmt; + } + + /** + * SQL query to update the job properties + * + * @param int $jobId the job id + * @param int $shdId the system/host/db id + * @param int $jobTypeId the job type id + * @param string $label the job label + * @param string $description the description + * @param string $priority the priority + * @param string $properties the properties + * @param string $parameters the parameters + * @param string $identity the identity + * + * @return string the sql statement + */ + function updateJob($jobId, $shdId, $jobTypeId, $label, $description, $priority, + $properties, $parameters='', $identity, $calendar) + { + $stmt = 'update ' . $this->setTablePrefix('jobs') . ' set ' . + ' id_shd=' . $shdId . ', ' . + ' id_job_type=' . $jobTypeId . ', ' . + " label='" . $label . "', " . + " description='" . rawurlencode(stripslashes($description)) . "', " . + ' priority=' . $priority . ', ' . + " parameters='" . $parameters . "', " . + ' identity=' . $identity . ', ' . + ' calendar=' . $calendar . ', ' . + " properties='" . $properties . "' " . + ' where id_job=' . $jobId; + return $stmt; + } + + /** + * SQL query to add crontab for job + * + * @param int $jobId the job id + * @param string $minute the crontab for minutes + * @param string $hour the crontab for hour + * @param string $day the crontab for day + * @param string $month the crontab for month + * @param string $dayweek the crontab for dayweek + * @param string $schedule_type the type of schedule + * + * @return string the sql statement + */ + function setJobCrontab($jobId, $minute, $hour, + $day, $month, $dayweek, $schedule_type) + { + $stmt = "insert into " . $this->setTablePrefix('job_crontab') . " values (" + . $jobId . ",'" + . $minute . "','" + . $hour . "','" + . $day . "','" + . $month . "','" + . $dayweek . "','" + . $schedule_type . "')"; + return $stmt; + } + + /** + * SQL query to add crontab for workflow + * + * @param int $id_workflow the workwflow id + * @param string $minute the crontab for minutes + * @param string $hour the crontab for hour + * @param string $day the crontab for day + * @param string $month the crontab for month + * @param string $dayweek the crontab for dayweek + * @param string $schedule_type the type of schedule + * + * @return string the sql statement + */ + function setWorkflowCrontab($id_workflow, $minute, $hour, $day, + $month, $dayweek, $schedule_type) + { + $stmt = 'insert into ' . $this->setTablePrefix('workflow_crontab') . + ' values (' + . $id_workflow . ",'" + . $minute . "','" + . $hour . "','" + . $day . "','" + . $month . "','" + . $dayweek . "','" + . $schedule_type . "')"; + return $stmt; + } + + /** + * SQL query to copy the job crontab + * + * @param int $jobId the job id + * + * @return string the sql statement + */ + function copyJobCrontab($jobId) + { + $stmt = 'insert into ' . $this->setTablePrefix('job_crontab') + . ' (crontab_m,crontab_h,crontab_dom,crontab_mon,crontab_dow,' + .'schedule_type) ' + . ' select crontab_m,crontab_h,crontab_dom,crontab_mon,' + .'crontab_dow,schedule_type from ' + . $this->setTablePrefix('job_crontab') + . ' where id_job =' + . $jobId; + return $stmt; + } + + /** + * SQL query to update crontab values + * + * @param int $jobId the job id + * @param string $minute the crontab for minutes + * @param string $hour the crontab for hour + * @param string $day the crontab for day + * @param string $month the crontab for month + * @param string $dayweek the crontab for dayweek + * @param string $schedule_type the type of schedule + * + * @return string the sql statement + */ + function updateJobCrontab($jobId, $minute, $hour, + $day, $month, $dayweek, $schedule_type) + { + $stmt = "update " . $this->setTablePrefix('job_crontab') . " set " . + " crontab_m='" . $minute . "', " . + " crontab_h='" . $hour . "', " . + " crontab_dom='" . $day . "', " . + " crontab_mon='" . $month . "', " . + " crontab_dow='" . $dayweek . "'," . + " schedule_type='" . $schedule_type . "'" . + " where id_job=" . $jobId; + return $stmt; + } + + /** + * SQL query to set the system, host, db relation + * + * @param int $id_workflow the workflow id + * @param string $minute the crontab for minutes + * @param string $hour the crontab for hour + * @param string $day the crontab for day + * @param string $month the crontab for month + * @param string $dayweek the crontab for dayweek + * @param string $schedule_type the type of schedule + * + * @return string the sql statement + */ + function updateWorkflowCrontab($id_workflow, $minute, $hour, + $day, $month, $dayweek, $schedule_type) + { + $stmt = "update " . $this->setTablePrefix('workflow_crontab') . " set " . + " crontab_m='" . $minute . "', " . + " crontab_h='" . $hour . "', " . + " crontab_dom='" . $day . "', " . + " crontab_mon='" . $month . "', " . + " crontab_dow='" . $dayweek . "'," . + " schedule_type='" . $schedule_type . "'" . + " where id_workflow=" . $id_workflow; + return $stmt; + } + + /** + * SQL query to retrieve all jobs with relative systems + * + * @param string $filter_job_label filter job label + * @param string $filter_system filter system id + * @param string $filter_status filter job status + * @param string $filter_result filter job result + * @param string $orderby filter order by + * + * @return string the sql statement + */ + function getSystemJobs($filter_job_label = '', + $filter_system = '', + $filter_status = '', + $filter_result = '', + $orderby = '') + { + $filter_stmt = ''; + if ($filter_job_label != '' && $filter_job_label != '*') { + $filter_stmt .= ' and a.label like \'%' . addslashes($filter_job_label) . '%\''; + } + if ($filter_system != '' && $filter_system != '*') { + $filter_stmt .= ' and b.id_system=' . $filter_system; + } + if ($filter_status != '' && $filter_status != '*') { + $filter_stmt .= ' and a.status=\'' . $filter_status . '\''; + } + if ($filter_result != '' && $filter_result != '*') { + $filter_stmt .= ' and a.status_exec=' . $filter_result; + } + if ($orderby == '') { + $orderby = ' b.name,a.label desc'; + } + $stmt = 'select a.label, a.description, a.end_exec, a.status, '. + 'a.status_exec, a.msg_exec, b.id_system, b.name, d.*, ' . + 'e.calendar as calendars ' . + ' from ' . + $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('system') . ' as b, ' . + $this->setTablePrefix('system_host_db') . ' as c, ' . + $this->setTablePrefix('job_crontab') . ' as d, ' . + $this->setTablePrefix('calendars') . ' as e ' . + ' where a.id_shd=c.id_shd ' . + ' and b.id_system=c.id_system' . + ' and a.id_job=d.id_job' . + ' and a.calendar=e.id_calendar ' . + $filter_stmt . + ' order by ' . $orderby; + return $stmt; + } + + /** + * SQL query to retrieve the last step added + * + * @param int $id_workflow workflow id + * + * @return string the sql statement + */ + function getLastWorkflowStep($id_workflow) + { + $stmt = 'select max(step) ' . + ' from ' . + $this->setTablePrefix('workflows_step') . + " where id_workflow=" . $id_workflow; + return $stmt; + } + + /** + * SQL query to retrieve all workflows + * + * @param string $filter_workflow_label filter workflow label + * @param string $filter_workflow_status filter workflow status + * + * @return string the sql statement + */ + function getWorkflows($filter_workflow_label='', $filter_workflow_status='') + { + $filter_stmt = ''; + if ($filter_workflow_label != '' && $filter_workflow_label != '*') { + $filter_stmt .= ' and a.label like \'%' . + addslashes($filter_workflow_label) . '%\''; + } + if ($filter_workflow_status != '' && $filter_workflow_status != '*') { + $filter_stmt .= ' and a.status like \'%' . + $filter_workflow_status . '%\''; + } + $stmt = 'select a.*,b.*,c.calendar as calendars, d.name as system_label ' . + ' from ' . + $this->setTablePrefix('workflows') . ' as a, ' . + $this->setTablePrefix('workflow_crontab') . ' as b, ' . + $this->setTablePrefix('calendars') . ' as c, ' . + $this->setTablePrefix('system') . ' as d ' . + ' where a.id_workflow=b.id_workflow ' . + ' and a.calendar=c.id_calendar ' . + ' and a.id_system=d.id_system ' . + $filter_stmt . + ' order by a.label'; + return $stmt; + } + + /** + * SQL query to retrieve all workflows label + * + * @param int $id_job the workflow id + * + * @return string the sql statement + */ + function getWorkflowsLabel($id_wf = '') + { + $stmt = 'select id_workflow, label ' . + ' from ' . $this->setTablePrefix('workflows'); + if ($id_job != '') { + $stmt .= ' where id_workflow=' . $id_wf; + } + return $stmt; + } + + /** + * SQL query to retrieve minimal workflow info + * + * @param int $id_workflow workflow id + * + * @return string the sql statement + */ + function getWorkflowBasicInfoById($id_workflow) + { + $stmt = 'select a.*, b.* ' . + ' from ' . + $this->setTablePrefix('workflows') . ' as a, ' . + $this->setTablePrefix('workflow_crontab') . ' as b ' . + ' where a.id_workflow=b.id_workflow and a.id_workflow=' . + $id_workflow; + return $stmt; + } + + /** + * SQL query to retrieve workflow info + * + * @param int $id_workflow workflow id + * + * @return string the sql statement + */ + function getWorkflowInfoById($id_workflow, $id_parent_node = '*', $exec_condition = '*') + { + $stmt = 'select * ' . + ' from ' . + $this->setTablePrefix('workflow_nodes') . + ' where id_workflow=' . $id_workflow; + if ($id_parent_node != '*') { + $stmt .= ' and id_parent_node = ' . $id_parent_node; + } + if ($exec_condition != '*') { + $stmt .= ' and exec_condition = ' . $exec_condition; + } + $stmt .= ' order by id_node'; + return $stmt; + } + + /** + * SQL query to retrieve all notifications with relative systems + * + * @param string $filter_job_label filter jobs label + * @param string $filter_system filter system + * @param string $filter_notify_type filter notify_type + * @param string $filter_notify_on filter notify_on + * + * @return string the sql statement + */ + function getSystemJobsNotify($filter_job_label = '', + $filter_system = '', + $filter_notify_type = '', + $filter_notify_on = '') + { + $filter_stmt = ''; + if ($filter_job_label != '' && $filter_job_label != '*') { + $filter_stmt .= ' and a.label like \'%' . addslashes($filter_job_label) . '%\''; + } + if ($filter_system != '' && $filter_system != '*') { + $filter_stmt .= ' and b.id_system=' . $filter_system; + } + if ($filter_notify_type != '' && $filter_notify_type != '*') { + $filter_stmt .= ' and d.id_notify_type=' . $filter_notify_type; + } + if ($filter_notify_on != '' && $filter_notify_on != '*') { + $filter_stmt .= " and d.notify_on like '%-" . $filter_notify_on . "-%'"; + } + $stmt = 'select a.label as job_label, b.id_system, b.name as system_name,'. + ' d.id_notify, d.notify_on, d.parameters, e.label as notify_label' . + ' from ' . + $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('system') . ' as b, ' . + $this->setTablePrefix('system_host_db') . ' as c, ' . + $this->setTablePrefix('notify') . ' as d, ' . + $this->setTablePrefix('notify_type') . ' as e ' . + ' where a.id_shd=c.id_shd ' . + ' and b.id_system=c.id_system' . + ' and a.id_job=d.id_job' . + ' and d.id_notify_type=e.id_notify_type' . + $filter_stmt . + ' order by b.name,job_label'; + return $stmt; + } + + /** + * SQL query to retrieve the job type list + * + * @return string the sql statement + */ + function getJobTypeList() + { + $stmt = 'select * ' . + ' from ' . $this->setTablePrefix('job_type') . + ' order by category,label'; + return $stmt; + } + + /** + * SQL query to retrieve the job type label + * + * @param int $jobTypeId the job type id + * + * @return string the sql statement + */ + function getJobTypeLabel($jobTypeId) + { + $stmt = 'select label, category ' . + ' from ' . $this->setTablePrefix('job_type') . + ' where id_job_type=' . $jobTypeId; + return $stmt; + } + + /** + * SQL query to check if a job with the same label is already defined + * + * @param string $label the job label + * + * @return string the sql statement + */ + function checkExistsJob($label) + { + $stmt = 'select id_job ' . + ' from ' . $this->setTablePrefix('jobs') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to check if a workflow with the same label is already defined + * + * @param string $label the workflow label + * + * @return string the sql statement + */ + function checkExistsWorkflow($label) + { + $stmt = "select id_workflow " . + " from " . $this->setTablePrefix('workflows') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to check if a plugin with the same label is already defined + * + * @param string $label the plugin label + * + * @return string the sql statement + */ + function checkExistsPlugin($label) + { + $stmt = 'select id_job_type ' . + ' from ' . $this->setTablePrefix('job_type') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to check if a notification plugin with the same + * label is already defined + * + * @param string $label the notification plugin label + * + * @return string the sql statement + */ + function checkExistsPluginNotify($label) + { + $stmt = 'select id_notify_type ' . + ' from ' . $this->setTablePrefix('notify_type') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to check if a notification is associated with the job + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function checkJobNotify($id_job) + { + $stmt = 'select count(id_job) ' . + ' from ' . $this->setTablePrefix('notify') . + " where id_job=" . $id_job; + return $stmt; + } + + /** + * SQL query to check if a job is associated with the database + * + * @param string $id_db the database id + * + * @return string the sql statement + */ + function checkJobDatabase($id_db) + { + $stmt = 'select id_job, label ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_shd in (' . + ' select id_shd ' . + ' from ' . + $this->setTablePrefix('system_host_db') . + ' where id_db=' . $id_db . + ')'; + return $stmt; + } + + /** + * SQL query to check if a job is associated with the system + * + * @param string $id_system the system id + * + * @return string the sql statement + */ + function checkJobSystem($id_system) + { + $stmt = 'select id_job, label ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_shd in (' . + ' select id_shd' . + ' from ' . + $this->setTablePrefix('system_host_db') . + ' where id_system=' . $id_system . + ')'; + return $stmt; + } + + /** + * SQL query to check if a plugin is associated with any job + * + * @param string $id_job_type the plugin type + * + * @return string the sql statement + */ + function checkJobPlugin($id_job_type) + { + $stmt = 'select id_job, label ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_job_type=' . $id_job_type; + return $stmt; + } + + /** + * SQL query to check if a notification plugin + * is associated with any job + * + * @param string $id_notify_type the plugin notification type + * + * @return string the sql statement + */ + function checkNotifyPlugin($id_notify_type) + { + $stmt = 'select id_notify ' . + ' from ' . $this->setTablePrefix('notify') . + ' where id_notify_type=' . $id_notify_type; + return $stmt; + } + + /** + * SQL query to check if the host is associated with any job + * + * @param string $id_system the system id + * @param string $id_host the host id + * + * @return string the sql statement + */ + function checkJobHost($id_system, $id_host) + { + $stmt = 'select id_job, label ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_shd in (' . + ' select id_shd ' . + ' from ' . + $this->setTablePrefix('system_host_db') . + ' where id_host=' . $id_host . + ' and id_system=' . $id_system . + ')'; + return $stmt; + } + + /** + * SQL query to check if the identity is associated with any job + * + * @param string $id_identity the identity id + * + * @return string the sql statement + */ + function checkJobIdentity($id_identity) + { + $stmt = 'select label ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where identity=' . $id_identity; + return $stmt; + } + + /** + * SQL query to remove a plugin + * + * @param int $id_job_type the job type id + * + * @return string the sql statement + */ + function deletePlugin($id_job_type) + { + $stmt = 'delete from ' . $this->setTablePrefix('job_type') . + ' where id_job_type=' . $id_job_type; + return $stmt; + } + + /** + * SQL query to remove a notification plugin + * + * @param int $id_notify_type the notification type id + * + * @return string the sql statement + */ + function deletePluginNotification($id_notify_type) + { + $stmt = 'delete from ' . $this->setTablePrefix('notify_type') . + ' where id_notify_type=' . $id_notify_type; + return $stmt; + } + + /** + * SQL query to remove a job + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function deleteJob($id_job) + { + $stmt = array(); + $stmt[0] = 'delete from ' . $this->setTablePrefix('jobs') . + ' where id_job=' . $id_job; + $stmt[1] = 'delete from ' . $this->setTablePrefix('job_crontab') . + ' where id_job=' . $id_job; + $stmt[2] = 'delete from ' . $this->setTablePrefix('jobs_archive') . + ' where id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to retrieve all job labels + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function getJobsLabel($id_job = '') + { + $stmt = 'select id_job, label ' . + ' from ' . $this->setTablePrefix('jobs'); + if ($id_job != '') { + $stmt .= ' where id_job=' . $id_job; + } + return $stmt; + } + + /** + * SQL query to retrieve the job type + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function getJobType($id_job) + { + $stmt = 'select b.label, b.category ' . + ' from ' . + $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('job_type') . ' as b ' . + ' where a.id_job_type=b.id_job_type ' . + ' and a.id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to retrieve the job result and execution message + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function getJobStatusDetail($id_job) + { + $stmt = 'select status, msg_exec ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to retrieve the job status + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function getJobStatus($id_job) + { + $stmt = 'select status, id_shd ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to retrieve the job minimal info + * + * @param int $id_job the job id + * + * @return string the sql statement + */ + function getJobBasicInfo($id_job) + { + $stmt = 'select label,description ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to set the job status + * + * @param int $id_job the job id + * @param string $newStatus the new status + * @param string $message the message to display + * + * @return string the sql statement + */ + function setJobStatus($id_job, $newStatus, $message='') + { + $msg_statement = ''; + if ($message != '') { + $msg_statement = ", msg_exec='" . $message . "'"; + } + $stmt = 'update ' . $this->setTablePrefix('jobs') . ' set ' . + " status='" . $newStatus . "' " . + $msg_statement . + ' where id_job=' . $id_job; + return $stmt; + } + + /** + * SQL query to retrieve info needed to execute the specified job + * + * @param string $label the job label + * + * @return string the sql statement + */ + function getJobsToExecRPC($label) + { + $stmt = 'select distinct a.id_job, b.label, b.category ' . + 'from ' . $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('job_type') . ' as b ' . + 'where a.id_job_type=b.id_job_type ' . + "and a.status='W' " . + "and a.label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to retrieve all jobs in timeout + * + * @return string the sql statement + */ + function getJobsTimeout() + { + + $timeout = time()-($GLOBALS['conf']['env']['job_timeout']) * 60; + + $stmt = 'select a.id_job ' . + 'from ' . $this->setTablePrefix('jobs') . ' as a ' . + "where a.status='R' " . + "and a.start_exec < " . + $timeout; + return $stmt; + } + + /** + * SQL query to retrieve all jobs to execute + * + * @return string the sql statement + */ + function getJobsToExec($available_shd) + { + + //Note: length(d.crontab_dom)=85 if crontab_dom is * + + $stmt = 'select distinct a.id_job, c.label, c.category ' . + 'from ' . $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('job_type') . ' as c, ' . + $this->setTablePrefix('job_crontab') . ' as d, ' . + $this->setTablePrefix('calendars') . ' as e ' . + 'where a.id_job_type=c.id_job_type ' . + "and (a.calendar=0 or (a.calendar=e.id_calendar and e.calendar like '%#" . mktime(0,0,0) . "#%' )) " . + 'and a.id_shd not in (' . $available_shd . ') ' . + 'and a.id_job=d.id_job ' . + "and a.status='W' " . + "and (d.schedule_type='A' or d.schedule_type='J') " . + "and d.crontab_m like '%-" . date('i') . "-%' " . + "and d.crontab_h like '%-" . date('G') . "-%' " . + "and d.crontab_mon like '%-" . date('n') . "-%' " . + 'and (' . + ' (length(d.crontab_dom) != 85 and ' . + "length(d.crontab_dow) != 15 and (d.crontab_dom like '%-" . + date('j') . + "-%' or d.crontab_dow like '%-" . date('w') . "-%')) ". + ' or ' . + " (d.crontab_dom like '%-" . date('j') . + "-%' and d.crontab_dow like '%-" . date('w') . "-%')" . + ' ) ' . + 'order by a.priority desc'; + return $stmt; + } + + /** + * Query to get all jobs part of workflow to execute + * + * @return string $stmt The sql statement + */ + function getJobsWorkflowToExec($available_shd) + { + + //Note: length(d.crontab_dom)=85 if crontab_dom is * + + $stmt = 'select distinct b.id_workflow, b.id_node ' . + 'from ' . $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('workflow_nodes') . ' as b, ' . + //$this->setTablePrefix('job_type') . ' as c, ' . + $this->setTablePrefix('job_crontab') . ' as d, ' . + $this->setTablePrefix('workflows') . ' as e, ' . + $this->setTablePrefix('calendars') . ' as f ' . + //'where a.id_job_type=c.id_job_type ' . + 'where ' . + "(a.calendar=1 or (a.calendar=f.id_calendar and f.calendar like '%#" . mktime(0,0,0) . "#%' )) " . + 'and a.id_shd not in (' . $available_shd . ') ' . + //'and a.id_job=b.id_job ' . + 'and b.id_to_exec=d.id_job ' . + //'and b.id_workflow=e.id_workflow ' . + "and a.status='W' " . + "and e.status='R' and b.status='W' " . + "and d.schedule_type='T' " . + "and d.crontab_m like '%-" . date('i') . "-%' " . + "and d.crontab_h like '%-" . date('G') . "-%' " . + "and d.crontab_mon like '%-" . date('n') . "-%' " . + 'and (' . + ' (length(d.crontab_dom) != 85 and ' . + "length(d.crontab_dow) != 15 and (d.crontab_dom like '%-" . + date('j') . + "-%' or d.crontab_dow like '%-" . date('w') . "-%')) ". + " or " . + " (d.crontab_dom like '%-" . date('j') . + "-%' and d.crontab_dow like '%-" . + date('w') . "-%')" . + ' ) ' . + 'order by a.priority desc'; + return $stmt; + } + + /** + * Query to get all workflows to execute + * + * @return string $stmt The sql statement + */ + function getWorkflowsToExec($available_shd) + { + + //Note: length(d.crontab_dom)=85 if crontab_dom is * + + $stmt = 'select distinct a.id_workflow, b.id_node '. + 'from ' . $this->setTablePrefix('workflows') . ' as a, ' . + $this->setTablePrefix('workflow_nodes') . ' as b, ' . + $this->setTablePrefix('calendars') . ' as c, ' . + $this->setTablePrefix('workflow_crontab') . ' as d ' . + "where (a.calendar=1 or (a.calendar=c.id_calendar and c.calendar like '%#" . mktime(0,0,0) . "#%' )) " . + "and a.status='W' " . + "and b.id_parent_node = 0 " . + "and a.id_workflow=b.id_workflow " . + "and b.id_workflow=d.id_workflow " . + "and d.schedule_type='A' " . + "and d.crontab_m like '%-" . date('i') . "-%' " . + "and d.crontab_h like '%-" . date('G') . "-%' " . + "and d.crontab_mon like '%-" . date('n') . "-%' " . + "and (" . + ' (length(d.crontab_dom) != 85 and ' . + "length(d.crontab_dow) != 15 and (d.crontab_dom like '%-" . + date('j') . "-%' or d.crontab_dow like '%-" . + date('w') . "-%')) ". + ' or ' . + " (d.crontab_dom like '%-" . date('j') . + "-%' and d.crontab_dow like '%-" . date('w') . "-%')" . + ' ) '; + return $stmt; + } + + /** + * SQL query to retrieve all info for the jobs to execute + * + * @param string $jobId the job id + * + * @return string the sql statement + */ + function getJobToExecInfo ($jobId) + { + $stmt = 'select ' . + 'a.parameters, a.identity, b.ip, c.sid, c.port, '. + 'd.label as dbms, e.id_system ' . + 'from ' . $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('host') . ' as b, ' . + $this->setTablePrefix('db') . ' as c, ' . + $this->setTablePrefix('dbms_type') . ' as d, ' . + $this->setTablePrefix('system_host_db') . ' as e ' . + ' where a.id_shd=e.id_shd ' . + ' and b.id_host=e.id_host ' . + ' and c.id_db=e.id_db ' . + ' and c.id_dbms_type=d.id_dbms_type ' . + ' and a.id_job=' . $jobId; + return $stmt; + } + + /** + * SQL query to retrieve all info for the jobs + * + * @param string $jobId the job id + * + * @return string the sql statement + */ + function getJobInfoById($jobId) + { + $stmt = 'select ' . + ' a.id_job, a.label, a.description, a.priority, a.parameters, '. + 'a.identity, a.calendar, a.properties, a.id_job_type, b.id_system, b.id_host,'. + ' b.id_db, c.label as job_type_label, '. + 'c.category as job_type_category, d.* ' . + ' from ' . + $this->setTablePrefix('jobs') . ' as a, ' . + $this->setTablePrefix('system_host_db') . ' as b, ' . + $this->setTablePrefix('job_type') . ' as c, ' . + $this->setTablePrefix('job_crontab') . ' as d ' . + ' where ' . + ' a.id_shd=b.id_shd and a.id_job_type=c.id_job_type and '. + ' a.id_job=d.id_job and' . + ' a.id_job=' . $jobId; + return $stmt; + } + + /** + * SQL query to retrieve all job properties + * + * @param string $jobId the job id + * + * @return string the sql statement + */ + function getJobProperties($jobId) + { + $stmt = 'select ' . + ' properties, num_failures' . + ' from ' . + $this->setTablePrefix('jobs') . + ' where ' . + ' id_job=' . $jobId; + return $stmt; + } + + /** + * SQL query to set the job execution start time + * + * @param int $jobId the job id + * @param string $msgExec the execution message + * + * @return string the sql statement + */ + function setJobStart($jobId, $msgExec) + { + $stmt = 'update ' . $this->setTablePrefix('jobs') . ' set ' . + "status='R'," . + 'start_exec=' . time() . ', ' . + "msg_exec='" . rawurlencode($msgExec) . "'" . + ' where id_job=' . $jobId; + return $stmt; + } + + /** + * SQL query to set the job execution end values + * + * @param int $jobId the job id + * @param int $execStatus the execution status + * @param string $msgExec the execution message + * @param int $num_failures the number of failures + * + * @return string the sql statement + */ + function setJobEnd($jobId, $execStatus, $msgExec, $num_failures=0) + { + $stmt = 'update ' . $this->setTablePrefix('jobs') . ' set ' . + "status='W'," . + 'end_exec=' . time() . ', ' . + 'status_exec=' . $execStatus . ', ' . + "msg_exec='" . rawurlencode($msgExec) . "', " . + ' num_failures=' . $num_failures . + ' where id_job=' . $jobId; + return $stmt; + } + + /** + * SQL query to retrieve the archived job results + * + * @param int $jobId the job id + * + * @return string the sql statement + */ + function getArchivedJobResults($jobId) + { + $stmt = 'select * from ' . $this->setTablePrefix('jobs_archive') . + ' where id_job=' . $jobId . + ' order by end_exec desc'; + return $stmt; + } + + /** + * SQL query archive the result for the specified job + * + * @param int $jobId the job id + * + * @return string the sql statement + */ + function archiveJobResult($jobId) + { + $stmt = 'insert into ' . $this->setTablePrefix('jobs_archive') . + ' select id_job,start_exec,end_exec,status_exec,msg_exec from ' . + $this->setTablePrefix('jobs') . + ' where id_job=' . + $jobId; + return $stmt; + } + + /** + * SQL query to apply the specified retention on the archived results + * + * @param int $jobId the job id + * @param int $date the retention time + * + * @return string the sql statement + */ + function applyRetentionPolicy($jobId, $date) + { + $stmt = 'delete from ' . $this->setTablePrefix('jobs_archive') . + ' where id_job=' . $jobId . + ' and end_exec < ' . $date; + return $stmt; + } + + /** + * SQL query to add a notification + * + * @param int $jobId the job id + * @param int $notifyTypeId the notification type id + * @param string $notifyInfo the notification info + * @param string $notify_on define if sends the notification + * on error or success + * @param string $id_identity the identity to use to send the notification + * + * @return string the sql statement + */ + function setNotify($jobId, $notifyTypeId, $notifyInfo, $notify_on, $id_identity) + { + $stmt = 'insert into ' . $this->setTablePrefix('notify') + . ' (id_job, id_notify_type, parameters, notify_on, identity)' + . ' values (' + . $jobId . ',' + . $notifyTypeId . ",'" + . $notifyInfo . "','" + . $notify_on . "'," + . $id_identity . ')'; + return $stmt; + } + + /** + * SQL query to copy a notification + * + * @param int $notifyId the notification id + * + * @return string the sql statement + */ + function copyNotify($notifyId) + { + $stmt = 'insert into ' + . $this->setTablePrefix('notify') + . ' (id_job, id_notify_type, parameters, notify_on, identity) ' + . ' select id_job, id_notify_type, parameters, ' + . ' notify_on,identity from ' + . $this->setTablePrefix('notify') + . ' where id_notify =' + . $notifyId; + return $stmt; + } + + /** + * SQL query to update a notification values + * + * @param int $id_job the job id + * @param int $id_notify the notification id + * @param string $notifyInfo the notification info + * @param string $notify_on define if sends the notification + * on error or success + * @param string $id_identity the identity to use to send the notification + * + * @return string the sql statement + */ + function updateNotify($id_job, $id_notify, $notifyInfo, $notify_on, $id_identity) + { + $stmt = 'update ' . $this->setTablePrefix('notify') . + " set parameters='" . $notifyInfo . "', " . + ' id_job=' . $id_job . ', ' . + " notify_on='" . $notify_on . "', " . + ' identity=' . $id_identity . + ' where id_notify=' . $id_notify; + return $stmt; + } + + /** + * SQL query to remove a notification + * + * @param int $id_notify the notification id + * + * @return string the sql statement + */ + + function deleteNotify($id_notify) + { + $stmt = 'delete from ' . $this->setTablePrefix('notify') . + ' where id_notify=' . $id_notify; + return $stmt; + } + + /** + * SQL query to retrieve all notification associated with the specified job + * + * @param int $jobId the job id + * @param int $notify_on the notify_on value to filter on + * + * @return string the sql statement + */ + function getNotifyInfoByJobId($jobId, $notify_on='') + { + $stmt = 'select a.id_job, a.parameters, a.notify_on, b.label, a.identity ' . + 'from ' . $this->setTablePrefix('notify') . ' as a, ' . + $this->setTablePrefix('notify_type') . ' as b ' . + 'where a.id_notify_type=b.id_notify_type ' . + 'and a.id_job=' . $jobId; + if ($notify_on != '') { + $stmt .= " and a.notify_on like '%-" . $notify_on . "-%'"; + } + return $stmt; + } + + /** + * SQL query to retrieve all the properties for the specified notification + * + * @param int $id_notify the notification id + * + * @return string the sql statement + */ + function getNotifyInfoById($id_notify) + { + $stmt = 'select * ' . + 'from ' . $this->setTablePrefix('notify') . ' as a ' . + 'where id_notify=' . $id_notify; + return $stmt; + } + + /** + * SQL query to retrieve the notification type lists + * + * @return string the sql statement + */ + function getNotifyTypeList() + { + $stmt = 'select * from ' . + $this->setTablePrefix('notify_type') . + ' order by label'; + return $stmt; + } + + /** + * SQL query to retrieve the notification type label + * + * @param int $notifyTypeId the notification type id + * + * @return string the sql statement + */ + function getNotifyLabel($notifyTypeId) + { + $stmt = 'select label ' . + ' from ' . $this->setTablePrefix('notify_type') . + ' where id_notify_type=' . $notifyTypeId; + return $stmt; + } + + /** + * SQL query to retrieve the login user type + * + * @param string $username the username + * + * @return string the sql statement + */ + function getUserLoginType($username) + { + $stmt = 'select type ' . + ' from ' . $this->setTablePrefix('users') . + " where username='" . $username . "'"; + return $stmt; + } + + /** + * SQL query to check for authorized user + * + * @param string $username the username + * @param string $password the password + * + * @return string the sql statement + */ + function login($username,$password) + { + $stmt = 'select a.id_user ' . + ' from ' . $this->setTablePrefix('users') . ' as a ' . + " where a.username='" . $username . + "' and a.password='" . $password . "'"; + return $stmt; + } + + /** + * SQL query to retrieve the user info + * + * @param string $username the username + * + * @return string the sql statement + */ + function getUserInfo($username) + { + $stmt = 'select a.id_user,a.language,b.id_group,c.id_role,'. + 'c.id_systems,d.label ' . + ' from ' . $this->setTablePrefix('users') . ' as a, ' . + $this->setTablePrefix('group_users') . ' as b, ' . + $this->setTablePrefix('group_roles') . ' as c, ' . + $this->setTablePrefix('roles') . ' as d ' . + ' where b.id_group=c.id_group and a.id_user=b.id_user and ' . + ' c.id_role=d.id_role ' . + " and a.username='" . $username . "'" . + ' order by c.id_role'; + return $stmt; + } + + /* Users and groups */ + + /** + * SQL query to retrieve all users + * + * @param string $filter_search filter search + * @param string $filter_text filter text + * @param string $filter_group filter group + * + * @return string the sql statement + */ + function getUsers($filter_search = '', + $filter_text = '', + $filter_group = '') + { + $filter_stmt = ''; + if ($filter_text != '') { + if ($filter_search == 'name') { + $filter_text = rawurlencode($filter_text); + } + $filter_stmt .= ' and a.' . $filter_search . + ' like \'%' . addslashes($filter_text) . '%\''; + } + if ($filter_group != '' && $filter_group != '*') { + $filter_stmt .= ' and b.groupname=\'' . $filter_group . '\''; + } + + $stmt = 'select a.*, b.groupname ' . + ' from ' . $this->setTablePrefix('users') . ' as a, ' . + $this->setTablePrefix('groups') . ' as b, ' . + $this->setTablePrefix('group_users') . ' as c ' . + ' where a.id_user=c.id_user ' . + ' and b.id_group=c.id_group ' . + $filter_stmt . + ' order by a.name'; + return $stmt; + } + + /** + * SQL query to retrieve user properties + * + * @param int $id_user the user id + * + * @return string the sql statement + */ + function getUserById($id_user) + { + $stmt = 'select username,name,mail,type,language ' . + ' from ' . $this->setTablePrefix('users') . + ' where id_user=' . $id_user; + return $stmt; + } + + /** + * SQL query to check for existing user + * + * @param string $username the username + * + * @return string the sql statement + */ + function checkExistsUser($username) + { + $stmt = 'select count(*) ' . + ' from ' . $this->setTablePrefix('users') . + " where username='" . $username . "'"; + return $stmt; + } + + /** + * SQL query to add a user + * + * @param string $username the username + * @param string $password the password + * @param string $name the complete name + * @param string $mail the mail + * @param string $type the authentication type + * @param string $language the language + * + * @return string the sql statement + */ + function setUser($username, $password, $name, $mail, $type, $language) + { + $md5_password = md5($password); + + $stmt = 'insert into ' . $this->setTablePrefix('users') . + ' (username, password, name, mail, type, language) values (' . + "'" . $username . "'," . + "'" . $md5_password . "'," . + "'" . rawurlencode(stripslashes($name)) . "'," . + "'" . $mail . "'," . + "'" . $type . "'," . + "'" . $language . "')"; + return $stmt; + } + + /** + * SQL query to set the last login time for user + * + * @param string $username the username + * @param int $lastLogin the login time + * + * @return string the sql statement + */ + function setUserLastLogin($username, $lastLogin) + { + $stmt = 'update ' . $this->setTablePrefix('users') . + ' set last_login=' . $lastLogin . + " where username='" . $username . "'"; + return $stmt; + } + + /** + * SQL query to update password for user + * + * @param int $id_user the user id + * @param string $password the password + * + * @return string the sql statement + */ + function updateUserPassword($id_user, $password) + { + $md5_password = md5($password); + + $stmt = 'update ' . $this->setTablePrefix('users') . + ' set ' . + " password='" . $md5_password . "'" . + ' where id_user=' . $id_user; + return $stmt; + } + + /** + * SQL query to update the user properties + * + * @param int $id_user the user id + * @param string $language the language + * @param string $name the complete name + * @param string $mail the mail + * + * @return string the sql statement + */ + function updateUserProperties($id_user, $language, $name='', $mail='') + { + $stmt = 'update ' . $this->setTablePrefix('users') . ' set '; + if ($name != '') { + $stmt .= " name='" . rawurlencode(stripslashes($name)) . "'," . + " mail='" . $mail . "',"; + } + $stmt .= " language='" . $language . "'" . + ' where id_user=' . $id_user; + return $stmt; + } + + /** + * SQL query to delete a user + * + * @param int $id_user the user id + * + * @return string the sql statement + */ + function deleteUser($id_user) + { + $stmt = array(); + $stmt[0] = 'delete from ' . $this->setTablePrefix('users') . + ' where id_user=' . $id_user; + $stmt[1] = 'delete from ' . $this->setTablePrefix('group_users') . + ' where id_user=' . $id_user; + return $stmt; + } + + /** + * SQL query to add a user in a group + * + * @param int $id_user the user id + * @param int $id_group the group id + * + * @return string the sql statement + */ + function setGroupUser($id_user, $id_group='1') + { + $stmt = 'insert into ' . $this->setTablePrefix('group_users') . + ' values (' . + $id_user . ',' . + $id_group . ')'; + return $stmt; + } + + /** + * SQL query to delete a user from a group + * + * @param int $id_user the user id + * @param int $id_group the group id + * + * @return string the sql statement + */ + function deleteGroupUser($id_user, $id_group) + { + $stmt = 'delete from ' . + $this->setTablePrefix('group_users') . + ' where id_user=' . $id_user . + ' and id_group=' . $id_group; + return $stmt; + } + + /** + * SQL query to retrieve all groups + * + * @return string the sql statement + */ + function getGroups() + { + $stmt = 'select a.groupname, b.*, c.label ' . + ' from ' . $this->setTablePrefix('groups') . ' as a, ' . + $this->setTablePrefix('group_roles') . ' as b, ' . + $this->setTablePrefix('roles') . ' as c ' . + ' where a.id_group=b.id_group and ' . + ' b.id_role=c.id_role' . + ' order by a.groupname'; + return $stmt; + } + + /** + * SQL query to retrieve all roles + * + * @return string the sql statement + */ + function getRoles() + { + $stmt = 'select * ' . + ' from ' . $this->setTablePrefix('roles'); + return $stmt; + } + + /** + * SQL query to retrieve the label for the specified role + * + * @param int $id_role the role id + * + * @return string the sql statement + */ + function getRoleById($id_role) + { + $stmt = 'select label ' . + ' from ' . $this->setTablePrefix('roles') . + ' where id_role=' . $id_role; + return $stmt; + } + + /** + * SQL query to check for existing group with the specified label + * + * @param string $groupname the group name + * + * @return string the sql statement + */ + function checkExistsGroup($groupname) + { + $stmt = 'select id_group ' . + ' from ' . $this->setTablePrefix('groups') . + " where groupname='" . $groupname . "'"; + return $stmt; + } + + /** + * SQL query to add a group + * + * @param string $groupname the group name + * + * @return string the sql statement + */ + function setGroup($groupname) + { + $stmt = 'insert into ' . $this->setTablePrefix('groups') . + ' (groupname) values (' . + "'" . $groupname . "')"; + return $stmt; + } + + /** + * SQL query to define a group with a specified role + * + * @param int $id_group the group id + * @param int $id_role the role id + * @param string $id_systems the system id separated by comma + * + * @return string the sql statement + */ + function setGroupRole($id_group, $id_role, $id_systems) + { + $stmt = 'insert into ' . $this->setTablePrefix('group_roles') . + ' values (' . + $id_group . ',' . + $id_role . ',' . + "'" . $id_systems . "')"; + return $stmt; + } + + /** + * SQL query to retrieve the properties for the specified group + * + * @param int $id_group the group id + * + * @return string the sql statement + */ + function getGroupInfoById($id_group) + { + $stmt = 'select a.groupname,b.* ' . + ' from ' . $this->setTablePrefix('groups') . ' as a, ' . + $this->setTablePrefix('group_roles') . ' as b ' . + ' where a.id_group=b.id_group and ' . + ' a.id_group=' . $id_group; + return $stmt; + } + + /** + * SQL query to update the grup name + * + * @param int $id_group the user id + * @param int $groupname the group name + * + * @return string the sql statement + */ + function updateGroup($id_group, $groupname) + { + $stmt = 'update ' . $this->setTablePrefix('groups') . + ' set ' . + " groupname='" . $groupname . "'" . + ' where id_group=' . $id_group; + return $stmt; + } + + /** + * SQL query to update the role for the the specified group + * + * @param int $id_group the group id + * @param int $id_role the role id + * @param string $id_systems the system id separated by comma + * + * @return string the sql statement + */ + function updateGroupRole($id_group, $id_role, $id_systems) + { + $stmt = 'update ' . $this->setTablePrefix('group_roles') . + ' set ' . + ' id_role=' . $id_role . ',' . + " id_systems='" . $id_systems . "'" . + ' where id_group=' . $id_group; + return $stmt; + } + + /** + * SQL query to delete the specified group + * + * @param int $id_group the group id + * + * @return string the sql statement + */ + function deleteGroup($id_group) + { + $stmt = array(); + $stmt[0] = 'delete from ' . $this->setTablePrefix('groups') . + ' where id_group=' . $id_group; + $stmt[1] = 'delete from ' . $this->setTablePrefix('group_roles') . + ' where id_group=' . $id_group; + return $stmt; + } + + /** + * SQL query to retrieve all users in the specified group + * + * @param int $id_group the group id + * + * @return string the sql statement + */ + function checkUserGroup($id_group) + { + $stmt = 'select b.username ' . + ' from ' . $this->setTablePrefix('group_users') . ' as a, ' . + $this->setTablePrefix('users') . ' as b ' . + ' where a.id_user=b.id_user and ' . + ' a.id_group=' . $id_group; + return $stmt; + } + + /** + * SQL query to retrieve the groups (not) associated with the specified user + * + * @param int $id_group the group id + * @param int $in must have the values: "IN" or "NOT IN" + * + * @return string the sql statement + */ + function getGroupUser($id_group, $in) + { + //$in must have the values: "IN" or "NOT IN" + $stmt = 'select id_group, groupname ' . + ' from ' . $this->setTablePrefix('groups') . + ' where id_group ' . $in . + ' (select id_group from ' . + $this->setTablePrefix('group_users') . + ' where id_user=' . $id_group . + ') order by groupname'; + return $stmt; + } + + /** + * SQL query to add a plugin + * + * @param string $label the plugin name + * @param string $category the category + * + * @return string the sql statement + */ + function setPlugin($label, $category) + { + $stmt = 'insert into ' . $this->setTablePrefix('job_type') . + " (label, category) values ('" . $label . "','" . $category . "')"; + return $stmt; + } + + /** + * SQL query to add a notification plugin + * + * @param string $label the plugin name + * + * @return string the sql statement + */ + function setPluginNotification($label) + { + $stmt = 'insert into ' . $this->setTablePrefix('notify_type') . + " (label) values ('" . $label . "')"; + return $stmt; + } + + + /* Calendars */ + + /** + * SQL query to check if calendar label is already defined + * + * @param string $label the calendar label + * + * @return string the sql statement + */ + function checkExistsCalendar($label) + { + $stmt = 'select id_calendar ' . + 'from ' . $this->setTablePrefix('calendars') . + " where label='" . $label . "'"; + return $stmt; + } + + /** + * SQL query to add an identity + * + * @param string $label the calendar label + * @param string $calendar the calendar + * @param int $id_system the system id + * @param int $id_shared_systems the systems id to share with + * + * @return string the sql statement + */ + function setCalendar($label, + $calendar, + $id_system, + $id_shared_systems) + { + $stmt = "insert into " . $this->setTablePrefix('calendars') . + " (label,calendar,system,share_with) " . + " values ('" . $label . "','" . + $calendar . "'," . + $id_system . ",'" . + $id_shared_systems . "')"; + return $stmt; + } + + /** + * SQL query to get all calendars + * a filter for system id may be used + * + * @param string $filter_system the system id + * + * @return string the sql statement + */ + function getCalendars($filter_system = '') + { + $filter_stmt = ''; + if ($filter_system != '' && $filter_system != '*') { + $filter_stmt .= ' where system=' . $filter_system; + } + $stmt = 'select id_calendar,label,system,share_with from ' . + $this->setTablePrefix('calendars') . + $filter_stmt . + ' order by system'; + return $stmt; + } + + /** + * SQL query to get a calendar by id + * + * @param string $id_calendar the calendar id + * + * @return string the sql statement + */ + function getCalendarById($id_calendar, $fields = '*') + { + $stmt = 'select ' . $fields . ' from ' . $this->setTablePrefix('calendars') . + ' where id_calendar=' . $id_calendar; + return $stmt; + } + + /** + * SQL query to update calendar properties + * + * @param int $id_calendar the calendar id + * @param string $label the calendar label + * @param string $calendar the calendar + * @param string $id_shared_systems the systems id to share with + * + * @return string the sql statement + */ + function updateCalendar($id_calendar, $label, $calendar, $id_shared_systems) + { + $stmt = 'update ' . $this->setTablePrefix('calendars') . + " set label='" . $label . "', " . + " calendar='" . $calendar . "', " . + " share_with='" . $id_shared_systems . "' " . + ' where id_calendar=' . $id_calendar; + return $stmt; + } + + /** + * SQL query to check if the calendar is associated with any job + * + * @param string $id_calendar the calendar id + * + * @return string the sql statement + */ + function checkJobCalendar($id_calendar) + { + $stmt = 'select label ' . + ' from ' . $this->setTablePrefix('jobs') . + ' where calendar=' . $id_calendar; + return $stmt; + } + + /** + * SQL query delete a calendar by id + * + * @param int $id_calendar the identity id + * + * @return string the sql statement + */ + function deleteCalendar($id_calendar) + { + $stmt = 'delete from ' . + $this->setTablePrefix('calendars') . + ' where ' . + ' id_calendar=' . $id_calendar; + return $stmt; + } + + + /** + * SQL query to copy a calendar + * + * @param string $id_calendar the calendar id + * @param string $new_label the new label + * + * @return string the sql statement + */ + function copyCalendar($id_calendar, $new_label) + { + $stmt = 'insert into ' . $this->setTablePrefix('calendars') + . ' (label, calendar, system, share_with) ' + . " select '" + . $new_label + . "', calendar, system, share_with from " + . $this->setTablePrefix('calendars') + . ' where id_calendar =' + . $id_calendar; + return $stmt; + } + + /** + * SQL query to get calendars starting from system id + * + * @param string $id_system the system id + * + * @return string the sql statement + */ + function getCalendarBySystem($id_system) + { + $stmt = 'select id_calendar,label from ' . + $this->setTablePrefix('calendars') . + ' where system=' . $id_system . + ' or share_with like \'%#' . $id_system . '#%\''; + return $stmt; + } + +} +?> diff --git a/lib/htmlUtil.php b/lib/htmlUtil.php new file mode 100644 index 0000000..c6dd51c --- /dev/null +++ b/lib/htmlUtil.php @@ -0,0 +1,939 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/** + * Force the download for a file + * + * @param string $saved_filename The name to use for the file on saving + * @param string $full_file_path The absolute path fo the file on the server + * + * @return void + */ +function httpDownload($saved_filename, $full_file_path) +{ + //Check for directory traversal + if (!is_file($full_file_path) || (strpos($full_file_path, '..') !== false)) { + return false; + } + //Force the download + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Cache-Control: private', false); + header('Content-Type: application/force-download'); + header('Content-Disposition: attachment; filename="'. $saved_filename . '";'); + header('Content-Transfer-Encoding: binary'); + header('Content-Length: ' . filesize($full_file_path)); + readfile($full_file_path); + exit(); +} + +/** + * Show a html message box + * + * @param string $action_message The message to display + * @param string $type_message The message type (i.e. success, warning) + * + * @return void + */ +function showMessage($action_message, $type_message) +{ + $allowed_type = false; + + switch ($type_message) { + case 'warning': + case 'success': + $allowed_type = true; + break; + default: + break; + } + + if (isset($action_message) && $allowed_type) { + $table = new HTML_Table(' class=' . $type_message); + $img_html = ''; + $table->addRow(array($img_html, $action_message), + 'align=left valign=top', 'TD', false); + $table->display(); + echo '
'; + } +} + +/** + * Create the html code for a link + * + * @param string $link uri + * @param string $title The alt message + * @param string $message The text to display + * @param string $attributes The html attributes (optional) + * + * @return string The html code + */ +function createHref($link, $title, $message, $attributes='') +{ + $href = '' . + $message . ''; + return $href; +} + +/** + * Print sizes in human readable format (e.g., 1K 234M 2G) + * + * @param string $size size to convert + * + * @return string The converted size + */ +function resizeBytes($size) +{ + $count = 0; + $format = array('B','KB','MB','GB','TB','PB','EB','ZB','YB'); + while (($size/1024)>1 && $count<8) { + $size = $size/1024; + $count++; + } + $return = number_format($size, 0, '', '.') . ' ' . $format[$count]; + return $return; +} + +/** + * Allows to create the html starting from a configuration file. + * + * @param Object $_form The form object + * @param Array $conf_field_metadata The form fields metedata + * @param String $conf_field_value The form field value (optional) + * @param String $cfg_file_path The absolute path of the configuration + * file (optional) + * + * @return Array + */ +function createDynamicForm($_form, $conf_field_metadata, +$conf_field_value, $cfg_file_path='') +{ + if ($conf_field_value == 'get_metadata_conf_value') { + $form_field_value = $conf_field_metadata['value']; + } else { + $form_field_value = $conf_field_value; + } + $separator = '
'; + switch ($conf_field_metadata['type']) { + case 'select': + $f_obj = $_form->addElement($conf_field_metadata['type'], + $conf_field_metadata['name'], + '', + $conf_field_metadata['value'], + $conf_field_metadata['attributes']); + $f_obj->setSelected($form_field_value); + $html_el = $separator . $f_obj->toHTML(); + break; + case 'radio': + $f_obj =& $_form->addElement($conf_field_metadata['type'], + $conf_field_metadata['name'], + '', + '', + $conf_field_metadata['value'], + $conf_field_metadata['attributes']); + $f_obj->setChecked($form_field_value); + $html_el = $separator . $f_obj->toHTML(); + break; + case 'file': + $html_el = $separator; + $html_el .= $_form->addElement($conf_field_metadata['type'], + $conf_field_metadata['name'], + $conf_field_metadata['value'], + $conf_field_metadata['attributes'])->toHTML(); + break; + case 'hidden': + $html_el = $_form->addElement($conf_field_metadata['type'], + $conf_field_metadata['name'], + $conf_field_metadata['value'], + $conf_field_metadata['attributes'])->toHTML(); + break; + case 'submit': + $f_obj = $_form->addElement($conf_field_metadata['type'], + $conf_field_metadata['name'], + '', + $conf_field_metadata['attributes']); + $f_obj->setValue($conf_field_metadata['value']); + $html_el = ' ' . $f_obj->toHTML(); + $is_dynamic_param = !(strpos($conf_field_metadata['name'], '_get_dynamic_params') === false); + if ($is_dynamic_param && isset($GLOBALS['ip'])) { + //The plugin require to load an addition php file + include_once $cfg_file_path . 'dynamic_parameters.php'; + // invoke the default function in dynamic_parameters.php + $html_el .= get_dynamic_params($GLOBALS['ip'], + $GLOBALS['plugin_field_values'], + $_form); + } + break; + default: + $f_obj = $_form->addElement($conf_field_metadata['type'], + $conf_field_metadata['name'], + '', + $conf_field_metadata['attributes']); + if ((strpos($conf_field_metadata['attributes'], 'htmlarea') === false)) { + // Fix html editor strange behavior + $f_obj->setValue($form_field_value); + } else { + $f_obj->setValue(str_replace('\\\\\\\'', "'", $conf_field_value)); + } + $identity_picker = ''; + if (!(strpos($conf_field_metadata['name'], '_identity') === false)) { + $identity_picker = ' '. + createHref('javascript:void(0);', + TOOLTIP_IDENTITY_PICKER, + '', + 'onclick="return identityPicker(\'' . + $conf_field_metadata['name'] . '\');"'); + + } + $html_el = $separator . $f_obj->toHTML() . $identity_picker; + break; + } + $form_html = $conf_field_metadata['description'] . $html_el; + //add the rule to form field if required + if (isset($conf_field_metadata['num_rules']) && + $conf_field_metadata['num_rules'] != 0) { + for ($j = 0; $j < $conf_field_metadata['num_rules']; $j++) { + if (isset($conf_field_metadata['rule_type'][$j])) { + $_form->addRule($conf_field_metadata['name'], + $conf_field_metadata['rule_msg'][$j], + $conf_field_metadata['rule_type'][$j], + $conf_field_metadata['rule_attribute'][$j], + 'client'); + } + } + } + return array('form'=>$_form,'html'=>$form_html); +} + +/** + * Get crontab values starting from form request format + * + * @param Array $cron The $_REQUEST array + * + * @return Array + */ +function getCrontabValues($cron) +{ + + /* Get crontab values starting from form request format */ + if (isset($cron['schedule_type'])) { + $crontab['schedule_type'] = $cron['schedule_type']; + } + + if ($cron != '' && $cron['schedule_type'] != 'D') { + + switch ($cron['crontab_m']) { + case '*': + $crontab['db']['m'] = '-00-01-02-03-04-05-06-07-08-09-10'. + '-11-12-13-14-15-16-17-18-19-20'. + '-21-22-23-24-25-26-27-28-29-30'. + '-31-32-33-34-35-36-37-38-39-40'. + '-41-42-43-44-45-46-47-48-49-50'. + '-51-52-53-54-55-56-57-58-59-'; + break; + case 'every5': + $crontab['db']['m'] = '-00-05-10-15-20-25-30-35-40-45-50-55-'; + break; + case 'every15': + $crontab['db']['m'] = '-00-15-30-45-'; + break; + case 'every30': + $crontab['db']['m'] = '-00-30-'; + break; + case 'custom': + $crontab['db']['m'] = '-' . implode('-', $cron['minute_custom']) . + '-'; + break; + case '-00-01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40-41-42-43-44-45-46-47-48-49-50-51-52-53-54-55-56-57-58-59-': + $crontab['form']['m'] = '*'; + $crontab['html']['m'] = '*'; + break; + case '-00-05-10-15-20-25-30-35-40-45-50-55-': + $crontab['form']['m'] = 'every5'; + $crontab['html']['m'] = FIELD_JOB_SCHEDULE_EVERY_5; + break; + case '-00-15-30-45-': + $crontab['form']['m'] = 'every15'; + $crontab['html']['m'] = FIELD_JOB_SCHEDULE_EVERY_15; + break; + case '-00-30-': + $crontab['form']['m'] = 'every30'; + $crontab['html']['m'] = FIELD_JOB_SCHEDULE_EVERY_30; + break; + default: + $crontab['form']['m'] = 'custom'; + $crontab_m_values = split('-', $cron['crontab_m']); + array_shift($crontab_m_values); + array_pop($crontab_m_values); + $crontab['form']['values']['m'] = $crontab_m_values; + $crontab['html']['m'] = implode(',', $crontab_m_values); + break; + } + + //hour + switch ($cron['crontab_h']) { + case '*': + $crontab['db']['h'] = '-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-'; + break; + case 'every6': + $crontab['db']['h'] = '-0-6-12-18-'; + break; + case 'every12': + $crontab['db']['h'] = '-0-12-'; + break; + case 'custom': + $crontab['db']['h'] = '-' . implode('-', $cron['hour_custom']) . '-'; + break; + case '-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-': + $crontab['form']['h'] = '*'; + $crontab['html']['h'] = '*'; + break; + case '-0-6-12-18-': + $crontab['form']['h'] = 'every6'; + $crontab['html']['h'] = FIELD_JOB_SCHEDULE_EVERY_6; + break; + case '-0-12-': + $crontab['form']['h'] = 'every12'; + $crontab['html']['h'] = FIELD_JOB_SCHEDULE_EVERY_12; + break; + default: + $crontab['form']['h'] = 'custom'; + $crontab_h_values = split('-', $cron['crontab_h']); + array_shift($crontab_h_values); + array_pop($crontab_h_values); + $crontab['form']['values']['h'] = $crontab_h_values; + $crontab['html']['h'] = implode(',', $crontab_h_values); + break; + } + + //day + switch ($cron['crontab_dom']) { + case '*': + $crontab['db']['dom'] = '-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-'; + break; + case 'custom': + $crontab['db']['dom'] = '-' . @implode('-', $cron['day_custom']) . '-'; + break; + case '-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-': + $crontab['form']['dom'] = '*'; + $crontab['html']['dom'] = '*'; + break; + default: + $crontab['form']['dom'] = 'custom'; + $crontab_dom_values = split('-', $cron['crontab_dom']); + array_shift($crontab_dom_values); + array_pop($crontab_dom_values); + $crontab['form']['values']['dom'] = $crontab_dom_values; + $crontab['html']['dom'] = implode(',', $crontab_dom_values); + break; + } + + //month + switch ($cron['crontab_mon']) { + case '*': + $crontab['db']['mon'] = '-1-2-3-4-5-6-7-8-9-10-11-12-'; + break; + case 'custom': + $crontab['db']['mon'] = '-' . implode('-', $cron['month_custom']) . '-'; + break; + case '-1-2-3-4-5-6-7-8-9-10-11-12-': + $crontab['form']['mon'] = '*'; + $crontab['html']['mon'] = '*'; + break; + default: + $crontab['form']['mon'] = 'custom'; + $crontab_mon_values = split('-', $cron['crontab_mon']); + array_shift($crontab_mon_values); + array_pop($crontab_mon_values); + $crontab['form']['values']['mon'] = $crontab_mon_values; + $crontab['html']['mon'] = implode(',', $crontab_mon_values); + break; + } + + //day of week + switch ($cron['crontab_dow']) { + case '*': + $crontab['db']['dow'] = '-0-1-2-3-4-5-6-'; + break; + case 'custom': + $crontab['db']['dow'] = '-' . implode('-', $cron['dayweek_custom']) . + '-'; + break; + case '-0-1-2-3-4-5-6-': + $crontab['form']['dow'] = '*'; + $crontab['html']['dow'] = '*'; + break; + default: + $crontab['form']['dow'] = 'custom'; + $crontab_dow_values = split('-', $cron['crontab_dow']); + array_shift($crontab_dow_values); + array_pop($crontab_dow_values); + $crontab['form']['values']['dow'] = $crontab_dow_values; + $crontab['html']['dow'] = implode(',', $crontab_dow_values); + break; + } + + } else { + $crontab['form']['m'] = '*'; + $crontab['form']['h'] = '*'; + $crontab['form']['dom'] = '*'; + $crontab['form']['mon'] = '*'; + $crontab['form']['dow'] = '*'; + $crontab['html']['m'] = '*'; + $crontab['html']['h'] = '*'; + $crontab['html']['dom'] = '*'; + $crontab['html']['mon'] = '*'; + $crontab['html']['dow'] = '*'; + $crontab['db']['m'] = '-'; + $crontab['db']['h'] = '-'; + $crontab['db']['dom'] = '-'; + $crontab['db']['mon'] = '-'; + $crontab['db']['dow'] = '-'; + if (isset($cron['schedule_type']) && $cron['schedule_type'] == 'D') { + $crontab['html']['m'] = '-'; + $crontab['html']['h'] = '-'; + $crontab['html']['dom'] = '-'; + $crontab['html']['mon'] = '-'; + $crontab['html']['dow'] = '-'; + } + } + + if (isset($cron['schedule_type'])) { + switch ($cron['schedule_type']) { + case 'A': + $crontab['html']['schedule_type'] = FIELD_JOB_SCHEDULE_ENABLE; + break; + case 'T': + $crontab['html']['schedule_type'] = FIELD_JOB_SCHEDULE_ENABLE_WORKFLOW; + break; + case 'J': + $crontab['html']['schedule_type'] = FIELD_JOB_SCHEDULE_ENABLE_JOB; + break; + case 'D': + $crontab['html']['schedule_type'] = FIELD_JOB_SCHEDULE_DISABLE; + break; + } + } + return $crontab; +} + +/** + * Allows to create the html code for crontab starting from the db parameters + * + * @param Object $form The form object + * @param Array $cron The crontab values + * @param String $category The category where crontab is used. + * + * @return Array + */ +function createCrontabHtml($form, $cron = '', $category = '') +{ + $table_attributes = 'cellpadding=0 cellspacing=0 border=0 width=100%'; + $hidden_table_attributes = $table_attributes . ' style="display: none"'; + $crontab_html_static = array(); + // --- get the crontabs fields --- + + $crontab = getCrontabValues($cron); + //minutes + + $select_minute['*'] = FIELD_JOB_SCHEDULE_EVERY_MIN; + $select_minute['every5'] = FIELD_JOB_SCHEDULE_EVERY_5_MIN; + $select_minute['every15'] = FIELD_JOB_SCHEDULE_EVERY_15_MIN; + $select_minute['every30'] = FIELD_JOB_SCHEDULE_EVERY_30_MIN; + $select_minute['custom'] = FIELD_JOB_SCHEDULE_CUSTOM; + $f_minute_obj = $form->addElement('select', + 'crontab_m', + '', + $select_minute, + 'onchange="showFormFields(this.value, \'minute_\', \'custom\');"'); + $f_minute_obj->setSelected($crontab['form']['m']); + $f_minute = $f_minute_obj->toHTML(); + + for ($index = 0; $index < 60; $index++) { + $prefix_0 = ''; + if ($index < 10) { + $prefix_0 = 0; + } + $select_minute_custom[$prefix_0 . $index] = $index; + } + $f_minute_custom = $form->addElement('select', 'minute_custom', '', + $select_minute_custom, + 'multiple id=minute_custom_sel'); + + $form->registerRule('checkMultiSelectJob', 'callback', 'checkMultiSelectJob'); + $form->addRule('crontab_m', MSG_SELECT_A_VALUE_FOR_MINUTE, + 'checkMultiSelectJob', 'minute_custom_sel', 'client'); + + if ($crontab['form']['m'] == 'custom') { + $table = new HTML_Table($table_attributes . ' id=minute_custom'); + $f_minute_custom->setSelected($crontab['form']['values']['m']); + } else { + $table = new HTML_Table($hidden_table_attributes . ' id=minute_custom'); + } + $table->addRow(array($f_minute_custom->toHTML()), + 'align=left valign=top', 'TD', false); + $table_minute = $table->toHTML(); + + //hours + $select_hour['*'] = FIELD_JOB_SCHEDULE_EVERY_HOUR; + $select_hour['every6'] = FIELD_JOB_SCHEDULE_EVERY_6_HOUR; + $select_hour['every12'] = FIELD_JOB_SCHEDULE_EVERY_12_HOUR; + $select_hour['custom'] = FIELD_JOB_SCHEDULE_CUSTOM; + + $f_hour_obj = $form->addElement('select', 'crontab_h', '', $select_hour, + 'onchange="showFormFields(this.value, \'hour_\', \'custom\');"'); + $f_hour_obj->setSelected($crontab['form']['h']); + $f_hour = $f_hour_obj->toHTML(); + + for ($index = 0; $index < 24; $index++) { + $select_hour_custom[$index] = $index; + } + + $f_hour_custom = $form->addElement('select', 'hour_custom', '', + $select_hour_custom, + 'multiple id=hour_custom_sel'); + $form->addRule('crontab_h', MSG_SELECT_A_VALUE_FOR_HOUR, + 'checkMultiSelectJob', 'hour_custom_sel', 'client'); + if ($crontab['form']['h'] == 'custom') { + $table = new HTML_Table($table_attributes . ' id=hour_custom'); + $f_hour_custom->setSelected($crontab['form']['values']['h']); + } else { + $table = new HTML_Table($hidden_table_attributes . ' id=hour_custom'); + } + $table->addRow(array($f_hour_custom->toHTML()), + 'align=left valign=top', 'TD', false); + $table_hour = $table->toHTML(); + + //day of month + $select_day['*'] = FIELD_JOB_SCHEDULE_EVERY_DAY; + $select_day['custom'] = FIELD_JOB_SCHEDULE_CUSTOM; + + $f_day_obj = $form->addElement('select', 'crontab_dom', '', $select_day, + 'onchange="showFormFields(this.value, \'day_\', \'custom\');"'); + + $f_day_obj->setSelected($crontab['form']['dom']); + $f_day = $f_day_obj->toHTML(); + + for ($index = 1; $index < 32; $index++) { + $select_day_custom[$index] = $index; + } + + $f_day_custom = $form->addElement('select', 'day_custom', '', + $select_day_custom, + 'multiple id=day_custom_sel'); + $form->addRule('crontab_dom', MSG_SELECT_A_VALUE_FOR_DAY, 'checkMultiSelectJob', + 'day_custom_sel', 'client'); + if ($crontab['form']['dom'] == 'custom') { + $table = new HTML_Table($table_attributes . ' id=day_custom'); + $f_day_custom->setSelected($crontab['form']['values']['dom']); + } else { + $table = new HTML_Table($hidden_table_attributes . ' id=day_custom'); + } + $table->addRow(array($f_day_custom->toHTML()), + 'align=left valign=top', 'TD', false); + $table_day = $table->toHTML(); + + //month of year + $select_month['*'] = FIELD_JOB_SCHEDULE_EVERY_MONTH; + $select_month['custom'] = FIELD_JOB_SCHEDULE_CUSTOM; + + $f_month_obj = $form->addElement('select', 'crontab_mon', '', $select_month, + 'onchange="showFormFields(this.value, \'month_\', \'custom\');"'); + $f_month_obj->setSelected($crontab['form']['mon']); + $f_month = $f_month_obj->toHTML(); + + for ($index = 1; $index < 13; $index++) { + $select_month_custom[$index] = $index; + } + + $f_month_custom = $form->addElement('select', 'month_custom', '', + $select_month_custom, + 'multiple id=month_custom_sel'); + $form->addRule('crontab_mon', MSG_SELECT_A_VALUE_FOR_MONTH, + 'checkMultiSelectJob', 'month_custom_sel', 'client'); + + if ($crontab['form']['mon'] == 'custom') { + $table = new HTML_Table($table_attributes . ' id=month_custom'); + $f_month_custom->setSelected($crontab['form']['values']['mon']); + } else { + $table = new HTML_Table($hidden_table_attributes . ' id=month_custom'); + } + $table->addRow(array($f_month_custom->toHTML()), + 'align=left valign=top', 'TD', false); + $table_month = $table->toHTML(); + + //day of week + $select_dayweek['*'] = FIELD_JOB_SCHEDULE_EVERY_DAY_OF_WEEK; + $select_dayweek['custom'] = FIELD_JOB_SCHEDULE_CUSTOM; + + $f_dayweek_obj = $form->addElement('select', 'crontab_dow', '', $select_dayweek, + 'onchange="showFormFields(this.value, \'dayweek_\', \'custom\');"'); + $f_dayweek_obj->setSelected($crontab['form']['dow']); + $f_dayweek = $f_dayweek_obj->toHTML(); + + $select_dayweek_custom['0'] = FIELD_JOB_SCHEDULE_SUNDAY; + $select_dayweek_custom['1'] = FIELD_JOB_SCHEDULE_MONDAY; + $select_dayweek_custom['2'] = FIELD_JOB_SCHEDULE_TUESDAY; + $select_dayweek_custom['3'] = FIELD_JOB_SCHEDULE_WEDNEDAY; + $select_dayweek_custom['4'] = FIELD_JOB_SCHEDULE_THURSDAY; + $select_dayweek_custom['5'] = FIELD_JOB_SCHEDULE_FRIDAY; + $select_dayweek_custom['6'] = FIELD_JOB_SCHEDULE_SATURDAY; + + $f_dayweek_custom = $form->addElement('select', 'dayweek_custom', '', + $select_dayweek_custom, + 'multiple id=dayweek_custom_sel'); + $form->addRule('crontab_dow', MSG_SELECT_A_VALUE_FOR_DAY_OF_WEEK, + 'checkMultiSelectJob', 'dayweek_custom_sel', 'client'); + if ($crontab['form']['dow'] == 'custom') { + $table = new HTML_Table($table_attributes . ' id=dayweek_custom'); + $f_dayweek_custom->setSelected($crontab['form']['values']['dow']); + } else { + $table = new HTML_Table($hidden_table_attributes . ' id=dayweek_custom'); + } + $table->addRow(array($f_dayweek_custom->toHTML()), + 'align=left valign=top', 'TD', false); + $table_dayweek = $table->toHTML(); + + if ($category == 'workflow') { + $select_schedule_type['A'] = FIELD_JOB_SCHEDULE_ENABLE; + } else { + $select_schedule_type['T'] = FIELD_JOB_SCHEDULE_ENABLE_WORKFLOW; + $select_schedule_type['J'] = FIELD_JOB_SCHEDULE_ENABLE_JOB; + } + $select_schedule_type['D'] = FIELD_JOB_SCHEDULE_DISABLE; + + $f_schedule_type = $form->addElement('select', 'schedule_type', '', + $select_schedule_type, + 'onchange="enableSchedule(this.value);"'); + if (isset($crontab['schedule_type'])) { + $f_schedule_type->setSelected($crontab['schedule_type']); + } + + $table = new HTML_Table($table_attributes); + $table->addRow(array(FIELD_JOB_SCHEDULE), 'colspan=5', 'TH'); + $table->addRow(array($f_schedule_type->toHTML()), 'colspan=5', 'TD', false); + $table->addRow(array(FIELD_JOB_SCHEDULE_MINUTE, + FIELD_JOB_SCHEDULE_HOUR, + FIELD_JOB_SCHEDULE_DAY_OF_MONTH, + FIELD_JOB_SCHEDULE_MONTH_OF_YEAR, + FIELD_JOB_SCHEDULE_DAY_OF_WEEK), + '', 'TH'); + $table->addRow(array($f_minute, + $f_hour, + $f_day, + $f_month, + $f_dayweek), 'valign=top', 'TD', false); + $table->addRow(array($table_minute, + $table_hour, + $table_day, + $table_month, + $table_dayweek), 'valign=top class=c1', 'TD', false); + $form_html = $table->toHTML(); + + return array('form'=>$form, 'html'=>$form_html); + +} + +/** + * Allows to create the html toolbar code + * + * @param array $buttons The associative array action => role + * + * @return array the associative array with javascript and html code + */ +function createToolbar($buttons) +{ + $html = array(); + $html_menu = array(); + $i = 0; + + $js_default_status = ''; + $js_admin_status = ''; + $js_guest_status = ''; + $js_default_admin_status = ''; + $js_hide_edit_button = ''; + $auto_refresh_html = ''; + $custom_html = ''; + $install_html = ''; + + foreach ($buttons as $button => $role) { + $class = 'toolbar_hidden'; + switch ($button) { + case 'add': + $description = ACTION_ADD_DESCRIPTION ; + $image = 'add.png'; + break; + case 'edit': + $description = ACTION_EDIT_DESCRIPTION ; + $image = 'edit.png'; + break; + case 'copy': + $description = ACTION_COPY_DESCRIPTION ; + $image = 'copy.png'; + break; + case 'delete': + $description = ACTION_DELETE_DESCRIPTION ; + $image = 'eraser.png'; + break; + case 'lock': + $description = ACTION_LOCK_DESCRIPTION ; + $image = 'lock.png'; + break; + case 'unlock': + $description = ACTION_UNLOCK_DESCRIPTION ; + $image = 'unlock.png'; + break; + case 'run': + $description = ACTION_RUN_DESCRIPTION ; + $image = 'run.png'; + break; + case 'details': + $description = ACTION_DETAIL_DESCRIPTION; + $image = 'details.png'; + break; + case 'userGroup': + $description = ACTION_GROUP_DESCRIPTION; + $image = 'groups.png'; + break; + case 'reload_page': + $description = ACTION_RELOAD_DESCRIPTION; + $image = 'reload_page.png'; + $class = 'toolbar'; + break; + case 'forward': + $description = ACTION_NEXT_STEP_DESCRIPTION; + $image = 'forward.png'; + $class = 'toolbar'; + break; + case 'back': + $description = ACTION_PREV_STEP_DESCRIPTION; + $image = 'back.png'; + $class = 'toolbar'; + break; + case 'forwardPage': + $description = ACTION_NEXT_PAGE_DESCRIPTION; + $image = 'forward.png'; + $class = 'toolbar'; + break; + case 'backPage': + $description = ACTION_PREV_PAGE_DESCRIPTION; + $image = 'back.png'; + $class = 'toolbar'; + break; + case 'kill': + $description = ACTION_KILL_DESCRIPTION; + $image = 'kill.png'; + $class = 'toolbar'; + break; + case 'auto_refresh': + $auto_refresh_html = $role; + continue 2; + break; + case 'custom': + $custom_html = $role; + continue 2; + break; + case 'install': + $install_html = $role; + continue 2; + break; + default: + break; + } + + $toolbar_id = 'toolbar_' . $button; + $toolbar_menu_id = 'toolbar_menu_' . $button; + + $js_default_status .= 'document.getElementById("' . $toolbar_id . + '").className = \'toolbar_hidden\';' . "\n"; + $js_default_status .= 'document.getElementById("' . $toolbar_menu_id . + '").className = \'toolbar_hidden\';' . "\n"; + + switch($role) { + case 'admin': + $js_admin_status .= 'document.getElementById("' . + $toolbar_id . + '").className = \'toolbar\';' . "\n"; + $js_admin_status .= 'document.getElementById("' . + $toolbar_menu_id . + '").className = \'toolbar\';' . "\n"; + break; + case 'guest': + //guest + $js_guest_status .= 'document.getElementById("' . + $toolbar_id . + '").className = \'toolbar\';' . "\n"; + $js_guest_status .= 'document.getElementById("' . + $toolbar_menu_id . + '").className = \'toolbar\';' . "\n"; + break; + case 'default': + $js_default_status .= 'document.getElementById("' . + $toolbar_id . + '").className = \'toolbar\';'. "\n"; + $js_default_status .= 'document.getElementById("' . + $toolbar_menu_id . + '").className = \'toolbar\';'. "\n"; + break; + case 'default_admin': + $js_default_admin_status .= 'document.getElementById("' . + $toolbar_id . + '").className = \'toolbar\';'. "\n"; + $js_default_admin_status .= 'document.getElementById("' . + $toolbar_menu_id . + '").className = \'toolbar\';'. "\n"; + break; + } + + $html[$i] = createHref('javascript:void(0);', + $description, + '' .
+        $description . '', + 'onclick="return submitForm(\'' . $button . + '\');" id="' .$toolbar_id . '" class="' . + $class . '"'); + + $html_menu[$i] = createHref('javascript:void(0);', + $description, + '' .
+        $description . '', + 'onclick="return submitForm(\'' . $button . + '\');" id="' .$toolbar_menu_id . '" class="' . + $class . '"'); + $i++; + } + + $javascript = ""; + + $table_attributes = 'cellpadding="0" cellspacing="0" border="0" width="100%"'; + + $table_toolbar_attributes = 'cellpadding="0" cellspacing="0" ' . + 'border="0" width="100px"'; + + $table_toolbar = new HTML_Table($table_attributes); + + if ($install_html != '') { + $table_toolbar->addRow(array($install_html,$html), 'class=install', 'TH'); + $table_toolbar->updateCellAttributes('0', '0', 'width=99%'); + $toolbar = array('header' => $table_toolbar->toHtml(), + 'javascript'=>$javascript); + } else { + $block_toolbar = createHref('javascript:void(0);', + ACTION_LOCK_UNLOCK, + '', + 'onclick="return ' . + 'blockToolbar(\'toolbar_img\');"'); + $table_toolbar->addRow(array($block_toolbar . ACTION_TITLE), '', 'TH'); + $align = ''; + if ($custom_html != '') { + //add custom button + array_push($html, $custom_html); + } + if ($auto_refresh_html != '') { + //add auto_refresh select + array_push($html, REFRESH_TITLE . $auto_refresh_html); + $align = 'align=right'; + } + $table_toolbar->updateCellAttributes('0', '0', 'colspan=' . count($html)); + $table_toolbar->addRow($html, 'class="c2"', 'TD', true); + $table_toolbar->updateCellAttributes('1', count($html)-1, + $align . ' width=99%'); + + /* Create the toolbar menu for scrolling */ + $table_toolbar_menu = new HTML_Table($table_toolbar_attributes); + $table_toolbar_menu->addRow(array(ACTION_TITLE), 'colspan=3', 'TH'); + $j = 0; + $temp_row = array(); + for ($k = 0; $k < sizeof($html_menu); $k++) { + array_push($temp_row, $html_menu[$k]); + if ($j==2) { + $table_toolbar_menu->addRow($temp_row, 'class=c2', 'TD', true); + $temp_row = array(); + $j = 0; + } else { + $j++; + } + } + if ($j!=0) { + $table_toolbar_menu->addRow($temp_row, 'class=c2', 'TD', true); + } + $toolbar = array('header' => $table_toolbar->toHtml(), + 'menu' => $table_toolbar_menu->toHtml(), + 'javascript'=>$javascript); + } + return $toolbar; +} +?> diff --git a/lib/installUtil.php b/lib/installUtil.php new file mode 100644 index 0000000..c84d562 --- /dev/null +++ b/lib/installUtil.php @@ -0,0 +1,158 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'System.php'; + +/** + * Checks for php presence and version + * + * @return array Test results + */ +function checkPHP($php_path = null) +{ + $required_version = '5.1'; + $result['php_version'] = phpversion() < $required_version ? 0 : 1; + //check for php-cli + if ($php_path != null) { + $rev_php_path = strrev($php_path); + if ($rev_php_path[0] != DIRECTORY_SEPARATOR) { + $php_path .= DIRECTORY_SEPARATOR; + } + } elseif (isset($_SESSION['installation']['env']['php_path'])) { + $php_path = $_SESSION['installation']['env']['php_path']; + } else { + $php_path = ''; + } + + $cmdLine = escapeshellarg($php_path . 'php') . " -r 'echo phpversion() < " . + $required_version . " ? 0 : 1;'"; + exec($cmdLine, $stdout, $exit_code); + if ($exit_code == '0') { + //php is in the path + $result['php-cli_version'] = $stdout[0]; + $result['php_path'] = $php_path; + $result['test_result'] = 1; + + $_SESSION['installation']['env']['php_path'] = $php_path; + } else { + $result['php_path'] = 'no'; + $result['test_result'] = 0; + } + return $result; +} + +/** + * Check for ssh presence + * + * @return array Test results + */ +function checkSSH() +{ + //check for openssh client + if (isset($_REQUEST['ssh_path'])) { + $ssh_path = $_REQUEST['ssh_path']; + $rev_ssh_path = strrev($ssh_path); + if ($rev_ssh_path[0] != DIRECTORY_SEPARATOR) { + $ssh_path .= DIRECTORY_SEPARATOR; + } + } elseif (isset($_SESSION['installation']['env']['ssh_path'])) { + $ssh_path = $_SESSION['installation']['env']['ssh_path']; + } else { + $ssh_path = ''; + } + + if (!System::which($ssh_path . 'ssh')) { + $result['ssh_path'] = 'no'; + $result['test_result'] = 0; + } else { + //ssh is installed + $result['ssh_path'] = $ssh_path; + $result['test_result'] = 1; + + $_SESSION['installation']['env']['ssh_path'] = $ssh_path; + } + return $result; +} + +/** + * Check for required extensions + * + * @return array Test results + */ +function checkExtensions() +{ + + $required_ext_list = array('bz2', + 'date', + 'ftp', + 'pcre', + 'xml', + //'zip', + 'zlib' + ); + + $result['missed_extensions'] = array(); + + foreach ($required_ext_list as $ext_to_check) { + if (!extension_loaded($ext_to_check)) { + $result['missed_extensions'][] = $ext_to_check; + } + } + + if (count($result['missed_extensions']) > 0) { + $result['test_result'] = 0; + } else { + $result['test_result'] = 1; + } + return $result; +} + +/** + * Check for installed DB driver + * + * @return array Test results + */ +function checkDBDriver() +{ + if (function_exists('mysql_connect')) { + $result['db_supported']['mysql'] = 'MySQL'; + } + if (function_exists('mysqli_connect')) { + $result['db_supported']['mysqli'] = 'MySQLi'; + } + if (function_exists('oci_connect')) { + $result['db_supported']['oci8'] = 'Oracle'; + } + if (function_exists('pg_connect')) { + $result['db_supported']['pgsql'] = 'PostgreSQL'; + } + if (function_exists('sqlite_open')) { + $result['db_supported']['sqlite'] = 'SQLite'; + } + if (function_exists('mssql_connect')) { + $result['db_supported']['mssql'] = 'Microsoft SQL Server'; + } + if (function_exists('ibase_connect')) { + $result['db_supported']['ibase'] = 'InterBase'; + } + + return $result; +} +?> diff --git a/lib/ioUtil.php b/lib/ioUtil.php new file mode 100644 index 0000000..cb027cb --- /dev/null +++ b/lib/ioUtil.php @@ -0,0 +1,232 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/** + * Read a file + * + * @param string $filePath absolute path of the file + * @param string $fileName file name + * + * @return string the file content + */ +function readFiles($filePath, $fileName) +{ + $filename = $filePath . $fileName; + $handle = fopen($filename, "r"); + $contents = fread($handle, filesize($filename)); + fclose($handle); + return $contents; +} + +/** +* Create an html file +* +* @param string $fileData file data +* @param string $filePath absolute path of the file +* @param string $fileName file name +* +* @return boolean true on success +*/ + +function createHTMLFile($fileData, $filePath, $fileName) +{ + $temp_file = $fileName . '_' . date('Y_m_d_H_i') . '.html'; + createFile($fileData, $filePath, $temp_file); +} + + + +/** +* Create a generic file +* +* @param string $fileData file data +* @param string $filePath absolute path of the file +* @param string $fileName file name +* +* @return boolean true on success +*/ +function createFile($fileData, $filePath, $fileName) +{ + //Create the folder if not exists + if (!is_dir($filePath)) { + mkdir($filePath, 0755, true); + } + $temp_file = $filePath . $fileName; + $fh = fopen($temp_file, 'w+'); + fwrite($fh, $fileData); + return fclose($fh); +} + + + +/** + * Create a file of the specified type starting from a query result + * Note: The file is zipped if its size is greater than + * "zip_file_threshold" parameter defined in the global configuration file. + * + * @param array $resultset query resultset + * @param string $filePath absolute path of the file + * @param string $fileName file name + * @param string $fileType file type/extension (e.g. txt,csv...) + * @param string $colSeparator char separator for column + * (e.g. ";", "\t", ...) + * @param string $rowSeparator char separator for row (e.g. "\n"...) + * @param string $print_column_header print the column headers in the file + * (default true) + * @param string $append_data_to_file_name append the date to the filename + * (default true) + * @param string $compress_file compress the output file if its size + * is greater than [env][zip_threshold] + * value (default true) + * + * @return string created file (absolute path) + */ + +function createFileByQuery($resultset, $filePath, $fileName, + $fileType, $colSeparator, $rowSeparator, + $print_column_header = true, + $append_data_to_file_name = true, $compress_file = true) +{ + $fileData = ''; + $column_name = array_keys($resultset[0]); + + if ($print_column_header) { + $fileData = implode($colSeparator, $column_name) . $rowSeparator; + } + + $num_cols = count($column_name); + + foreach ($resultset as $row) { + $i = 1; + $rowData = ''; + foreach ($column_name as $name) { + switch ($fileType) { + case 'csv': + if (strlen($row[$name]) > 31000) { + //reached the max cell characters limit in a worksheet + // cell for excel + //trying to remove multiple spaces + $row[$name] = preg_replace('/\s+/', ' ', $row[$name]); + } + $rowData .= '"' . str_replace('"', '""', $row[$name]) . '"'; + break; + default: + $rowData .= $row[$name]; + break; + } + if ($i < $num_cols) { + $rowData .= $colSeparator; + $i++; + } + } + $fileData .= $rowData . $rowSeparator; + } + //Create the folder if not exists + if (!is_dir($filePath)) { + mkdir($filePath, 0755, true); + } + + if ($append_data_to_file_name) { + $temp_file = $filePath . $fileName . '_' . date('Y_m_d_H_i') . '.'; + } else { + $temp_file = $filePath . $fileName . '.'; + } + + $fh = fopen($temp_file . $fileType, 'w+'); + fwrite($fh, $fileData); + fclose($fh); + if ($compress_file && filesize($temp_file . $fileType) > + $GLOBALS['conf']['env']['zip_threshold'] && + is_file($GLOBALS['conf']['env']['zip_path'])) { + $cmdLine = $GLOBALS['conf']['env']['zip_path'] . ' -j ' . + $temp_file .'zip' . ' ' . $temp_file . $fileType; + exec($cmdLine, $stdout, $exit_code); + if ($exit_code == '0') { + //remove the uncompressed file + unlink($temp_file . $fileType); + $fileZipped = true; + } + } + if ($fileZipped) { + return $temp_file . 'zip'; + } else { + return $temp_file . $fileType; + } +} + + +/** + * Remove directories, even if they contain files or subdirectories. + * + * @param string $dir absolute path of the file + * + * @return void + */ + +function removeDirectory($dir) +{ + $dir = $dir . DIRECTORY_SEPARATOR; + if (!is_dir($dir) || (strpos($dir, '..') !== false)) { + return false; + } + $dir_contents = scandir($dir); + foreach ($dir_contents as $item) { + if (is_dir($dir.$item) && $item != '.' && $item != '..') { + removeDirectory($dir.$item.DIRECTORY_SEPARATOR); + } elseif (file_exists($dir.$item) && $item != '.' && $item != '..') { + unlink($dir.$item); + } + } + rmdir($dir); +} + + +/** + * This function return a array with all files into a param directory + * + * @param string $rootDir absolute path of the file + * + * @param array $allData name of files list + * + * @return array + */ + +function scanDirectories($rootDir, $allData=array()) +{ + $invisibleFileNames = array( + ".", + "..", + ".DS_Store", + "backup" + ); + $dirContent = scandir($rootDir); + foreach ($dirContent as $key => $content) { + $path = $rootDir.DS.$content; + if (!in_array($content, $invisibleFileNames)) { + if (is_file($path) && is_readable($path)) { + $allData[] = $path; + } elseif (is_dir($path) && is_readable($path)) { + $allData = scanDirectories($path, $allData); + } + } + } + return $allData; +} +?> \ No newline at end of file diff --git a/lib/langUtil.php b/lib/langUtil.php new file mode 100644 index 0000000..4403b01 --- /dev/null +++ b/lib/langUtil.php @@ -0,0 +1,99 @@ + + * @author Luca Corbo + * @link http://www.ortro.net + */ + +/** + * Include the language definition file in according with the selected language. + * If $_SESSION['lang'] variable is not set the installation language will be used (english is the default). + * If $_SESSION['lang'] is set but the plug in is not yet translated in the selected language is forced to english. + * @param string $category The category of the plugin or 'template' to translate a page + * @param string $name The name of the plugin or the template page name + */ + +function i18n($category, $name) { + + //Check for malicious include + if ((strpos($category, '..') !== false) || (strpos($name, '..') !== false)) { + return false; + } + + require_once 'authUtil.php'; + //Include common tranlation file for plugin. + $relative_plugin_language_file_path = ''; + $absolute_plugin_language_file_path = ''; + $absolute_plugin_common_language_file_path = ''; + $relative_plugin_common_language_file_path = DS . 'template' . DS . 'plugin_common.php'; + + switch ($category) { + case 'template': + //Include tranlation file for page. + $relative_plugin_language_file_path = DS . 'template' . DS . $name; + break; + case 'js': + //Include tranlation file for page. + $relative_plugin_language_file_path = DS . 'js' . DS . 'js.php'; + break; + default: + //Include tranlation file for plugin. + $relative_plugin_language_file_path = DS . 'plugins' . DS . $category . + DS . $name . DS . 'language.php'; + break; + } + + $language = AuthUtil::getSessionData('language'); + + //Trying to load language file in according to session value + if ($language !== false){ + $absolute_plugin_common_language_file_path = ORTRO_LANG . $language . $relative_plugin_common_language_file_path; + $absolute_plugin_language_file_path = ORTRO_LANG . $language . $relative_plugin_language_file_path; + } + + if (!file_exists($absolute_plugin_language_file_path)){ + //Force to load language file in according to language default value + $absolute_plugin_common_language_file_path = ORTRO_LANG . ORTRO_DEFAULT_LANGUAGE . $relative_plugin_common_language_file_path; + $absolute_plugin_language_file_path = ORTRO_LANG . ORTRO_DEFAULT_LANGUAGE . $relative_plugin_language_file_path; + } + if ($category != 'template') { + @include_once ($absolute_plugin_common_language_file_path); + } + @include_once ($absolute_plugin_language_file_path); +} + +/** + * Retrieve all available languages using the current locale. + * @return array The available languages + */ + +function getAvailableLanguages() { + require_once 'authUtil.php'; + require_once 'I18Nv2/Language.php'; + + $i18n = new I18Nv2_Language(); + + $language_codes = $i18n->getAllCodes(); + + $lang_dirs = scandir(ORTRO_LANG); + foreach ($lang_dirs as $lang_available) { + if ($lang_available[0] != '.') { + $ortro_languages[$lang_available] = $language_codes[$lang_available]; + } + } + return $ortro_languages; +} +?> \ No newline at end of file diff --git a/lib/ldapUtil.php b/lib/ldapUtil.php new file mode 100644 index 0000000..23716dc --- /dev/null +++ b/lib/ldapUtil.php @@ -0,0 +1,187 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; + +/** + * LDAP Class Interface + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class LdapUtil +{ + + // {{{ constructor + /** + * ldapUtil Class constructor. + * This flavour of the constructor only enable logging + * identifying it by the name of the class file. + * + * @access public + */ + function ldapUtil() + { + $this->logger = new LogUtil('ldapUtil.php'); + } + // }}} + + // {{{ ldapSearch() + /** + * This method allows to search on the defined ldap tree. + * + * @param string $filter The search filter can be simple + * or advanced, using boolean operators in + * the format described in the LDAP + * documentation. + * @param array $only_these_attributes An array of the required attributes, + * e.g. array("mail", "sn", "cn"). + * Note that the "dn" is always returned + * irrespective of which attributes + * types are requested. + * + * @return array the found entries + */ + function ldapSearch($filter, $only_these_attributes) + { + $ldapserver = @ldap_connect($GLOBALS['conf']['ldap']['server']); + $info = ''; + //for fix strange behavior ldap_search doesn't see it as an array + $temp_array = array_reverse($only_these_attributes); + if ($ldapserver != true) { + $this->logger->trace('ERROR', "LDAP connection failed"); + ldap_close($ldapserver); + $info = 'error'; + return $info; + } + + if ($GLOBALS['conf']['ldap']['bind_dn'] == '') { + //anonymous search allowed + $bind = @ldap_bind($ldapserver); + } else { + $bind = @ldap_bind($ldapserver, + $GLOBALS['conf']['ldap']['bind_dn'], + $GLOBALS['conf']['ldap']['bind_password']); + } + + if ($bind != true) { + $this->logger->trace('ERROR', 'LDAP bind failed'); + ldap_close($ldapserver); + $info = 'error'; + return $info; + } + + if ($only_these_attributes == '') { + $result = ldap_search($ldapserver, + $GLOBALS['conf']['ldap']['base_dn'], + $filter); + } else { + $result = ldap_search($ldapserver, + $GLOBALS['conf']['ldap']['base_dn'], + $filter, + $temp_array); + } + + if ($result != true) { + $this->logger->trace('ERROR', 'LDAP search failed'); + ldap_close($ldapserver); + $info = 'error'; + return $info; + } + + if ($info != 'error') { + $info = @ldap_get_entries($ldapserver, $result); + } + + ldap_close($ldapserver); + + return $info; + } + // }}} + + // {{{ ldapLogin() + /** + * This method authenticates the submitted credential against the ldap tree + * + * @param string $userid The user id + * @param string $password The password + * + * @return boolean true on authentication success + */ + function ldapLogin($userid, $password) + { + $login_status = 'error'; + if (strlen($password)>0) { + $ldapserver = @ldap_connect($GLOBALS['conf']['ldap']['server']); + if ($ldapserver != true) { + $this->logger->trace('ERROR', 'LDAP connection failed!'); + ldap_close($ldapserver); + return $login_status; + } + + if ($GLOBALS['conf']['ldap']['bind_dn'] == '') { + //anonymous search allowed + $bind = @ldap_bind($ldapserver); + } else { + $bind = @ldap_bind($ldapserver, + $GLOBALS['conf']['ldap']['bind_dn'], + $GLOBALS['conf']['ldap']['bind_password']); + } + + if ($bind != true) { + $this->logger->trace('ERROR', 'LDAP bind failed'); + ldap_close($ldapserver); + return $login_status; + } + + $filter = $GLOBALS['conf']['ldap']['search_attribute_uid'] . '=' . + $userid; + $result = @ldap_search($ldapserver, + $GLOBALS['conf']['ldap']['base_dn'], + $filter); + $info = @ldap_get_entries($ldapserver, $result); + + if ($result != true || $info['count'] == 0) { + $this->logger->trace('ERROR', 'LDAP search failed'); + ldap_close($ldapserver); + $login_status = false; + return $login_status; + } + + $user_dn = $info[0]['dn']; + $bind = @ldap_bind($ldapserver, $user_dn, $password); + if ($bind) { + $this->logger->trace('DEBUG', 'LDAP OK'); + $login_status = true; + } else { + $this->logger->trace('DEBUG', 'LDAP KO'); + $login_status = false; + } + + ldap_close($ldapserver); + } + return $login_status; + } + // }}} +} +?> \ No newline at end of file diff --git a/lib/logUtil.php b/lib/logUtil.php new file mode 100644 index 0000000..3dbb9d5 --- /dev/null +++ b/lib/logUtil.php @@ -0,0 +1,134 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/** + * Logger Class + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class LogUtil +{ + + // {{{ constructor + /** + * Constructor + * + * @param string $fileName set a custom name for the log file + * @param string $logPath set a custom path for the log file + * + * @return logUtil + * + * @access public + */ + function logUtil($fileName, $logPath='') + { + $this->fileName = $fileName; + if ($logPath=='') { + //Use application log file + if (isset($GLOBALS['conf']['env']['dateFormat'])) { + $this->logPath = ORTRO_LOG . 'ortro_' . + date($GLOBALS['conf']['env']['dateFormat']) . + '.log'; + } else { + //installation log + $this->logPath = ORTRO_LOG . 'ortro_install.log'; + } + } else { + //Use custom log file + $this->logPath = $logPath . '_' . + date($GLOBALS['conf']['env']['dateFormat']) . + '.log'; + } + if (!is_dir(dirname($this->logPath))) { + mkdir(dirname($this->logPath), 0755, true); + } + if (!file_exists($this->logPath)) { + $logfile = fopen($this->logPath, 'w+'); + fclose($logfile); + } + if (isset($GLOBALS['conf']['env']['log_level'])) { + $this->logLevel = $GLOBALS['conf']['env']['log_level']; + } else { + //running installer set to debug + $this->logLevel = 'DEBUG'; + } + } + // }}} + + // {{{ trace() + /** + * This method writes in the log file. + * + * @param string $traceLevel The tracelevel + * @param string $message The message to write + * + * @return void + */ + function trace($traceLevel,$message) + { + if (isset($GLOBALS['conf']['env']['timeFormat'])) { + $dateFormat = date($GLOBALS['conf']['env']['timeFormat']); + } else { + $dateFormat = date('Y-m-d'); + } + if ($this->getTraceLevel($this->logLevel) >= + $this->getTraceLevel($traceLevel)) { + $logMessage = '[' . $traceLevel . '] ' . $dateFormat . + ' - ' . $this->fileName . + ': ' . $message . chr(10); + + error_log($logMessage, 3, $this->logPath); + } + } + // }}} + + // {{{ getTraceLevel() + /** + * This method allows to get the weight of the tracelevel + * + * @param string $traceLevel The tracelevel + * + * @return int The weight + */ + function getTraceLevel($traceLevel) + { + switch ($traceLevel) { + case 'DEBUG': + $weight = 2; + break; + case 'INFO': + $weight = 1; + break; + case 'ERROR': + $weight = 0; + break; + default: + $weight = 0; + break; + } + return $weight; + } + // }}} +} +?> \ No newline at end of file diff --git a/lib/notifyUtil.php b/lib/notifyUtil.php new file mode 100644 index 0000000..ed35618 --- /dev/null +++ b/lib/notifyUtil.php @@ -0,0 +1,139 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; +require_once 'dbUtil.php'; + +/** + * Notification Class + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class NotifyUtil +{ + // {{{ constructor + /** + * notifyUtil Class constructor. + * This flavour of the constructor only enable logging + * identifying it by the name of the class file. + * + * @access public + */ + function notifyUtil() + { + $this->logger = new LogUtil('notifyUtil.php'); + } + // }}} + + // {{{ test() + /** + * This method tests a input value against a specified threshold. + * + * @param int $value The value to test + * @param int $threshold The threshold + * @param string $operator The logical operator + * @param int $is_error On a true comparison result an error + * or success value is returned as defined + * by this value + * + * @return int 1 on success and 0 on error + */ + function &test($value, $threshold, $operator, $is_error) + { + switch ($operator) { + case '>': + if ($value > $threshold) { + $testResult = 1; + } else { + $testResult = 0; + } + break; + case '<': + if ($value < $threshold) { + $testResult = 1; + } else { + $testResult = 0; + } + break; + case '=': + if ($value == $threshold) { + $testResult = 1; + } else { + $testResult = 0; + } + break; + case '!=': + if ($value != $threshold) { + $testResult = 1; + } else { + $testResult = 0; + } + break; + } + + if ($testResult && $is_error == 0) { + //set success + $result = 1; + } + if ($testResult && $is_error == 1) { + //set error + $result = 0; + } + if (!$testResult && $is_error == 0) { + //set error + $result = 0; + } + if (!$testResult && $is_error == 1) { + //set success + $result = 1; + } + return $result; + } + // }}} + + // {{{ sendNotify() + /** + * This method execute the requested notification plugin + * using the concept of variable functions. + * + * @param array $notify_type The notification info + * @param int $result The job result + * @param array $attachments The attachments for notification + * + * @return void + */ + function sendNotify($notify_type, $parameters, $attachments) + { + //send the notify + $notify_plugin_path = ORTRO_NOTIFICATION_PLUGINS . + $notify_type . DS; + @include_once $notify_plugin_path . 'configure.php'; + include_once $notify_plugin_path . 'core.php'; + //add the job_result to notify_info for eventual attach + $notify_function = $notify_type . 'Notify'; + $notify_function($parameters, $attachments); + } + // }}} +} +?> \ No newline at end of file diff --git a/lib/sshUtil.php b/lib/sshUtil.php new file mode 100644 index 0000000..cf2bc83 --- /dev/null +++ b/lib/sshUtil.php @@ -0,0 +1,115 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; + +/** + * SSH Class + * + * @category Libs + * @package Ortro + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ +class SSHUtil +{ + // {{{ constructor + /** + * SshUtil Class constructor. + * This flavour of the constructor only enable logging + * identifying it by the name of the class file. + * + * @access public + */ + function sshUtil() + { + $this->logger = new LogUtil('sshUtil.php'); + } + // }}} + + // {{{ sshConn() + /** + * This method executes a command on a remote host using ssh + * + * @param string $user The user to login + * @param string $ip The ip address of the remote host + * @param string $port The port to connect + * @param string $path_script The command script to execute + * @param boolean $local If the script to execute is stored locally or + * on the remote machine (default) + * @param boolean $run_bg Run the command in background + * + * @return array Contains the standard output and exit code + */ + function sshConn($user, $ip, $port, $path_script, $local = false, $local_parameters = '') + { + if ($port == '') { + $port = '22'; + } + + if ($GLOBALS['conf']['env']['ssh_StrictHostKeyChecking'] == 'no') { + $StrictHostKeyChecking = ' -o StrictHostKeyChecking=no '; + } else { + $StrictHostKeyChecking = ''; + } + + if ($local === false) { + $script = '"' . $path_script . '" 2>&1'; + } else { + if (!is_file($path_script)) { + $msg = "The script $path_script was not found on the local server"; + return array('stdout' => array($msg), 'exit_code' => '1' ); + } + $script = '"/bin/sh -s ' . $local_parameters . + ' 2>&1" < ' . escapeshellarg($path_script); + } + + + $cmdLine = 'nohup ' . escapeshellarg($GLOBALS['conf']['env']['ssh_path'] . 'ssh') . + ' -i ' . + escapeshellarg(ORTRO_SSH_PATH . + $GLOBALS['conf']['env']['ssh_keyname']) . + $run_bg . + $StrictHostKeyChecking . + ' -p ' . + escapeshellarg($port) . + ' ' . + escapeshellarg($user) . + '@' . + escapeshellarg($ip) . + ' ' . + $script; + + $this->logger->trace('DEBUG', $cmdLine); + + exec($cmdLine, $stdout, $exit_code); + + if ($exit_code != '0') { + $this->logger->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . implode("\n", $stdout)); + } + + $result = array('stdout' => $stdout, 'exit_code' => $exit_code ); + return $result; + } + // }}} +} +?> diff --git a/packages/deb/crontab.php b/packages/deb/crontab.php new file mode 100644 index 0000000..a491df2 --- /dev/null +++ b/packages/deb/crontab.php @@ -0,0 +1,26 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once '/etc/ortro/init.inc.php'; +require_once 'cronUtil.php'; +$cronUtil = new CronUtil(); +$cronUtil->runCron(); + +?> diff --git a/packages/deb/init.inc.php b/packages/deb/init.inc.php new file mode 100644 index 0000000..bac359d --- /dev/null +++ b/packages/deb/init.inc.php @@ -0,0 +1,22 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once '/etc/ortro/init.php'; +?> diff --git a/packages/deb/init.php b/packages/deb/init.php new file mode 100644 index 0000000..daa6d67 --- /dev/null +++ b/packages/deb/init.php @@ -0,0 +1,102 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//########### ENV SETTINGS ########### +// DON'T MODIFY THE LINES BELOW !!!! # +//#################################### + +define('ORTRO_VERSION', '1.3.4'); +define('ORTRO_DEFAULT_LANGUAGE', 'en'); + +define('DS', DIRECTORY_SEPARATOR); +define('ORTRO_PATH', '/usr/share/ortro/'); + +define('ORTRO_CONF', '/etc/ortro/'); +define('ORTRO_CONF_PLUGINS', ORTRO_CONF . 'plugins' . DS); +define('ORTRO_SSH_PATH', ORTRO_CONF .'.ssh' . DS); +define('ORTRO_SESSION_SAVE_PATH', ORTRO_CONF .'session' . DS); + +define('ORTRO_DATA', '/var/lib/ortro/'); +define('ORTRO_FILES', ORTRO_DATA . 'files' . DS); +define('ORTRO_INCOMING', ORTRO_DATA . 'incoming' . DS); +define('ORTRO_REPORTS', ORTRO_DATA . 'reports' . DS); +define('ORTRO_SQLITE_DB', ORTRO_DATA . 'db' . DS); +define('ORTRO_ATTACHMENTS', ORTRO_DATA . 'attachments' . DS); + +define('ORTRO_LANG', ORTRO_PATH . 'lang' . DS); + +define('ORTRO_LIB', '/usr/share/php/ortro/'); +define('ORTRO_LIB_PEAR', ORTRO_LIB . 'Pear' . DS); + +define('ORTRO_LOG', '/var/log/ortro/'); +define('ORTRO_LOG_PLUGINS', ORTRO_LOG . 'plugins' . DS); + +define('ORTRO_PLUGINS', ORTRO_PATH . 'plugins' . DS); +define('ORTRO_NOTIFICATION_PLUGINS', ORTRO_PLUGINS . 'notification' . DS); + +define('ORTRO_TEMP', '/tmp/ortro/'); + +define('ORTRO_WEB', '/usr/share/ortro/www/'); +define('ORTRO_TEMPLATE', ORTRO_WEB . 'template' . DS); +define('ORTRO_INSTALL', ORTRO_TEMPLATE . 'install' . DS); + +//### ADD LIBS TO LIB_PATH ### +//Avoid problems with magic_quotes_runtime +@ini_set('magic_quotes_runtime', false); +//Disable display error +@ini_set('display_startup_errors', false); +@ini_set('display_errors', false); + +set_include_path(".:".ORTRO_LIB.":".ORTRO_LIB_PEAR.":".ORTRO_PLUGINS); + +//prepare config array() +global $conf; +$conf = array(); + +if (file_exists(ORTRO_CONF . 'configure.php')) { + include_once ORTRO_CONF . 'configure.php'; +} + +/** + * Throw new exception on error + * + * @param int $errno Contains the level of the error raised, as an integer. + * @param string $errstr Contains the error message + * @param string $errfile Contains the filename that the error was raised in + * @param int $errline Contains the line number the error was raised at + * @param array $errcontext An array that points to the active symbol + * table at the point the error occurred. + * In other words, errcontext will contain + * an array of every variable that existed in the scope + * the error was triggered in. + * + * @return boolean + * + */ +function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) +{ + if ($errno == E_WARNING || $errno == E_PARSE || $errno == E_ERROR) { + throw new Exception($errstr, $errno); + return true; + } else { + return false; + } +} +?> diff --git a/packages/deb/mkdeb.sh b/packages/deb/mkdeb.sh new file mode 100755 index 0000000..00b3e22 --- /dev/null +++ b/packages/deb/mkdeb.sh @@ -0,0 +1,91 @@ +#!/bin/bash +cat > ortro.list < +%readme /usr/share/ortro/README +%license /usr/share/ortro/LICENSE +%requires apache2,openssh-client,openssh-server,mysql-server,php5,php5-cli,php5-mysql,php5-ldap,php-pear,php5-sqlite +%postinstall < post_install.sh +%postremove < post_remove.sh + +EOF +VAR=$1 +VAR=${VAR:="notset"} +# PREFIX +PREFIX=deb_dir +# DIR DEF +ETC=$PREFIX/etc/ortro +SHARE=$PREFIX/usr/share/ortro +PHP=$PREFIX/usr/share/php/ortro +WWW=$PREFIX/usr/share/ortro/www + +if [ "$VAR" == "copy" ] +then + echo "Copy file" + ## ETC + if [ ! -d $ETC ] + then + mkdir -p $ETC && echo mkdir $ETC + fi + # copy for ETC + echo ETC + for FILE in ../../conf/* ./ortro-apache2.conf ./init.inc.php ./init.php + do + cp -r $FILE $ETC && echo copy $FILE $ETC + done + ## PHP + if [ ! -d $PHP ] + then + mkdir -p $PHP && echo mkdir $PHP + fi + # copy for PHP + echo PHP + for FILE in ../../lib/* + do + cp -r $FILE $PHP && echo copy $FILE $PHP + done + ## SHARE + if [ ! -d $SHARE ] + then + mkdir -p $SHARE && echo mkdir $SHARE + fi + ## create $SHARE/plugins + mkdir -p $SHARE/plugins && echo mkdir $SHARE/plugins + # copy init.inc.php in $SHARE/plugins language files + cp ./init.inc.php $SHARE/plugins/ && echo copy ./init.inc.php $SHARE/plugins + # copy for SHARE + echo SHARE + for FILE in ../../bin ../../lang + do + cp -r $FILE $SHARE && echo copy $FILE $SHARE + done + # remove plugins language files + rm -rf $SHARE/lang/*/plugins/* + ## WWW + if [ ! -d $WWW ] + then + mkdir -p $WWW && echo mkdir $WWW + fi + # copy for WWW + echo WWW + for FILE in ../../www/* ../../LICENSE ../../README ../../COPYRIGHT ./init.inc.php + do + cp -r $FILE $WWW && echo copy $FILE $WWW + done + # copy new crontab.php + cp ./crontab.php $SHARE/bin +fi +if [ $VAR == "deb" ] +then + echo "Create Package" + mkepmlist -g www-data -u root --prefix / ./$PREFIX/ | grep -v svn >> ortro.list + epm -a all -n -f deb ortro + cp linux-2.6-all/ortro*.deb ./ + rm -rf linux-2.6-all + rm -rf deb_dir + rm -fr ortro.list +fi +[ $VAR == "notset" ] && echo "usage: mkdeb.sh copy|deb" diff --git a/packages/deb/ortro-apache2.conf b/packages/deb/ortro-apache2.conf new file mode 100644 index 0000000..45a28d9 --- /dev/null +++ b/packages/deb/ortro-apache2.conf @@ -0,0 +1,6 @@ +# Alias for Ortro path +Alias /ortro /usr/share/ortro/www + + Options None + AllowOverride None + diff --git a/packages/deb/post_install.sh b/packages/deb/post_install.sh new file mode 100755 index 0000000..c7e36f1 --- /dev/null +++ b/packages/deb/post_install.sh @@ -0,0 +1,15 @@ +/bin/chown -R root:www-data /etc/ortro +/bin/chmod 770 /etc/ortro +/usr/bin/find /etc/ortro -type f | /usr/bin/xargs /bin/chmod 660 +/bin/chown -R root:www-data /usr/share/ortro +/bin/chmod 775 /usr/share/ortro +/usr/bin/find /usr/share/ortro -type d | /usr/bin/xargs /bin/chmod 775 +/usr/bin/find /usr/share/ortro -type f | /usr/bin/xargs /bin/chmod 664 +/bin/chown -R root:www-data /usr/share/php/ortro +/usr/bin/find /usr/share/php/ortro -type d | /usr/bin/xargs /bin/chmod 755 +/usr/bin/find /usr/share/php/ortro -type f | /usr/bin/xargs /bin/chmod 644 +[ ! -d /var/log/ortro ] && mkdir /var/log/ortro && /bin/chown -R root:www-data /var/log/ortro && /bin/chmod 770 /var/log/ortro +[ ! -d /var/lib/ortro ] && mkdir /var/lib/ortro && /bin/chown -R root:www-data /var/lib/ortro && /bin/chmod 770 /var/lib/ortro +ln -s /var/log/ortro /usr/share/ortro/log && /bin/chown -R root:www-data /usr/share/ortro/log +cp /etc/ortro/ortro-apache2.conf /etc/apache2/sites-available/ +/usr/sbin/a2ensite ortro-apache2.conf 2>&1 diff --git a/packages/deb/post_remove.sh b/packages/deb/post_remove.sh new file mode 100755 index 0000000..38e66aa --- /dev/null +++ b/packages/deb/post_remove.sh @@ -0,0 +1,9 @@ +/usr/sbin/a2dissite ortro-apache2.conf 2>&1 >/dev/null && /etc/init.d/apache2 reload +if [ -d /var/lib/ortro ] +then + rm -rf /var/lib/ortro +fi +if [ -d /var/log/ortro ] +then + rm -rf /var/log/ortro +fi diff --git a/plugins/database/check_tablespace/CHANGELOG b/plugins/database/check_tablespace/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/database/check_tablespace/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/database/check_tablespace/LICENSE b/plugins/database/check_tablespace/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/database/check_tablespace/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/check_tablespace/configure.php b/plugins/database/check_tablespace/configure.php new file mode 100644 index 0000000..f4f4df9 --- /dev/null +++ b/plugins/database/check_tablespace/configure.php @@ -0,0 +1,89 @@ + + * @link http://www.ortro.net + */ + +$plugin_actions['check_tablespace'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['check_tablespace'][0]['action'] = 'plugin'; +$plugin_actions['check_tablespace'][0]['file'] = 'display_reports'; +$plugin_actions['check_tablespace'][0]['image'] = 'archive.png'; + +$plugin_field['check_tablespace'][0]['version'] = '1.2.2'; +$plugin_field['check_tablespace'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['check_tablespace'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['check_tablespace'][0]['description'] = PLUGIN_DB_CHECK_TABLESPACE_DESCRIPTION; +$plugin_field['check_tablespace'][0]['title'] = PLUGIN_DB_CHECK_TABLESPACE_TITLE; + +$plugin_field['check_tablespace'][1]['type'] = 'text'; +$plugin_field['check_tablespace'][1]['name'] = 'db_check_tablespace_identity'; +$plugin_field['check_tablespace'][1]['value'] = ''; +$plugin_field['check_tablespace'][1]['attributes'] = 'disabled readonly'; +$plugin_field['check_tablespace'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['check_tablespace'][1]['num_rules'] = '1'; +$plugin_field['check_tablespace'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['check_tablespace'][1]['rule_type'][0] = 'required'; +$plugin_field['check_tablespace'][1]['rule_attribute'][0] = ''; + +$plugin_field['check_tablespace'][2]['type'] = 'textarea'; +$plugin_field['check_tablespace'][2]['name'] = 'db_check_tablespace_query'; +$plugin_field['check_tablespace'][2]['value'] = 'SELECT df.tablespace_name TABLESPACE,'. + 'df.total_space_mb TOTAL_SPACE_MB,'. + '(df.total_space_mb - fs.free_space_mb) USED_SPACE_MB,'. + 'fs.free_space_mb FREE_SPACE_MB,'. + 'ROUND(100 * (fs.free_space / df.total_space),2) PCT_FREE '. + 'FROM (SELECT tablespace_name, SUM(bytes) TOTAL_SPACE, '. + 'ROUND(SUM(bytes) / 1048576) TOTAL_SPACE_MB '. + 'FROM dba_data_files '. + 'GROUP BY tablespace_name) df, '. + '(SELECT tablespace_name, SUM(bytes) FREE_SPACE, '. + 'ROUND(SUM(bytes) / 1048576) FREE_SPACE_MB '. + 'FROM dba_free_space '. + 'GROUP BY tablespace_name) fs '. + 'WHERE df.tablespace_name = fs.tablespace_name (+) '. + 'ORDER BY 5'; + +$plugin_field['check_tablespace'][2]['attributes'] = 'disabled rows=30 cols=70'; +$plugin_field['check_tablespace'][2]['description'] = PLUGIN_QUERY; +$plugin_field['check_tablespace'][2]['num_rules'] = '1'; +$plugin_field['check_tablespace'][2]['rule_msg'][0] = PLUGIN_QUERY_RULE; +$plugin_field['check_tablespace'][2]['rule_type'][0] = 'required'; +$plugin_field['check_tablespace'][2]['rule_attribute'][0] = ''; + +$plugin_field['check_tablespace'][3]['type'] = 'select'; +$plugin_field['check_tablespace'][3]['name'] = 'db_check_tablespace_attach_result'; +$plugin_field['check_tablespace'][3]['value'] = array('html' => '.html', + 'txt' => '.txt', + 'csv' => '.csv'); +$plugin_field['check_tablespace'][3]['attributes'] = ''; +$plugin_field['check_tablespace'][3]['description'] = PLUGIN_ATTACH_RESULT; + +$plugin_field['check_tablespace'][4]['type'] = 'text'; +$plugin_field['check_tablespace'][4]['name'] = 'db_check_tablespace_file_name'; +$plugin_field['check_tablespace'][4]['value'] = ''; +$plugin_field['check_tablespace'][4]['attributes'] = 'disabled'; +$plugin_field['check_tablespace'][4]['description'] = PLUGIN_FILE_NAME; +$plugin_field['check_tablespace'][4]['num_rules'] = '1'; +$plugin_field['check_tablespace'][4]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['check_tablespace'][4]['rule_type'][0] = 'required'; +$plugin_field['check_tablespace'][4]['rule_attribute'][0] = ''; + +$plugin_field['check_tablespace'][5]['type'] = 'text'; +$plugin_field['check_tablespace'][5]['name'] = 'db_check_tablespace_retention'; +$plugin_field['check_tablespace'][5]['value'] = ''; +$plugin_field['check_tablespace'][5]['attributes'] = 'disabled'; +$plugin_field['check_tablespace'][5]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/database/check_tablespace/core.php b/plugins/database/check_tablespace/core.php new file mode 100644 index 0000000..51186ce --- /dev/null +++ b/plugins/database/check_tablespace/core.php @@ -0,0 +1,156 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + include_once 'ioUtil.php'; + + //Get the params required by plugin from argv + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $query = $parameters['db_check_tablespace_query']; + $attach_result_as = $parameters['db_check_tablespace_attach_result']; + $filename = $parameters['db_check_tablespace_file_name']; + + + if ($filename == '') { + $filename = 'file'; + } + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + $id_system = $job_infos['id_system']; + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $rows = $dbUtil->dbQuery($dbh, $query, MDB2_FETCHMODE_ASSOC); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + if (count($rows)>0) { + + $reports_storing_path = ORTRO_REPORTS . $id_system . DIRECTORY_SEPARATOR . + $id_job . DIRECTORY_SEPARATOR; + + switch ($attach_result_as) { + case 'html': + $th_class = 'class="background-color : #eee; ' . + 'border-bottom : 1px #bbb solid; ' . + 'border-right : 1px #bbb solid;' . + 'text-align : left;' . + 'font-family : verdana;' . + 'font-size : 8pt;' . + 'font-weight : bold;"'; + + $td_class = 'class="font-family : arial, helvetica, sans-serif; ' . + 'font-size : 10pt;"'; + + include_once 'Pear/HTML/Table.php'; + $table = new HTML_Table('cellpadding=4 cellspacing=0 border=1'); + $column_name = array_keys($rows[0]); + $table->addRow($column_name, $th_class, 'TH'); + foreach ($rows as $row) { + $table_row = array(); + foreach ($column_name as $name) { + array_push($table_row, $row[$name]); + } + $table->addRow($table_row, '', 'TD', false); + } + $attachments['html'] = $table->toHTML(); + createHTMLFile($attachments['html'], $reports_storing_path, $filename); + break; + + case 'txt': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'txt', + "\t", + "\n"); + + $attachments['file'] = array($temp_file); + break; + + case 'csv': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'csv', + ';', + "\n"); + + $attachments['file'] = array($temp_file); + break; + } + + $result = 1; + $msg_exec = $result; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'FILESYSTEM'; + + $retention_data['retention'] = $parameters['db_check_tablespace_retention']; + $retention_data['path'] = $reports_storing_path; + $retention_data['filename'] = $filename; + } + //---- End plugin code ----- +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> diff --git a/plugins/database/custom_query/CHANGELOG b/plugins/database/custom_query/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/database/custom_query/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/database/custom_query/LICENSE b/plugins/database/custom_query/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/database/custom_query/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/custom_query/configure.php b/plugins/database/custom_query/configure.php new file mode 100644 index 0000000..e457fae --- /dev/null +++ b/plugins/database/custom_query/configure.php @@ -0,0 +1,82 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['custom_query'][0]['description'] = PLUGIN_METADATA_CONFIGURATION; +$plugin_actions['custom_query'][0]['action'] = 'plugin'; +$plugin_actions['custom_query'][0]['file'] = 'display_archive_results'; +$plugin_actions['custom_query'][0]['image'] = 'archive.png'; + +$plugin_field['custom_query'][0]['version'] = '1.2.2'; +$plugin_field['custom_query'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['custom_query'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['custom_query'][0]['description'] = PLUGIN_DB_CUSTOM_QUERY_DESCRIPTION; +$plugin_field['custom_query'][0]['title'] = PLUGIN_DB_CUSTOM_QUERY_TITLE; + +$plugin_field['custom_query'][1]['type'] = 'text'; +$plugin_field['custom_query'][1]['name'] = 'db_custom_query_identity'; +$plugin_field['custom_query'][1]['value'] = ''; +$plugin_field['custom_query'][1]['attributes'] = 'disabled readonly'; +$plugin_field['custom_query'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['custom_query'][1]['num_rules'] = '1'; +$plugin_field['custom_query'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['custom_query'][1]['rule_type'][0] = 'required'; +$plugin_field['custom_query'][1]['rule_attribute'][0] = ''; + +$plugin_field['custom_query'][2]['type'] = 'textarea'; +$plugin_field['custom_query'][2]['name'] = 'db_custom_query_query'; +$plugin_field['custom_query'][2]['value'] = ''; +$plugin_field['custom_query'][2]['attributes'] = 'disabled rows=5 cols=50'; +$plugin_field['custom_query'][2]['description'] = PLUGIN_QUERY ; +$plugin_field['custom_query'][2]['num_rules'] = '1'; +$plugin_field['custom_query'][2]['rule_msg'][0] = PLUGIN_QUERY_RULE; +$plugin_field['custom_query'][2]['rule_type'][0] = 'required'; +$plugin_field['custom_query'][2]['rule_attribute'][0] = ''; + +$plugin_field['custom_query'][3]['type'] = 'select'; +$plugin_field['custom_query'][3]['name'] = 'db_custom_query_operator'; +$plugin_field['custom_query'][3]['value'] = array('>' => '>', '<' => '<', '=' => '=', '!=' => '!='); +$plugin_field['custom_query'][3]['attributes'] = ''; +$plugin_field['custom_query'][3]['description'] = PLUGIN_DB_CUSTOM_QUERY_OPERATOR_DESCRIPTION; +$plugin_field['custom_query'][3]['num_rules'] = '0'; + +$plugin_field['custom_query'][4]['type'] = 'text'; +$plugin_field['custom_query'][4]['name'] = 'db_custom_query_threshold'; +$plugin_field['custom_query'][4]['value'] = ''; +$plugin_field['custom_query'][4]['attributes'] = 'disabled'; +$plugin_field['custom_query'][4]['description'] = PLUGIN_DB_CUSTOM_QUERY_THRESHOLD_DESCRIPTION; +$plugin_field['custom_query'][4]['num_rules'] = '1'; +$plugin_field['custom_query'][4]['rule_msg'][0] = PLUGIN_DB_CUSTOM_QUERY_RULE_4_0; +$plugin_field['custom_query'][4]['rule_type'][0] = 'required'; +$plugin_field['custom_query'][4]['rule_attribute'][0] = ''; + +$plugin_field['custom_query'][5]['type'] = 'select'; +$plugin_field['custom_query'][5]['name'] = 'db_custom_query_is_error'; +$plugin_field['custom_query'][5]['value'] = array('0' => PLUGIN_DB_CUSTOM_QUERY_SUCCESS, + '1' => PLUGIN_DB_CUSTOM_QUERY_ERROR); +$plugin_field['custom_query'][5]['attributes'] = ''; +$plugin_field['custom_query'][5]['description'] = PLUGIN_DB_CUSTOM_QUERY_ERROR_DESCRIPTION ; +$plugin_field['custom_query'][5]['num_rules'] = '0'; + +$plugin_field['custom_query'][6]['type'] = 'text'; +$plugin_field['custom_query'][6]['name'] = 'db_custom_query_retention'; +$plugin_field['custom_query'][6]['value'] = ''; +$plugin_field['custom_query'][6]['attributes'] = 'disabled'; +$plugin_field['custom_query'][6]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/database/custom_query/core.php b/plugins/database/custom_query/core.php new file mode 100644 index 0000000..b36aae3 --- /dev/null +++ b/plugins/database/custom_query/core.php @@ -0,0 +1,115 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + include_once 'dbUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //---- Start plugin code ----- + + //Get the params required by plugin from argv + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $query = $parameters['db_custom_query_query']; + $operator = $parameters['db_custom_query_operator']; + $threshold = $parameters['db_custom_query_threshold']; + $is_error = $parameters['db_custom_query_is_error']; + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + + try { + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $rows = $dbUtil->dbQuery($dbh, $query); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + $testValue = $rows[0][0]; + $loggerPlugin->trace('DEBUG', 'id=' . $id_job . ' result:' . $testValue); + + $result = notifyUtil::test($testValue, $threshold, $operator, $is_error); + $msg_exec = $testValue; + + $attachments['txt'] = $testValue; + $attachments['html'] = $testValue; + } catch (Exception $e) { + $result = 0; + $msg_exec = $e->getMessage(); + + $attachments['txt'] = $msg_exec; + $attachments['html'] = $msg_exec; + $loggerPlugin->trace('ERROR', $msg_exec); + } + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['db_custom_query_retention']; + + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/database/custom_query_report/CHANGELOG b/plugins/database/custom_query_report/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/database/custom_query_report/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/database/custom_query_report/LICENSE b/plugins/database/custom_query_report/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/database/custom_query_report/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/custom_query_report/configure.php b/plugins/database/custom_query_report/configure.php new file mode 100644 index 0000000..449e33c --- /dev/null +++ b/plugins/database/custom_query_report/configure.php @@ -0,0 +1,75 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['custom_query_report'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['custom_query_report'][0]['action'] = 'plugin'; +$plugin_actions['custom_query_report'][0]['file'] = 'display_reports'; +$plugin_actions['custom_query_report'][0]['image'] = 'archive.png'; + +$plugin_field['custom_query_report'][0]['version'] = '1.2.2'; +$plugin_field['custom_query_report'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['custom_query_report'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['custom_query_report'][0]['description'] = PLUGIN_DB_CUSTOM_QUERY_REPORT_DESCRIPTION; +$plugin_field['custom_query_report'][0]['title'] = PLUGIN_DB_CUSTOM_QUERY_REPORT_TITLE; + +$plugin_field['custom_query_report'][1]['type'] = 'text'; +$plugin_field['custom_query_report'][1]['name'] = 'db_custom_query_report_identity'; +$plugin_field['custom_query_report'][1]['value'] = ''; +$plugin_field['custom_query_report'][1]['attributes'] = 'disabled readonly'; +$plugin_field['custom_query_report'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['custom_query_report'][1]['num_rules'] = '1'; +$plugin_field['custom_query_report'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['custom_query_report'][1]['rule_type'][0] = 'required'; +$plugin_field['custom_query_report'][1]['rule_attribute'][0] = ''; + +$plugin_field['custom_query_report'][2]['type'] = 'textarea'; +$plugin_field['custom_query_report'][2]['name'] = 'db_custom_query_report_query'; +$plugin_field['custom_query_report'][2]['value'] = ''; +$plugin_field['custom_query_report'][2]['attributes'] = 'disabled rows=30 cols=70'; +$plugin_field['custom_query_report'][2]['description'] = PLUGIN_QUERY; +$plugin_field['custom_query_report'][2]['num_rules'] = '1'; +$plugin_field['custom_query_report'][2]['rule_msg'][0] = PLUGIN_QUERY_RULE; +$plugin_field['custom_query_report'][2]['rule_type'][0] = 'required'; +$plugin_field['custom_query_report'][2]['rule_attribute'][0] = ''; + +$plugin_field['custom_query_report'][3]['type'] = 'select'; +$plugin_field['custom_query_report'][3]['name'] = 'db_custom_query_report_attach_result'; +$plugin_field['custom_query_report'][3]['value'] = array('html' => '.html', + 'txt' => '.txt', + 'csv' => '.csv'); +$plugin_field['custom_query_report'][3]['attributes'] = ''; +$plugin_field['custom_query_report'][3]['description'] = PLUGIN_ATTACH_RESULT; + +$plugin_field['custom_query_report'][4]['type'] = 'text'; +$plugin_field['custom_query_report'][4]['name'] = 'db_custom_query_report_file_name'; +$plugin_field['custom_query_report'][4]['value'] = ''; +$plugin_field['custom_query_report'][4]['attributes'] = 'disabled'; +$plugin_field['custom_query_report'][4]['description'] = PLUGIN_FILE_NAME; +$plugin_field['custom_query_report'][4]['num_rules'] = '1'; +$plugin_field['custom_query_report'][4]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['custom_query_report'][4]['rule_type'][0] = 'required'; +$plugin_field['custom_query_report'][4]['rule_attribute'][0] = ''; + +$plugin_field['custom_query_report'][5]['type'] = 'text'; +$plugin_field['custom_query_report'][5]['name'] = 'db_custom_query_report_retention'; +$plugin_field['custom_query_report'][5]['value'] = ''; +$plugin_field['custom_query_report'][5]['attributes'] = 'disabled'; +$plugin_field['custom_query_report'][5]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/database/custom_query_report/core.php b/plugins/database/custom_query_report/core.php new file mode 100644 index 0000000..df96ea9 --- /dev/null +++ b/plugins/database/custom_query_report/core.php @@ -0,0 +1,161 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + include_once 'ioUtil.php'; + include_once 'dbUtil.php'; + + //Get the params required by plugin from argv + + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $query = $parameters['db_custom_query_report_query']; + $attach_result_as = $parameters['db_custom_query_report_attach_result']; + $filename = $parameters['db_custom_query_report_file_name']; + + if ($filename == '') { + $filename = 'file'; + } + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + $id_system = $job_infos['id_system']; + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $rows = $dbUtil->dbQuery($dbh, $query, MDB2_FETCHMODE_ASSOC); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + if (count($rows)>0) { + + $reports_storing_path = ORTRO_REPORTS . $id_system . + DIRECTORY_SEPARATOR . $id_job . + DIRECTORY_SEPARATOR; + + switch ($attach_result_as) { + case 'html': + $th_class = 'class="background-color : #eee; ' . + 'border-bottom : 1px #bbb solid; ' . + 'border-right : 1px #bbb solid;' . + 'text-align : left;' . + 'font-family : verdana;' . + 'font-size : 8pt;' . + 'font-weight : bold;"'; + $td_class = 'class="font-family : arial, helvetica, sans-serif; ' . + 'font-size : 10pt;"'; + + include_once 'Pear/HTML/Table.php'; + $table = new HTML_Table('cellpadding=4 cellspacing=0 border=1'); + $column_name = array_keys($rows[0]); + $table->addRow($column_name, $th_class, 'TH'); + foreach ($rows as $row) { + $table_row = array(); + foreach ($column_name as $name) { + array_push($table_row, $row[$name]); + } + $table->addRow($table_row, '', 'TD', false); + } + + $attachments['html'] = $table->toHTML(); + createHTMLFile($attachments['html'], $reports_storing_path, $filename); + break; + + case 'txt': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'txt', + "\t", + "\n"); + + $attachments['file'] = array($temp_file); + break; + + case 'csv': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'csv', + ';', + "\n"); + + $attachments['file'] = array($temp_file); + break; + } + + $result = 1; + $msg_exec = $result; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'FILESYSTEM'; + $retention_data['retention'] = $parameters['db_custom_query_report_retention']; + $retention_data['path'] = $reports_storing_path; + $retention_data['filename'] = $filename; + + } else { + $msg_exec = 'No records found.'; + } + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/database/execute_sql_from_file/CHANGELOG b/plugins/database/execute_sql_from_file/CHANGELOG new file mode 100644 index 0000000..8d7173e --- /dev/null +++ b/plugins/database/execute_sql_from_file/CHANGELOG @@ -0,0 +1,6 @@ +1.0.1 (2008.06.09) +Fixed. #74 Incorrect min version required + +1.0.0 (2008.06.06) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/database/execute_sql_from_file/LICENSE b/plugins/database/execute_sql_from_file/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/database/execute_sql_from_file/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/execute_sql_from_file/configure.php b/plugins/database/execute_sql_from_file/configure.php new file mode 100644 index 0000000..46b4030 --- /dev/null +++ b/plugins/database/execute_sql_from_file/configure.php @@ -0,0 +1,45 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$_plugin_name = 'execute_sql_from_file'; +$plugin_field[$_plugin_name][0]['version'] = '1.0.1'; +$plugin_field[$_plugin_name][0]['min_ortro_version'] = '1.3.1'; +$plugin_field[$_plugin_name][0]['authors'][0] = 'Luca Corbo '; +$plugin_field[$_plugin_name][0]['description'] = PLUGIN_DB_EXECUTE_SQL_FROM_FILE_DESCRIPTION; +$plugin_field[$_plugin_name][0]['title'] = PLUGIN_DB_EXECUTE_SQL_FROM_FILE_TITLE; + +$plugin_field[$_plugin_name][1]['type'] = 'text'; +$plugin_field[$_plugin_name][1]['name'] = 'db_execute_sql_from_file_identity'; +$plugin_field[$_plugin_name][1]['value'] = ''; +$plugin_field[$_plugin_name][1]['attributes'] = 'disabled readonly'; +$plugin_field[$_plugin_name][1]['description'] = PLUGIN_IDENTITY; +$plugin_field[$_plugin_name][1]['num_rules'] = '1'; +$plugin_field[$_plugin_name][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field[$_plugin_name][1]['rule_type'][0] = 'required'; +$plugin_field[$_plugin_name][1]['rule_attribute'][0] = ''; + +$plugin_field[$_plugin_name][2]['type'] = 'file'; +$plugin_field[$_plugin_name][2]['required'] = true;//check for uploaded file only when adding it. +$plugin_field[$_plugin_name][2]['name'] = 'db_execute_sql_from_file_query'; +$plugin_field[$_plugin_name][2]['value'] = ''; +$plugin_field[$_plugin_name][2]['attributes'] = 'disabled size=70'; +$plugin_field[$_plugin_name][2]['description'] = PLUGIN_DB_EXECUTE_SQL_FROM_FILE ; +$plugin_field[$_plugin_name][2]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/database/execute_sql_from_file/core.php b/plugins/database/execute_sql_from_file/core.php new file mode 100644 index 0000000..525ea05 --- /dev/null +++ b/plugins/database/execute_sql_from_file/core.php @@ -0,0 +1,93 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + include_once 'dbUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //---- Start plugin code ----- + + //Get the params required by plugin from argv + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $sql_file = ORTRO_ATTACHMENTS . $id_job . DS . $parameters['db_execute_sql_from_file_query']; + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + + try { + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $dbUtil->dbExecFromFile($dbh, $sql_file); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + $loggerPlugin->trace('DEBUG', 'id=' . $id_job . ' result: file_query_ok'); + + $msg_exec = 'Ok'; + $result = 1; + } catch (Exception $e) { + $msg_exec = $e->getMessage(); + $loggerPlugin->trace('ERROR', $msg_exec); + } + //---- End plugin code ----- + + $attachments['txt'] = $msg_exec; + $attachments['html'] = $msg_exec; + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/database/mysql_table_check/CHANGELOG b/plugins/database/mysql_table_check/CHANGELOG new file mode 100755 index 0000000..8081e08 --- /dev/null +++ b/plugins/database/mysql_table_check/CHANGELOG @@ -0,0 +1,3 @@ +1.0.0 (2008.06.19) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/database/mysql_table_check/LICENSE b/plugins/database/mysql_table_check/LICENSE new file mode 100755 index 0000000..d511905 --- /dev/null +++ b/plugins/database/mysql_table_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/mysql_table_check/configure.php b/plugins/database/mysql_table_check/configure.php new file mode 100755 index 0000000..f8743b5 --- /dev/null +++ b/plugins/database/mysql_table_check/configure.php @@ -0,0 +1,47 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['mysql_table_check'][0]['description'] = PLUGIN_METADATA_CONFIGURATION; +$plugin_actions['mysql_table_check'][0]['action'] = 'plugin'; +$plugin_actions['mysql_table_check'][0]['file'] = 'display_archive_results'; +$plugin_actions['mysql_table_check'][0]['image'] = 'archive.png'; + +$plugin_field['mysql_table_check'][0]['version'] = '1.0.0'; +$plugin_field['mysql_table_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['mysql_table_check'][0]['authors'][0] = 'Michael Mueller '; +$plugin_field['mysql_table_check'][0]['description'] = PLUGIN_DB_MYSQL_CHECK_TABLES_DESCRIPTION; +$plugin_field['mysql_table_check'][0]['title'] = PLUGIN_DB_MYSQL_CHECK_TABLES_TITLE; + +$plugin_field['mysql_table_check'][1]['type'] = 'text'; +$plugin_field['mysql_table_check'][1]['name'] = 'db_mysql_table_check_identity'; +$plugin_field['mysql_table_check'][1]['value'] = ''; +$plugin_field['mysql_table_check'][1]['attributes'] = 'disabled readonly'; +$plugin_field['mysql_table_check'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['mysql_table_check'][1]['num_rules'] = '1'; +$plugin_field['mysql_table_check'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['mysql_table_check'][1]['rule_type'][0] = 'required'; +$plugin_field['mysql_table_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['mysql_table_check'][2]['type'] = 'text'; +$plugin_field['mysql_table_check'][2]['name'] = 'db_mysql_table_check_retention'; +$plugin_field['mysql_table_check'][2]['value'] = ''; +$plugin_field['mysql_table_check'][2]['attributes'] = 'disabled'; +$plugin_field['mysql_table_check'][2]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/database/mysql_table_check/core.php b/plugins/database/mysql_table_check/core.php new file mode 100755 index 0000000..432ce6f --- /dev/null +++ b/plugins/database/mysql_table_check/core.php @@ -0,0 +1,120 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + + //###### Required core code ###### + + require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; + require_once 'cronUtil.php'; + + $plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); + $id_job = $argv[1];// Get the job id + $request_type = $argv[2];// Get the type of request + + $cronUtil = new CronUtil($request_type); + $job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); + $parameters = $job_infos['parameters']; + set_error_handler("errorHandler"); + + //###### End required core code ###### + + try + { + + //---- Start plugin code ----- + include_once 'dbUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //---- Start plugin code ----- + + //Get the params required by plugin from argv + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $query = $parameters['db_check_mysql_tables_query']; + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + + try { + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $query = 'SHOW TABLES'; + $tables = $dbUtil->dbQuery($dbh, $query); + + $msg_exec = ''; + $result = 1; + foreach ($tables as $table) { + $loggerPlugin->trace('DEBUG', 'About to check table ' . $table[0]); + $query = "check table " . $table[0]; + $checkResult = $dbUtil->dbQuery($dbh, $query); + if (($checkResult[0][2] == 'error') || ($checkResult[0][2] == 'warning')) { + $msg_exec .= 'Problem Found on With table ' . $table[0] . + ' status ' . $checkResult[0][2] . + ' Message: ' . $checkResult[0][3] . + " in Database: $sid Host: $ip\n"; + $loggerPlugin->trace('ERROR', 'Found Problem with table :' . $table[0] . + ' status is :' . $checkResult[0][2]); + $result = 0; + } + } + + + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + } catch (Exception $e) { + $result = 0; + $msg_exec = $e->getMessage(); + $loggerPlugin->trace('ERROR', $msg_exec); + } + + $attachments['txt'] = $msg_exec; + $attachments['html'] = $msg_exec; + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['db_check_mysql_tables_retention']; + + + //---- End plugin code ----- + + } catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + + } + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/database/oracle_freespa_report/CHANGELOG b/plugins/database/oracle_freespa_report/CHANGELOG new file mode 100644 index 0000000..5cc1231 --- /dev/null +++ b/plugins/database/oracle_freespa_report/CHANGELOG @@ -0,0 +1,11 @@ +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.0.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/database/oracle_freespa_report/LICENSE b/plugins/database/oracle_freespa_report/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/database/oracle_freespa_report/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/oracle_freespa_report/configure.php b/plugins/database/oracle_freespa_report/configure.php new file mode 100644 index 0000000..4e9f0ba --- /dev/null +++ b/plugins/database/oracle_freespa_report/configure.php @@ -0,0 +1,71 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['oracle_freespa_report'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['oracle_freespa_report'][0]['action'] = 'plugin'; +$plugin_actions['oracle_freespa_report'][0]['file'] = 'display_reports'; +$plugin_actions['oracle_freespa_report'][0]['image'] = 'archive.png'; + +$plugin_field['oracle_freespa_report'][0]['version'] ='1.0.2'; +$plugin_field['oracle_freespa_report'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['oracle_freespa_report'][0]['authors'][0] = 'Giuseppe De Santis '; +$plugin_field['oracle_freespa_report'][0]['description'] = PLUGIN_ORACLE_FREESPA_REPORT_DESCRIPTION; +$plugin_field['oracle_freespa_report'][0]['title'] = PLUGIN_ORACLE_FREESPA_REPORT_TITLE; + +$plugin_field['oracle_freespa_report'][1]['type'] = 'text'; +$plugin_field['oracle_freespa_report'][1]['name'] = 'db_oracle_freespa_report_identity'; +$plugin_field['oracle_freespa_report'][1]['value'] = ''; +$plugin_field['oracle_freespa_report'][1]['attributes'] = 'disabled readonly'; +$plugin_field['oracle_freespa_report'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['oracle_freespa_report'][1]['num_rules'] = '1'; +$plugin_field['oracle_freespa_report'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['oracle_freespa_report'][1]['rule_type'][0] = 'required'; +$plugin_field['oracle_freespa_report'][1]['rule_attribute'][0] = ''; + +$plugin_field['oracle_freespa_report'][2]['type'] = 'textarea'; +$plugin_field['oracle_freespa_report'][2]['name'] = 'db_oracle_freespa_report_tablespaces'; +$plugin_field['oracle_freespa_report'][2]['value'] = ''; +$plugin_field['oracle_freespa_report'][2]['attributes'] = 'disabled'; +$plugin_field['oracle_freespa_report'][2]['description'] = PLUGIN_ORACLE_FREESPA_REPORT_TABLESPACES_DESCRIPTION; + +$plugin_field['oracle_freespa_report'][3]['type'] = 'select'; +$plugin_field['oracle_freespa_report'][3]['name'] = 'db_oracle_freespa_report_attach_result'; +$plugin_field['oracle_freespa_report'][3]['value'] = array('html' => '.html', + 'txt' => '.txt', + 'csv' => '.csv'); +$plugin_field['oracle_freespa_report'][3]['attributes'] = ''; +$plugin_field['oracle_freespa_report'][3]['description'] = PLUGIN_ATTACH_RESULT; + +$plugin_field['oracle_freespa_report'][4]['type'] = 'text'; +$plugin_field['oracle_freespa_report'][4]['name'] = 'db_oracle_freespa_report_file_name'; +$plugin_field['oracle_freespa_report'][4]['value'] = ''; +$plugin_field['oracle_freespa_report'][4]['attributes'] = 'disabled'; +$plugin_field['oracle_freespa_report'][4]['description'] = PLUGIN_FILE_NAME; +$plugin_field['oracle_freespa_report'][4]['num_rules'] = '1'; +$plugin_field['oracle_freespa_report'][4]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['oracle_freespa_report'][4]['rule_type'][0] = 'required'; +$plugin_field['oracle_freespa_report'][4]['rule_attribute'][0] = ''; + +$plugin_field['oracle_freespa_report'][5]['type'] = 'text'; +$plugin_field['oracle_freespa_report'][5]['name'] = 'db_oracle_freespa_report_retention'; +$plugin_field['oracle_freespa_report'][5]['value'] = ''; +$plugin_field['oracle_freespa_report'][5]['attributes'] = 'disabled'; +$plugin_field['oracle_freespa_report'][5]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/database/oracle_freespa_report/core.php b/plugins/database/oracle_freespa_report/core.php new file mode 100644 index 0000000..3171f6f --- /dev/null +++ b/plugins/database/oracle_freespa_report/core.php @@ -0,0 +1,192 @@ + + * @author Giuseppe De Santis + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + include_once 'ioUtil.php'; + include_once 'dbUtil.php'; + + //Get the params required by plugin from argv + + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $tablespaces = trim($parameters['db_oracle_freespa_report_tablespaces']); + $attach_result_as = $parameters['db_oracle_freespa_report_attach_result']; + $filename = $parameters['db_oracle_freespa_report_file_name']; + + if ($filename == '') { + $filename = 'file'; + } + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + $id_system = $job_infos['id_system']; + + + //Base query + $query_base = "SELECT FILE_NAME, TABLESPACE_NAME, (BYTES/(1024*1024)) Mega, " . + "AUTOEXTENSIBLE, INCREMENT_BY, " . + "round((MAXBYTES/(1024*1024)),2) MaxMega, " . + "round((SELECT SUM(a.bytes) FROM dba_free_space a WHERE " . + "a.file_id = b.file_id)/(1024*1024),2) free " . + "FROM dba_data_files b "; + + $query_bottom = "SELECT FILE_NAME, TABLESPACE_NAME, (BYTES/(1024*1024)), " . + "AUTOEXTENSIBLE, INCREMENT_BY, " . + "round((MAXBYTES/(1024*1024)),2), " . + "round((SELECT SUM(a.bytes) " . + "FROM dba_free_space a WHERE " . + "a.file_id = b.file_id)/(1024*1024),2) free " . + "FROM dba_temp_files b order by 7 nulls first"; + + $query = ''; + if (isset($tablespaces) && $tablespaces != '') { + $tablespaces_array = explode(',', $tablespaces); + for ($k = 0; $k < sizeof($tablespaces_array); $k++) { + $query .= $query_base . $query_tablespace . + " where tablespace_name = '" . + trim($tablespaces_array[$k]) . "' UNION "; + } + } else { + $query .= $query_base . ' UNION '; + } + + $query .= $query_bottom; + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $rows = $dbUtil->dbQuery($dbh, $query, MDB2_FETCHMODE_ASSOC); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + if (count($rows)>0) { + + $reports_storing_path = ORTRO_REPORTS . $id_system . + DIRECTORY_SEPARATOR . $id_job . + DIRECTORY_SEPARATOR; + + switch ($attach_result_as) { + case 'html': + $th_class = 'class="background-color : #eee; ' . + 'border-bottom : 1px #bbb solid; ' . + 'border-right : 1px #bbb solid;' . + 'text-align : left;' . + 'font-family : verdana;' . + 'font-size : 8pt;' . + 'font-weight : bold;"'; + + $td_class = 'class="font-family : arial, helvetica, sans-serif; ' . + 'font-size : 10pt;"'; + + include_once 'Pear/HTML/Table.php'; + $table = new HTML_Table('cellpadding=4 cellspacing=0 border=1'); + $column_name = array_keys($rows[0]); + $table->addRow($column_name, $th_class, 'TH'); + foreach ($rows as $row) { + $table_row = array(); + foreach ($column_name as $name) { + array_push($table_row, $row[$name]); + } + $table->addRow($table_row, '', 'TD', false); + } + + $attachments['html'] = $table->toHTML(); + createHTMLFile($attachments['html'], $reports_storing_path, $filename); + break; + + case 'txt': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'txt', + "\t", + "\n"); + + $attachments['file'] = array($temp_file); + break; + + case 'csv': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'csv', + ';', + "\n"); + + $attachments['file'] = array($temp_file); + break; + } + + $result = 1; + $msg_exec = $result; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'FILESYSTEM'; + $retention_data['retention'] = $parameters['db_oracle_freespa_report_retention']; + $retention_data['path'] = $reports_storing_path; + $retention_data['filename'] = $filename; + + } + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/database/oracle_session_report/CHANGELOG b/plugins/database/oracle_session_report/CHANGELOG new file mode 100644 index 0000000..5cc1231 --- /dev/null +++ b/plugins/database/oracle_session_report/CHANGELOG @@ -0,0 +1,11 @@ +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.0.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/database/oracle_session_report/LICENSE b/plugins/database/oracle_session_report/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/database/oracle_session_report/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/database/oracle_session_report/configure.php b/plugins/database/oracle_session_report/configure.php new file mode 100644 index 0000000..e402a26 --- /dev/null +++ b/plugins/database/oracle_session_report/configure.php @@ -0,0 +1,65 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['oracle_session_report'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['oracle_session_report'][0]['action'] = 'plugin'; +$plugin_actions['oracle_session_report'][0]['file'] = 'display_reports'; +$plugin_actions['oracle_session_report'][0]['image'] = 'archive.png'; + +$plugin_field['oracle_session_report'][0]['version'] = '1.0.2'; +$plugin_field['oracle_session_report'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['oracle_session_report'][0]['authors'][0] = 'Giuseppe De Santis '; +$plugin_field['oracle_session_report'][0]['description'] = PLUGIN_SESSION_REPORT_DESCRIPTION; +$plugin_field['oracle_session_report'][0]['title'] = PLUGIN_SESSION_REPORT_TITLE; + +$plugin_field['oracle_session_report'][1]['type'] = 'text'; +$plugin_field['oracle_session_report'][1]['name'] = 'db_oracle_session_report_identity'; +$plugin_field['oracle_session_report'][1]['value'] = ''; +$plugin_field['oracle_session_report'][1]['attributes'] = 'disabled readonly'; +$plugin_field['oracle_session_report'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['oracle_session_report'][1]['num_rules'] = '1'; +$plugin_field['oracle_session_report'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['oracle_session_report'][1]['rule_type'][0] = 'required'; +$plugin_field['oracle_session_report'][1]['rule_attribute'][0] = ''; + +$plugin_field['oracle_session_report'][2]['type'] = 'select'; +$plugin_field['oracle_session_report'][2]['name'] = 'db_oracle_session_report_attach_result'; +$plugin_field['oracle_session_report'][2]['value'] = array('html' => '.html', + 'txt' => '.txt', + 'csv' => '.csv'); +$plugin_field['oracle_session_report'][2]['attributes'] = ''; +$plugin_field['oracle_session_report'][2]['description'] = PLUGIN_ATTACH_RESULT; + +$plugin_field['oracle_session_report'][3]['type'] = 'text'; +$plugin_field['oracle_session_report'][3]['name'] = 'db_oracle_session_report_file_name'; +$plugin_field['oracle_session_report'][3]['value'] = ''; +$plugin_field['oracle_session_report'][3]['attributes'] = 'disabled'; +$plugin_field['oracle_session_report'][3]['description'] = PLUGIN_FILE_NAME; +$plugin_field['oracle_session_report'][3]['num_rules'] = '1'; +$plugin_field['oracle_session_report'][3]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['oracle_session_report'][3]['rule_type'][0] = 'required'; +$plugin_field['oracle_session_report'][3]['rule_attribute'][0] = ''; + +$plugin_field['oracle_session_report'][4]['type'] = 'text'; +$plugin_field['oracle_session_report'][4]['name'] = 'db_oracle_session_report_retention'; +$plugin_field['oracle_session_report'][4]['value'] = ''; +$plugin_field['oracle_session_report'][4]['attributes'] = 'disabled'; +$plugin_field['oracle_session_report'][4]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/database/oracle_session_report/core.php b/plugins/database/oracle_session_report/core.php new file mode 100644 index 0000000..9ab8658 --- /dev/null +++ b/plugins/database/oracle_session_report/core.php @@ -0,0 +1,165 @@ + + * @author Giuseppe De Santis + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + include_once 'ioUtil.php'; + include_once 'dbUtil.php'; + + //Get the params required by plugin from argv + + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $tablespaces = trim($parameters['db_oracle_session_report_tablespaces']); + $attach_result_as = $parameters['db_oracle_session_report_attach_result']; + $filename = $parameters['db_oracle_session_report_file_name']; + + if ($filename == '') { + $filename = 'file'; + } + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + $id_system = $job_infos['id_system']; + + $query = 'select RESOURCE_NAME, CURRENT_UTILIZATION, '. + 'MAX_UTILIZATION, LIMIT_VALUE ' . + ' from v$resource_limit ' . + " where resource_name in ('processes','sessions')"; + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + $rows = $dbUtil->dbQuery($dbh, $query, MDB2_FETCHMODE_ASSOC); + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + + if (count($rows)>0) { + + $reports_storing_path = ORTRO_REPORTS . $id_system . DIRECTORY_SEPARATOR . + $id_job . DIRECTORY_SEPARATOR; + + switch ($attach_result_as) { + case 'html': + $th_class = 'class="background-color : #eee; ' . + 'border-bottom : 1px #bbb solid; ' . + 'border-right : 1px #bbb solid;' . + 'text-align : left;' . + 'font-family : verdana;' . + 'font-size : 8pt;' . + 'font-weight : bold;"'; + + $td_class = 'class="font-family : arial, helvetica, sans-serif; ' . + 'font-size : 10pt;"'; + + include_once 'Pear/HTML/Table.php'; + $table = new HTML_Table('cellpadding=4 cellspacing=0 border=1'); + $column_name = array_keys($rows[0]); + $table->addRow($column_name, $th_class, 'TH'); + foreach ($rows as $row) { + $table_row = array(); + foreach ($column_name as $name) { + array_push($table_row, $row[$name]); + } + $table->addRow($table_row, '', 'TD', false); + } + + $attachments['html'] = $table->toHTML(); + createHTMLFile($attachments['html'], $reports_storing_path, $filename); + break; + + case 'txt': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'txt', + "\t", + "\n"); + + $attachments['file'] = array($temp_file); + break; + + case 'csv': + $temp_file = createFileByQuery($rows, + $reports_storing_path, + $filename, + 'csv', + ';', + "\n"); + + $attachments['file'] = array($temp_file); + break; + } + + $result = 1; + $msg_exec = $result; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'FILESYSTEM'; + $retention_data['retention'] = $parameters['db_oracle_session_report_retention']; + $retention_data['path'] = $reports_storing_path; + $retention_data['filename'] = $filename; + + } + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/advanced_file_transfer/CHANGELOG b/plugins/file/advanced_file_transfer/CHANGELOG new file mode 100644 index 0000000..a4d483c --- /dev/null +++ b/plugins/file/advanced_file_transfer/CHANGELOG @@ -0,0 +1,3 @@ +1.0.0 (2009.10.13) +------------------ +Initial release. diff --git a/plugins/file/advanced_file_transfer/LICENSE b/plugins/file/advanced_file_transfer/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/advanced_file_transfer/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/advanced_file_transfer/configure.php b/plugins/file/advanced_file_transfer/configure.php new file mode 100644 index 0000000..bccdb46 --- /dev/null +++ b/plugins/file/advanced_file_transfer/configure.php @@ -0,0 +1,109 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['advanced_file_transfer'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['advanced_file_transfer'][0]['action'] = 'plugin'; +$plugin_actions['advanced_file_transfer'][0]['file'] = 'display_archive_results'; +$plugin_actions['advanced_file_transfer'][0]['image'] = 'archive.png'; + +$plugin_field['advanced_file_transfer'][0]['version'] = '1.0.0'; +$plugin_field['advanced_file_transfer'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['advanced_file_transfer'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['advanced_file_transfer'][0]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_DESCRIPTION; +$plugin_field['advanced_file_transfer'][0]['title'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_TITLE; + +$plugin_field['advanced_file_transfer'][1]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][1]['name'] = 'file_advanced_file_transfer_src_user'; +$plugin_field['advanced_file_transfer'][1]['value'] = ''; +$plugin_field['advanced_file_transfer'][1]['attributes'] = 'disabled size=30'; +$plugin_field['advanced_file_transfer'][1]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_SRC_USER_DESCRIPTION; +$plugin_field['advanced_file_transfer'][1]['num_rules'] = '1'; +$plugin_field['advanced_file_transfer'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['advanced_file_transfer'][1]['rule_type'][0] = 'required'; +$plugin_field['advanced_file_transfer'][1]['rule_attribute'][0] = ''; + +$plugin_field['advanced_file_transfer'][2]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][2]['name'] = 'file_advanced_file_transfer_src_filename'; +$plugin_field['advanced_file_transfer'][2]['value'] = ''; +$plugin_field['advanced_file_transfer'][2]['attributes'] = 'disabled size=50'; +$plugin_field['advanced_file_transfer'][2]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_SRC_FILE_DESCRIPTION; +$plugin_field['advanced_file_transfer'][2]['num_rules'] = '1'; +$plugin_field['advanced_file_transfer'][2]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['advanced_file_transfer'][2]['rule_type'][0] = 'required'; +$plugin_field['advanced_file_transfer'][2]['rule_attribute'][0] = ''; + +$plugin_field['advanced_file_transfer'][3]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][3]['name'] = 'file_advanced_file_transfer_src_rsync_path'; +$plugin_field['advanced_file_transfer'][3]['value'] = ''; +$plugin_field['advanced_file_transfer'][3]['attributes'] = 'disabled size=50'; +$plugin_field['advanced_file_transfer'][3]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_SRC_RSYNC_PATH; + +$plugin_field['advanced_file_transfer'][4]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][4]['name'] = 'file_advanced_file_transfer_dest_host'; +$plugin_field['advanced_file_transfer'][4]['value'] = ''; +$plugin_field['advanced_file_transfer'][4]['attributes'] = 'disabled size=30'; +$plugin_field['advanced_file_transfer'][4]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_DEST_HOST_DESCRIPTION; +$plugin_field['advanced_file_transfer'][4]['num_rules'] = '1'; +$plugin_field['advanced_file_transfer'][4]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['advanced_file_transfer'][4]['rule_type'][0] = 'required'; +$plugin_field['advanced_file_transfer'][4]['rule_attribute'][0] = ''; + +$plugin_field['advanced_file_transfer'][5]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][5]['name'] = 'file_advanced_file_transfer_dest_user'; +$plugin_field['advanced_file_transfer'][5]['value'] = ''; +$plugin_field['advanced_file_transfer'][5]['attributes'] = 'disabled size=30'; +$plugin_field['advanced_file_transfer'][5]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_DEST_USER_DESCRIPTION; +$plugin_field['advanced_file_transfer'][5]['num_rules'] = '1'; +$plugin_field['advanced_file_transfer'][5]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['advanced_file_transfer'][5]['rule_type'][0] = 'required'; +$plugin_field['advanced_file_transfer'][5]['rule_attribute'][0] = ''; + +$plugin_field['advanced_file_transfer'][6]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][6]['name'] = 'file_advanced_file_transfer_dest_dir'; +$plugin_field['advanced_file_transfer'][6]['value'] = ''; +$plugin_field['advanced_file_transfer'][6]['attributes'] = 'disabled size=50'; +$plugin_field['advanced_file_transfer'][6]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_DEST_DIR_DESCRIPTION; + +$plugin_field['advanced_file_transfer'][7]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][7]['name'] = 'file_advanced_file_transfer_dest_rsync_path'; +$plugin_field['advanced_file_transfer'][7]['value'] = ''; +$plugin_field['advanced_file_transfer'][7]['attributes'] = 'disabled size=50'; +$plugin_field['advanced_file_transfer'][7]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_DEST_RSYNC_PATH; + +$plugin_field['advanced_file_transfer'][8]['type'] = 'select'; +$plugin_field['advanced_file_transfer'][8]['name'] = 'file_advanced_file_transfer_checkpoint'; +$plugin_field['advanced_file_transfer'][8]['value'] = array('0' => NO, + '1' => YES); +$plugin_field['advanced_file_transfer'][8]['attributes'] = ''; +$plugin_field['advanced_file_transfer'][8]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_CHECKPOINT_DESCRIPTION; + +$plugin_field['advanced_file_transfer'][9]['type'] = 'select'; +$plugin_field['advanced_file_transfer'][9]['name'] = 'file_advanced_file_transfer_compress'; +$plugin_field['advanced_file_transfer'][9]['value'] = array('0' => NO, + '1' => YES); +$plugin_field['advanced_file_transfer'][9]['attributes'] = ''; +$plugin_field['advanced_file_transfer'][9]['description'] = PLUGIN_FILE_ADVANCED_FILE_TRANSFER_COMPRESS_DESCRIPTION; + +$plugin_field['advanced_file_transfer'][10]['type'] = 'text'; +$plugin_field['advanced_file_transfer'][10]['name'] = 'file_advanced_file_transfer_retention'; +$plugin_field['advanced_file_transfer'][10]['value'] = '7'; +$plugin_field['advanced_file_transfer'][10]['attributes'] = 'disabled'; +$plugin_field['advanced_file_transfer'][10]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/file/advanced_file_transfer/configure_metadata.php b/plugins/file/advanced_file_transfer/configure_metadata.php new file mode 100644 index 0000000..c56b7d3 --- /dev/null +++ b/plugins/file/advanced_file_transfer/configure_metadata.php @@ -0,0 +1,35 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['advanced_file_transfer']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['advanced_file_transfer']['mode']['description'] = PLUGIN_ADVANCED_FILE_TRANSFER_METADATA_MODE_DESCRIPTION; +$conf_metadata['advanced_file_transfer']['mode']['type'] = 'select'; +$conf_metadata['advanced_file_transfer']['mode']['name'] = 'advanced_file_transfer-mode'; +$conf_metadata['advanced_file_transfer']['mode']['value'] = array('nofilter' => PLUGIN_ADVANCED_FILE_TRANSFER_METADATA_MODE_NO_DESCRIPTION, + 'whitelist' => PLUGIN_ADVANCED_FILE_TRANSFER_METADATA_MODE_WHITELIST_DESCRIPTION, + 'blacklist' => PLUGIN_ADVANCED_FILE_TRANSFER_METADATA_MODE_BLACKLIST_DESCRIPTION); +$conf_metadata['advanced_file_transfer']['mode']['attributes'] =''; + +$conf_metadata['advanced_file_transfer']['rules']['description'] = PLUGIN_ADVANCED_FILE_TRANSFER_METADATA_ADDRESS_DESCRIPTION; +$conf_metadata['advanced_file_transfer']['rules']['type'] = 'textarea'; +$conf_metadata['advanced_file_transfer']['rules']['name'] = 'advanced_file_transfer-rules'; +$conf_metadata['advanced_file_transfer']['rules']['value'] = ";example\nlocalhost:/root"; +$conf_metadata['advanced_file_transfer']['rules']['attributes'] = 'rows=50 cols=80'; +?> \ No newline at end of file diff --git a/plugins/file/advanced_file_transfer/core.php b/plugins/file/advanced_file_transfer/core.php new file mode 100644 index 0000000..7b15270 --- /dev/null +++ b/plugins/file/advanced_file_transfer/core.php @@ -0,0 +1,175 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + * @patch lucke + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +set_include_path(realpath(dirname($argv[0])) . "/lib/Pear/:" . + ini_get("include_path")); +@require_once ORTRO_CONF_PLUGINS . 'file_advanced_file_transfer.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $log_prefix = '[job: ' . $id_job . '] '; + $loggerPlugin->trace('INFO', $log_prefix . 'Executing job'); + + $result = 0; + + //Get job info + $src_host = $job_infos['ip']; + $src_user = $parameters['file_advanced_file_transfer_src_user']; + $src_filename = $parameters['file_advanced_file_transfer_src_filename']; + $src_rsync_path = $parameters['file_advanced_file_transfer_src_rsync_path']; + + + $dest_host = $parameters['file_advanced_file_transfer_dest_host']; + $dest_user = $parameters['file_advanced_file_transfer_dest_user']; + $dest_dir = $parameters['file_advanced_file_transfer_dest_dir']; + $dest_rsync_path = $parameters['file_advanced_file_transfer_dest_rsync_path']; + + $enable_checkpoint = $parameters['file_advanced_file_transfer_checkpoint']; + $enable_recursive_copy = $parameters['file_advanced_file_transfer_recursive']; + $enable_compress = $parameters['file_advanced_file_transfer_compress']; + + //Get whitelist/blacklist filter mode + $filter_mode = $conf['advanced_file_transfer']['mode']; + + if ($filter_mode != 'nofilter') { + //Filter enabled + $loggerPlugin->trace('INFO', $log_prefix . 'Enabled filter: ' . $filter_mode); + //retrieve an array with specified rules + $rules = array_map('trim', explode("\n", $conf['advanced_file_transfer']['rules'])); + + //Get the ip:path to check + $address = $dest_host . ':' . $dest_dir; + + //Check for whitelist/blacklist + $test = in_array($address, $rules); + + $msg_deny = "The specified host:path ($address) is not allowed.\nPlease contact the System Administrator"; + + $loggerPlugin->trace('DEBUG', $log_prefix . 'IP:Path to check: ' . $address); + $loggerPlugin->trace('DEBUG', $log_prefix . 'List to filter: ' . print_r($rules, true)); + switch ($filter_mode) { + case 'whitelist': + if ($test !== true) { + throw new Exception($msg_deny); + } + case 'blacklist': + if ($test === true) { + throw new Exception($msg_deny); + } + default: + throw new Exception('Filter mode "' . $filter_mode . '" not supported. Please contact the System Administrator'); + break; + } + } + + $advanced_file_transfer_command = 'rsync'; + + if($src_rsync_path != '') { + $advanced_file_transfer_command = escapeshellarg($src_rsync_path . DIRECTORY_SEPARATOR . 'rsync'); + } + + $advanced_file_transfer_command .= ' -av --progress '; + + if ($enable_compress == 1) { + $advanced_file_transfer_command .= ' -z '; + } + + if ($enable_checkpoint == 1) { + $advanced_file_transfer_command .= ' --partial --append '; + } + + if ($dest_rsync_path != '') { + $advanced_file_transfer_command .= ' --rsync-path=' . escapeshellarg($dest_rsync_path . DIRECTORY_SEPARATOR . 'rsync') . ' '; + } + + $advanced_file_transfer_command .= escapeshellarg($src_filename) . ' '; + + if ($dest_user != '') { + $advanced_file_transfer_command .= escapeshellarg($dest_user) . '@'; + } + + $advanced_file_transfer_command .= escapeshellarg($dest_host) . ':' . escapeshellarg($dest_dir); + + $loggerPlugin->trace('DEBUG', $log_prefix . 'Secure transfer command: ' . $advanced_file_transfer_command); + + require_once 'sshUtil.php'; + + $ssh = new SSHUtil(); + $start_timer = time(); + $sshCommandResult = $ssh->sshConn($src_user, $src_host, '22', $advanced_file_transfer_command, false); + $end_timer = time(); + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + if ($exit_code == '0') { + $result = '1'; + $attachments['txt'] = $end_timer - $start_timer; + } else { + $loggerPlugin->trace('ERROR', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + $result = '0'; + } + + $msg_exec = $attachments['txt']; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['file_advanced_file_transfer_retention']; + + $loggerPlugin->trace('INFO', $log_prefix . 'Done.'); + + //---- End plugin code ----- + +} catch (Exception $e) { + $msg_exec = $e->getMessage(); + $result = 0; +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/check_tail_status/CHANGELOG b/plugins/file/check_tail_status/CHANGELOG new file mode 100644 index 0000000..1b7d49b --- /dev/null +++ b/plugins/file/check_tail_status/CHANGELOG @@ -0,0 +1,15 @@ +1.2.3 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/file/check_tail_status/LICENSE b/plugins/file/check_tail_status/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/check_tail_status/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/check_tail_status/configure.php b/plugins/file/check_tail_status/configure.php new file mode 100644 index 0000000..4b3723e --- /dev/null +++ b/plugins/file/check_tail_status/configure.php @@ -0,0 +1,62 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['check_tail_status'][0]['version'] = '1.2.3'; +$plugin_field['check_tail_status'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['check_tail_status'][0]['authors'][0] = 'Marcello Sessa '; +$plugin_field['check_tail_status'][0]['description'] = PLUGIN_FILE_CHECK_TAIL_STATUS_DESCRIPTION; +$plugin_field['check_tail_status'][0]['title'] = PLUGIN_FILE_CHECK_TAIL_STATUS_TITLE; + +$plugin_field['check_tail_status'][1]['type'] = 'text'; +$plugin_field['check_tail_status'][1]['name'] = 'check_tail_status_user'; +$plugin_field['check_tail_status'][1]['value'] = ''; +$plugin_field['check_tail_status'][1]['attributes'] = 'disabled'; +$plugin_field['check_tail_status'][1]['description'] = PLUGIN_USER; +$plugin_field['check_tail_status'][1]['num_rules'] = '1'; +$plugin_field['check_tail_status'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['check_tail_status'][1]['rule_type'][0] = 'required'; +$plugin_field['check_tail_status'][1]['rule_attribute'][0] = ''; + +$plugin_field['check_tail_status'][2]['type'] = 'text'; +$plugin_field['check_tail_status'][2]['name'] = 'check_tail_status_port'; +$plugin_field['check_tail_status'][2]['value'] = ''; +$plugin_field['check_tail_status'][2]['attributes'] = 'disabled'; +$plugin_field['check_tail_status'][2]['description'] = PLUGIN_PORT; + +$plugin_field['check_tail_status'][3]['type'] = 'text'; +$plugin_field['check_tail_status'][3]['name'] = 'check_tail_status_dir_path'; +$plugin_field['check_tail_status'][3]['value'] = ''; +$plugin_field['check_tail_status'][3]['attributes'] = 'disabled size=70'; +$plugin_field['check_tail_status'][3]['description'] = PLUGIN_FILE_CHECK_TAIL_STATUS_DIR_PATH_DESCRIPTION; +$plugin_field['check_tail_status'][3]['num_rules'] = '1'; +$plugin_field['check_tail_status'][3]['rule_msg'][0] = PLUGIN_FILE_CHECK_TAIL_STATUS_RULE_3_0; +$plugin_field['check_tail_status'][3]['rule_type'][0] = 'required'; +$plugin_field['check_tail_status'][3]['rule_attribute'][0] = ''; + +$plugin_field['check_tail_status'][4]['type'] = 'text'; +$plugin_field['check_tail_status'][4]['name'] = 'check_tail_status_sleep'; +$plugin_field['check_tail_status'][4]['value'] = ''; +$plugin_field['check_tail_status'][4]['attributes'] = 'disabled'; +$plugin_field['check_tail_status'][4]['description'] = PLUGIN_FILE_CHECK_TAIL_STATUS_SLEEP_DESCRIPTION; +$plugin_field['check_tail_status'][4]['num_rules'] = '1'; +$plugin_field['check_tail_status'][4]['rule_msg'][0] = PLUGIN_FILE_CHECK_TAIL_STATUS_RULE_4_0; +$plugin_field['check_tail_status'][4]['rule_type'][0] = 'required'; +$plugin_field['check_tail_status'][4]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/file/check_tail_status/core.php b/plugins/file/check_tail_status/core.php new file mode 100644 index 0000000..b0fae3c --- /dev/null +++ b/plugins/file/check_tail_status/core.php @@ -0,0 +1,105 @@ + + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['check_tail_status_user']; + $port = $parameters['check_tail_status_port']; + + // The absolute path of folder to apply check_tail_status policy + $dir_path = '"' . $parameters['check_tail_status_dir_path'] . '"'; + // The time to sleep between the read of the rows + $sleep = '"' . $parameters['check_tail_status_sleep'] . '"'; + + $script_parameters = array($dir_path, $sleep); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/tail.sh'; + + $local_parameters = implode(' ', $script_parameters); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/check_tail_status/tail.sh b/plugins/file/check_tail_status/tail.sh new file mode 100644 index 0000000..c9fc286 --- /dev/null +++ b/plugins/file/check_tail_status/tail.sh @@ -0,0 +1,31 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License v2 +# a copy of which has been included with this distribution in the LICENSE file. +# +# This script allows you to monitor the tail of a specified file +# +# File Authors: +# Marcello Sessa +# +################################################################################## + +# The first time that comes read the file +FIRST_TIME=`tail -1 $1` +sleep $2 +# The second time that comes read the file +SECOND_TIME=`tail -1 $1` + +echo $FIRST_TIME +echo +echo +echo $SECOND_TIME + +if [ "x$FIRST_TIME" = "x$SECOND_TIME" ] + then + exit 1 +else + exit 0 +fi diff --git a/plugins/file/create/CHANGELOG b/plugins/file/create/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/file/create/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/file/create/LICENSE b/plugins/file/create/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/create/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/create/configure.php b/plugins/file/create/configure.php new file mode 100644 index 0000000..068b464 --- /dev/null +++ b/plugins/file/create/configure.php @@ -0,0 +1,46 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['create'][0]['version'] = '1.2.2'; +$plugin_field['create'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['create'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['create'][0]['description'] = PLUGIN_FILE_CREATE_DESCRIPTION; +$plugin_field['create'][0]['title'] = PLUGIN_FILE_CREATE_TITLE; + +$plugin_field['create'][1]['type'] = 'textarea'; +$plugin_field['create'][1]['name'] = 'file_create_body'; +$plugin_field['create'][1]['value'] = ''; +$plugin_field['create'][1]['attributes'] = 'disabled rows=30 cols=30'; +$plugin_field['create'][1]['description'] = PLUGIN_FILE_CREATE_FILE_BODY_DESCRIPTION; +$plugin_field['create'][1]['num_rules'] = '1'; +$plugin_field['create'][1]['rule_msg'][0] = PLUGIN_FILE_CREATE_FILE_RULE_1_0; +$plugin_field['create'][1]['rule_type'][0] = 'required'; +$plugin_field['create'][1]['rule_attribute'][0] = ''; + +$plugin_field['create'][2]['type'] = 'text'; +$plugin_field['create'][2]['name'] = 'file_create_name'; +$plugin_field['create'][2]['value'] = ''; +$plugin_field['create'][2]['attributes'] = 'disabled'; +$plugin_field['create'][2]['description'] = PLUGIN_FILE_NAME; +$plugin_field['create'][2]['num_rules'] = '1'; +$plugin_field['create'][2]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['create'][2]['rule_type'][0] = 'required'; +$plugin_field['create'][2]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/file/create/core.php b/plugins/file/create/core.php new file mode 100644 index 0000000..153fe26 --- /dev/null +++ b/plugins/file/create/core.php @@ -0,0 +1,72 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + include_once 'ioUtil.php'; + + //Get the params required by plugin from argv + + $filedata = $parameters['file_create_body']; + $filename = $parameters['file_create_name']; + + createFile($filedata, ORTRO_FILES, $filename); + + $result = 1; + $msg_exec = $result; + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### + +?> diff --git a/plugins/file/ftp_upload/CHANGELOG b/plugins/file/ftp_upload/CHANGELOG new file mode 100644 index 0000000..1d3524a --- /dev/null +++ b/plugins/file/ftp_upload/CHANGELOG @@ -0,0 +1,15 @@ +1.0.3 (2008.06.24) +------------------ +#80 Add get function, put is the default if not set + +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.10.22) +------------------ +Changed. Use ORTRO_INCOMING as default dir to save file + +1.0.0 (2007.10.15) +------------------ +Initial release diff --git a/plugins/file/ftp_upload/LICENSE b/plugins/file/ftp_upload/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/ftp_upload/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/ftp_upload/configure.php b/plugins/file/ftp_upload/configure.php new file mode 100644 index 0000000..dae8517 --- /dev/null +++ b/plugins/file/ftp_upload/configure.php @@ -0,0 +1,75 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + * @patch lucke + */ + +$plugin_field['ftp_upload'][0]['version'] = '1.0.3'; +$plugin_field['ftp_upload'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['ftp_upload'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['ftp_upload'][0]['description'] = PLUGIN_FILE_FTP_UPLOAD_DESCRIPTION; +$plugin_field['ftp_upload'][0]['title'] = PLUGIN_FILE_FTP_UPLOAD_TITLE; + +$plugin_field['ftp_upload'][1]['type'] = 'text'; +$plugin_field['ftp_upload'][1]['name'] = 'file_ftp_upload_identity'; +$plugin_field['ftp_upload'][1]['value'] = ''; +$plugin_field['ftp_upload'][1]['attributes'] = 'disabled readonly size=30'; +$plugin_field['ftp_upload'][1]['description'] = PLUGIN_FILE_FTP_UPLOAD_IDENTITY_DESCRIPTION; + +$plugin_field['ftp_upload'][2]['type'] = 'text'; +$plugin_field['ftp_upload'][2]['name'] = 'file_ftp_upload_local_dir'; +$plugin_field['ftp_upload'][2]['value'] = ''; +$plugin_field['ftp_upload'][2]['attributes'] = 'disabled size=50'; +$plugin_field['ftp_upload'][2]['description'] = PLUGIN_FILE_FTP_UPLOAD_LOCAL_DIR_DESCRIPTION; + +$plugin_field['ftp_upload'][3]['type'] = 'text'; +$plugin_field['ftp_upload'][3]['name'] = 'file_ftp_upload_filename'; +$plugin_field['ftp_upload'][3]['value'] = ''; +$plugin_field['ftp_upload'][3]['attributes'] = 'disabled size=50'; +$plugin_field['ftp_upload'][3]['description'] = PLUGIN_FILE_NAME; +$plugin_field['ftp_upload'][3]['num_rules'] = '1'; +$plugin_field['ftp_upload'][3]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['ftp_upload'][3]['rule_type'][0] = 'required'; +$plugin_field['ftp_upload'][3]['rule_attribute'][0] = ''; + +$plugin_field['ftp_upload'][4]['type'] = 'text'; +$plugin_field['ftp_upload'][4]['name'] = 'file_ftp_upload_remote_dir'; +$plugin_field['ftp_upload'][4]['value'] = ''; +$plugin_field['ftp_upload'][4]['attributes'] = 'disabled size=50'; +$plugin_field['ftp_upload'][4]['description'] = PLUGIN_FILE_FTP_UPLOAD_REMOTE_DIR_DESCRIPTION; + +$plugin_field['ftp_upload'][5]['type'] = 'select'; +$plugin_field['ftp_upload'][5]['name'] = 'file_ftp_upload_transfer_mode'; +$plugin_field['ftp_upload'][5]['value'] = array('ascii' => PLUGIN_FILE_FTP_UPLOAD_TRANSFER_MODE_VALUE_0, + 'binary' => PLUGIN_FILE_FTP_UPLOAD_TRANSFER_MODE_VALUE_1); +$plugin_field['ftp_upload'][5]['attributes'] = ''; +$plugin_field['ftp_upload'][5]['description'] = PLUGIN_FILE_FTP_UPLOAD_TRANSFER_MODE_DESCRIPTION; + +$plugin_field['ftp_upload'][6]['type'] = 'text'; +$plugin_field['ftp_upload'][6]['name'] = 'file_ftp_upload_port'; +$plugin_field['ftp_upload'][6]['value'] = ''; +$plugin_field['ftp_upload'][6]['attributes'] = 'disabled size=6'; +$plugin_field['ftp_upload'][6]['description'] = PLUGIN_FILE_FTP_UPLOAD_PORT_DESCRIPTION; + +$plugin_field['ftp_upload'][7]['type'] = 'select'; +$plugin_field['ftp_upload'][7]['name'] = 'file_ftp_upload_transfer_way'; +$plugin_field['ftp_upload'][7]['value'] = array('put' => PLUGIN_FILE_FTP_UPLOAD_TRANSFER_WAY_VALUE_0, + 'get' => PLUGIN_FILE_FTP_UPLOAD_TRANSFER_WAY_VALUE_1); +$plugin_field['ftp_upload'][7]['attributes'] = ''; +$plugin_field['ftp_upload'][7]['description'] = PLUGIN_FILE_FTP_UPLOAD_TRANSFER_WAY_DESCRIPTION; +?> diff --git a/plugins/file/ftp_upload/core.php b/plugins/file/ftp_upload/core.php new file mode 100644 index 0000000..e4e6f33 --- /dev/null +++ b/plugins/file/ftp_upload/core.php @@ -0,0 +1,155 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + * @patch lucke + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $log_prefix = '[job: ' . $id_job . '] '; + $loggerPlugin->trace('INFO', $log_prefix . 'Executing job'); + + $result = 0; + + //Get the params required by plugin + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + + $ftp_server = $job_infos['ip']; + + $local_dir = $parameters['file_ftp_upload_local_dir']; + if (isset($local_dir) && trim($local_dir)=='') { + $id_system = $job_infos['id_system']; + $local_dir = ORTRO_INCOMING . $id_system; + } + + $filename = $parameters['file_ftp_upload_filename']; + $remote_dir = $parameters['file_ftp_upload_remote_dir']; + $tranfer_mode = $parameters['file_ftp_upload_tranfer_mode']; + $port = $parameters['file_ftp_upload_port']; + $way = $parameters['file_ftp_upload_transfer_way']; + + if ($port == '') { + $port = 21; + } + + //check for existeing file locally + $full_path = $local_dir . DS . $filename; + $loggerPlugin->trace('ERROR', "Param : $full_path, $remote_dir, $tranfer_mode, $port, $ftp_server, $user, $pwd"); + + if (($way != 'get') && (!file_exists($full_path))) { + $msg_exec = 'File ' . $filename . ' not found!!!'; + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); + throw new Exception($msg_exec); + } + + // set up basic connection + $conn_id = ftp_connect($ftp_server, $port); + + // login with username and password + $login_result = ftp_login($conn_id, $user, $pwd); + + // check connection + if ((!$conn_id) || (!$login_result)) { + $msg_exec = "FTP connection has failed! Attempted to connect to " . + " $ftp_server for user " . $user; + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); + throw new Exception($msg_exec); + } else { + $loggerPlugin->trace('DEBUG', + "Connected to $ftp_server, for user " .$user); + } + + // try to change the directory to somedir if defined + if (isset($remote_dir) && $remote_dir != '') { + if (ftp_chdir($conn_id, $remote_dir)) { + $loggerPlugin->trace('DEBUG', + $log_prefix . "cd " . ftp_pwd($conn_id)); + } else { + $msg_exec = "Couldn't change directory: " . $remote_dir; + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); + throw new Exception($msg_exec); + } + } + + // upload the file + if ($tranfer_mode == 'ascii') { + $tranfer_mode = FTP_ASCII; + } else { + $tranfer_mode = FTP_BINARY; + } + + if ($way == 'get') { + $upload = ftp_get($conn_id, $full_path, $filename, $tranfer_mode); + } else { + $upload = ftp_put($conn_id, $filename, $full_path, $tranfer_mode); + } + + // check upload status + if (!$upload) { + $msg_exec = 'FTP upload has failed!'; + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); + throw new Exception($msg_exec); + } else { + $loggerPlugin->trace('DEBUG', + "Uploaded message to $ftp_server as $filename"); + } + // close the FTP stream + ftp_close($conn_id); + + + $result = 1; + $msg_exec = ''; + $loggerPlugin->trace('INFO', $log_prefix . 'Done.'); + + //---- End plugin code ----- + +} catch (Exception $e) { + $msg_exec = $e->getMessage(); + $result = 0; +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, + $id_job, + $result, + $msg_exec, + $attachments, + $output); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/read_file/CHANGELOG b/plugins/file/read_file/CHANGELOG new file mode 100644 index 0000000..c6771b3 --- /dev/null +++ b/plugins/file/read_file/CHANGELOG @@ -0,0 +1,11 @@ +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.10.22) +------------------ +Changed. Use ORTRO_INCOMING as default dir to read file + +1.0.0 (2007.10.15) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/file/read_file/LICENSE b/plugins/file/read_file/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/read_file/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/read_file/configure.php b/plugins/file/read_file/configure.php new file mode 100644 index 0000000..1c38090 --- /dev/null +++ b/plugins/file/read_file/configure.php @@ -0,0 +1,36 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['read_file'][0]['version'] = '1.0.2'; +$plugin_field['read_file'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['read_file'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['read_file'][0]['description'] = PLUGIN_FILE_READ_FILE_DESCRIPTION; +$plugin_field['read_file'][0]['title'] = PLUGIN_FILE_READ_FILE_TITLE; + +$plugin_field['read_file'][1]['type'] = 'text'; +$plugin_field['read_file'][1]['name'] = 'file_read_file_name'; +$plugin_field['read_file'][1]['value'] = ''; +$plugin_field['read_file'][1]['attributes'] = 'disabled'; +$plugin_field['read_file'][1]['description'] = PLUGIN_FILE_NAME; +$plugin_field['read_file'][1]['num_rules'] = '1'; +$plugin_field['read_file'][1]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['read_file'][1]['rule_type'][0] = 'required'; +$plugin_field['read_file'][1]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/file/read_file/core.php b/plugins/file/read_file/core.php new file mode 100644 index 0000000..5132257 --- /dev/null +++ b/plugins/file/read_file/core.php @@ -0,0 +1,85 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, + ORTRO_LOG_PLUGINS . $plugin_name); + $log_prefix = '[job: ' . $id_job . '] '; + $loggerPlugin->trace('INFO', $log_prefix . 'Executing job'); + + $result = 0; + + //Get the params required by plugin from argv + + $filename = $parameters['file_read_file_name']; + + $id_system = $job_infos['id_system']; + + $output = file(ORTRO_INCOMING . $id_system . DS . $filename); + + if ($output === false) { + $result = 0; + $msg_exec = 'Failed!!!'; + $loggerPlugin->trace('INFO', $log_prefix . 'Failed!!!'); + } else { + $result = 1; + $msg_exec = ''; + $loggerPlugin->trace('INFO', $log_prefix . 'Done.'); + } + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, + $id_job, + $result, + $msg_exec, + $attachments, + $output); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/retention/CHANGELOG b/plugins/file/retention/CHANGELOG new file mode 100644 index 0000000..b398234 --- /dev/null +++ b/plugins/file/retention/CHANGELOG @@ -0,0 +1,20 @@ +1.2.4 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.2.3 (2007.11.19) +------------------ +Use init.inc.php + +1.2.2 (2007.08.21) +------------------ +Fixed typo in italian translation. +Added default values for compression and remove retention. + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/file/retention/LICENSE b/plugins/file/retention/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/retention/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/retention/configure.php b/plugins/file/retention/configure.php new file mode 100644 index 0000000..08b3518 --- /dev/null +++ b/plugins/file/retention/configure.php @@ -0,0 +1,111 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['retention'][0]['version'] = '1.2.4'; +$plugin_field['retention'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['retention'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['retention'][0]['description'] = PLUGIN_FILE_RETENTION_DESCRIPTION; +$plugin_field['retention'][0]['title'] = PLUGIN_FILE_RETENTION_TITLE; + +$plugin_field['retention'][1]['type'] = 'text'; +$plugin_field['retention'][1]['name'] = 'file_retention_user'; +$plugin_field['retention'][1]['value'] = ''; +$plugin_field['retention'][1]['attributes'] = 'disabled'; +$plugin_field['retention'][1]['description'] = PLUGIN_USER; +$plugin_field['retention'][1]['num_rules'] = '1'; +$plugin_field['retention'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['retention'][1]['rule_type'][0] = 'required'; +$plugin_field['retention'][1]['rule_attribute'][0] = ''; + +$plugin_field['retention'][2]['type'] = 'text'; +$plugin_field['retention'][2]['name'] = 'file_retention_port'; +$plugin_field['retention'][2]['value'] = ''; +$plugin_field['retention'][2]['attributes'] = 'disabled'; +$plugin_field['retention'][2]['description'] = PLUGIN_PORT; + +$plugin_field['retention'][3]['type'] = 'text'; +$plugin_field['retention'][3]['name'] = 'file_retention_dir_path'; +$plugin_field['retention'][3]['value'] = ''; +$plugin_field['retention'][3]['attributes'] = 'disabled size=70'; +$plugin_field['retention'][3]['description'] = PLUGIN_FILE_RETENTION_PATH_DESCRIPTION; +$plugin_field['retention'][3]['num_rules'] = '1'; +$plugin_field['retention'][3]['rule_msg'][0] = PLUGIN_FILE_RETENTION_RULE_3_0; +$plugin_field['retention'][3]['rule_type'][0] = 'required'; +$plugin_field['retention'][3]['rule_attribute'][0] = ''; + +$plugin_field['retention'][4]['type'] = 'text'; +$plugin_field['retention'][4]['name'] = 'file_retention_search_for'; +$plugin_field['retention'][4]['value'] = ''; +$plugin_field['retention'][4]['attributes'] = 'disabled'; +$plugin_field['retention'][4]['description'] = PLUGIN_FILE_RETENTION_SEARCH_DESCRIPTION; +$plugin_field['retention'][4]['num_rules'] = '1'; +$plugin_field['retention'][4]['rule_msg'][0] = PLUGIN_FILE_RETENTION_RULE_4_0; +$plugin_field['retention'][4]['rule_type'][0] = 'required'; +$plugin_field['retention'][4]['rule_attribute'][0] = ''; + +$plugin_field['retention'][5]['type'] = 'select'; +$plugin_field['retention'][5]['name'] = 'file_retention_recursive'; +$plugin_field['retention'][5]['value'] = array('0' => PLUGIN_FILE_RETENTION_RECURSIVE_VALUE_FALSE, + '1' => PLUGIN_FILE_RETENTION_RECURSIVE_VALUE_TRUE); +$plugin_field['retention'][5]['attributes'] = ''; +$plugin_field['retention'][5]['description'] = PLUGIN_FILE_RETENTION_RECURSIVE_DESCRIPTION; + +$plugin_field['retention'][6]['type'] = 'select'; +$plugin_field['retention'][6]['name'] = 'file_retention_compress_program'; +$plugin_field['retention'][6]['value'] = array('0' => PLUGIN_FILE_RETENTION_COMPRESS_PROGRAM_VALUE_0, + 'gzip' => PLUGIN_FILE_RETENTION_COMPRESS_PROGRAM_VALUE_1, + 'compress' => PLUGIN_FILE_RETENTION_COMPRESS_PROGRAM_VALUE_2); +$plugin_field['retention'][6]['attributes'] = ''; +$plugin_field['retention'][6]['description'] = PLUGIN_FILE_RETENTION_PROGRAM_DESCRIPTION; + +$plugin_field['retention'][7]['type'] = 'text'; +$plugin_field['retention'][7]['name'] = 'file_retention_compress_program_path'; +$plugin_field['retention'][7]['value'] = ''; +$plugin_field['retention'][7]['attributes'] = 'disabled size=70'; +$plugin_field['retention'][7]['description'] = PLUGIN_FILE_RETENTION_COMPRESS_PATH_DESCRIPTION; + +$plugin_field['retention'][8]['type'] = 'text'; +$plugin_field['retention'][8]['name'] = 'file_retention_compress_retention'; +$plugin_field['retention'][8]['value'] = '0'; +$plugin_field['retention'][8]['attributes'] = 'disabled'; +$plugin_field['retention'][8]['description'] = PLUGIN_FILE_RETENTION_RETENTION_COMPRESS_PERIOD_DESCRIPTION; +$plugin_field['retention'][8]['num_rules'] = '1'; +$plugin_field['retention'][8]['rule_msg'][0] = PLUGIN_FILE_RETENTION_RULE_8_0; +$plugin_field['retention'][8]['rule_type'][0] = 'required'; +$plugin_field['retention'][8]['rule_attribute'][0] = ''; + +$plugin_field['retention'][9]['type'] = 'select'; +$plugin_field['retention'][9]['name'] = 'file_retention_remove_flag'; +$plugin_field['retention'][9]['value'] = array('0' => PLUGIN_FILE_RETENTION_REMOVE_FLAG_VALUE_0, + '1' => PLUGIN_FILE_RETENTION_REMOVE_FLAG_VALUE_1, + '2' => PLUGIN_FILE_RETENTION_REMOVE_FLAG_VALUE_2); +$plugin_field['retention'][9]['attributes'] = ''; +$plugin_field['retention'][9]['description'] = PLUGIN_FILE_RETENTION_REMOVE_FILES_DESCRIPTION; + +$plugin_field['retention'][10]['type'] = 'text'; +$plugin_field['retention'][10]['name'] = 'file_retention_remove_retention'; +$plugin_field['retention'][10]['value'] = '0'; +$plugin_field['retention'][10]['attributes'] = 'disabled'; +$plugin_field['retention'][10]['description'] = PLUGIN_FILE_RETENTION_RETENTION_PERIOD_DESCRIPTION; +$plugin_field['retention'][10]['num_rules'] = '1'; +$plugin_field['retention'][10]['rule_msg'][0] = PLUGIN_FILE_RETENTION_RULE_10_0; +$plugin_field['retention'][10]['rule_type'][0] = 'required'; +$plugin_field['retention'][10]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/file/retention/core.php b/plugins/file/retention/core.php new file mode 100644 index 0000000..5eeeaaa --- /dev/null +++ b/plugins/file/retention/core.php @@ -0,0 +1,137 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, + ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', + 'Executing job ' . $plugin_name . ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['file_retention_user']; + $port = $parameters['file_retention_port']; + + // The absolute path of folder to apply retention policy + $dir_path = '"' . $parameters['file_retention_dir_path'] . '"'; + // The search pattern + $search_for = '"' . + str_replace('*', + '\*', + $parameters['file_retention_search_for']) . + '"'; + // Is it a recursive search? (0 = false, 1 = true) + $recursive = $parameters['file_retention_recursive']; + + //# Compress section + // Program used for compress (0, gzip, compress) + $compress_program = $parameters['file_retention_compress_program']; + + if ($parameters['file_retention_compress_program_path'] != '') { + $compress_program_path = + $parameters['file_retention_compress_program_path'] . + DIRECTORY_SEPARATOR; + } else { + $compress_program_path = '"none"'; + } + + // Retention period + $compress_retention = $parameters['file_retention_compress_retention']-1; + //# Delete section + // Remove flag (1 = remove, 0 skip) + $delete_flag = $parameters['file_retention_remove_flag']; + // Retention period + $delete_retention = $parameters['file_retention_remove_retention']-1; + + $script_parameters = array($dir_path, + $search_for, + $recursive, + $compress_program, + $compress_program_path, + $compress_retention, + $delete_flag, + $delete_retention); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/script.sh'; + + $local_parameters = implode(' ', $script_parameters); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/retention/script.sh b/plugins/file/retention/script.sh new file mode 100644 index 0000000..160d914 --- /dev/null +++ b/plugins/file/retention/script.sh @@ -0,0 +1,135 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License +# a copy of which has been included with this distribution in the LICENSE file. +# +# File Retention script +# This script allows you to compress and/or remove files older then +# a specified retention period +# +# +# File Authors: +# Luca Corbo +# +################################################################################## + +# The absolute path of folder to apply retention policy +DIR_PATH=$1 +# The search pattern +SEARCH_FOR=$2 +# Is it a recursive search? (0 = false, 1 = true) +RECURSIVE=$3 + +## Compress section +# Program used for compress (none, gzip, compress) +COMPRESS_PROGRAM=$4 + +if [ "x$5" != "xnone" ] + then + COMPRESS_PROGRAM_PATH=$5$4 + else + COMPRESS_PROGRAM_PATH=$4 +fi + +# Retention period +COMPRESS_RETENTION=$6 + +## Delete section +# Remove flag (1 = remove, 0 skip) +DELETE_FLAG=$7 +# Retention period +DELETE_RETENTION=$8 + + +##################################################### +#### Main program +##################################################### + +## Compress files + +if [ "x$COMPRESS_PROGRAM" != "x0" ] +then + + echo "Check for files to compress...." + CHECK_COMPRESS_PATH=`which $COMPRESS_PROGRAM_PATH` + if [ "x$CHECK_COMPRESS_PATH" = "x" ] + then + echo "$COMPRESS_PROGRAM_PATH : command not found. Please check your ENV" + exit 1 + fi + + if [ "x$RECURSIVE" = "x1" ] + then + FILES_TO_COMPRESS=`find $DIR_PATH -name "$SEARCH_FOR" -type f -mtime +$COMPRESS_RETENTION` + else + FILES_TO_COMPRESS=`find $DIR_PATH/. ! -name . -prune -name "$SEARCH_FOR" -type f -mtime +$COMPRESS_RETENTION` + fi + if [ "x$FILES_TO_COMPRESS" = "x" ] + then + echo "No files found." + else + for i in $FILES_TO_COMPRESS + do + `$COMPRESS_PROGRAM_PATH $i` + EXIT_CODE=$? + echo -n "Attempt to compress $i" + if [ "x$EXIT_CODE" = "x0" ] + then + echo " -> Done." + else + echo " -> Failed!" + ERROR=1 + fi + done + fi + echo "Compress files done." +fi + +if [ "x$DELETE_FLAG" != "x0" ] +then + echo "Check for files to delete...." + if [ "x$DELETE_FLAG" = "x1" ] + then + SEARCH_COMPRESSED="" + else + if [ "x$COMPRESS_PROGRAM" = "xgzip" ] + then + SEARCH_COMPRESSED=".gz" + else + SEARCH_COMPRESSED=".Z" + fi + fi + if [ "x$RECURSIVE" = "x1" ] + then + FILES_TO_DELETE=`find $DIR_PATH -name "$SEARCH_FOR"$SEARCH_COMPRESSED -type f -mtime +$DELETE_RETENTION` + else + FILES_TO_DELETE=`find $DIR_PATH/. ! -name . -prune -name "$SEARCH_FOR"$SEARCH_COMPRESSED -type f -mtime +$DELETE_RETENTION` + fi + if [ "x$FILES_TO_DELETE" = "x" ] + then + echo "No files found." + else + for i in $FILES_TO_DELETE + do + `rm -f $i` + EXIT_CODE=$? + echo -n "Attempt to remove $i" + if [ "x$EXIT_CODE" = "x0" ] + then + echo " -> Done." + else + echo " -> Failed!" + ERROR=1 + fi + done + fi + echo "Delete files done." +fi + +# Check for error +if [ "x$ERROR" = "x1" ] +then + exit 1 +fi diff --git a/plugins/file/scp/CHANGELOG b/plugins/file/scp/CHANGELOG new file mode 100644 index 0000000..a78c8e4 --- /dev/null +++ b/plugins/file/scp/CHANGELOG @@ -0,0 +1,16 @@ +1.0.3 (2009.07.30) +------------------ +Feature #121: enable compression and recursive copy + +1.0.2 (2009.07.20) +------------------ +Feature #117: whitelist/blacklist filter +Feature #118: display transfer time + +1.0.1 (2009.07.17) +------------------ +Enabled archive result function. + +1.0.0 (2009.06.04) +------------------ +Initial release. \ No newline at end of file diff --git a/plugins/file/scp/LICENSE b/plugins/file/scp/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/scp/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/scp/configure.php b/plugins/file/scp/configure.php new file mode 100644 index 0000000..58d1cc8 --- /dev/null +++ b/plugins/file/scp/configure.php @@ -0,0 +1,98 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['scp'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['scp'][0]['action'] = 'plugin'; +$plugin_actions['scp'][0]['file'] = 'display_archive_results'; +$plugin_actions['scp'][0]['image'] = 'archive.png'; + +$plugin_field['scp'][0]['version'] = '1.0.3'; +$plugin_field['scp'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['scp'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['scp'][0]['description'] = PLUGIN_FILE_SCP_DESCRIPTION; +$plugin_field['scp'][0]['title'] = PLUGIN_FILE_SCP_TITLE; + +$plugin_field['scp'][1]['type'] = 'text'; +$plugin_field['scp'][1]['name'] = 'file_scp_src_user'; +$plugin_field['scp'][1]['value'] = ''; +$plugin_field['scp'][1]['attributes'] = 'disabled size=30'; +$plugin_field['scp'][1]['description'] = PLUGIN_FILE_SCP_SRC_USER_DESCRIPTION; +$plugin_field['scp'][1]['num_rules'] = '1'; +$plugin_field['scp'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['scp'][1]['rule_type'][0] = 'required'; +$plugin_field['scp'][1]['rule_attribute'][0] = ''; + + +$plugin_field['scp'][2]['type'] = 'text'; +$plugin_field['scp'][2]['name'] = 'file_scp_src_filename'; +$plugin_field['scp'][2]['value'] = ''; +$plugin_field['scp'][2]['attributes'] = 'disabled size=50'; +$plugin_field['scp'][2]['description'] = PLUGIN_FILE_SCP_SRC_FILE_DESCRIPTION; +$plugin_field['scp'][2]['num_rules'] = '1'; +$plugin_field['scp'][2]['rule_msg'][0] = PLUGIN_FILE_NAME_RULE; +$plugin_field['scp'][2]['rule_type'][0] = 'required'; +$plugin_field['scp'][2]['rule_attribute'][0] = ''; + +$plugin_field['scp'][3]['type'] = 'text'; +$plugin_field['scp'][3]['name'] = 'file_scp_dest_host'; +$plugin_field['scp'][3]['value'] = ''; +$plugin_field['scp'][3]['attributes'] = 'disabled size=30'; +$plugin_field['scp'][3]['description'] = PLUGIN_FILE_SCP_DEST_HOST_DESCRIPTION; +$plugin_field['scp'][3]['num_rules'] = '1'; +$plugin_field['scp'][3]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['scp'][3]['rule_type'][0] = 'required'; +$plugin_field['scp'][3]['rule_attribute'][0] = ''; + +$plugin_field['scp'][4]['type'] = 'text'; +$plugin_field['scp'][4]['name'] = 'file_scp_dest_user'; +$plugin_field['scp'][4]['value'] = ''; +$plugin_field['scp'][4]['attributes'] = 'disabled size=30'; +$plugin_field['scp'][4]['description'] = PLUGIN_FILE_SCP_DEST_USER_DESCRIPTION; +$plugin_field['scp'][4]['num_rules'] = '1'; +$plugin_field['scp'][4]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['scp'][4]['rule_type'][0] = 'required'; +$plugin_field['scp'][4]['rule_attribute'][0] = ''; + +$plugin_field['scp'][5]['type'] = 'text'; +$plugin_field['scp'][5]['name'] = 'file_scp_dest_dir'; +$plugin_field['scp'][5]['value'] = ''; +$plugin_field['scp'][5]['attributes'] = 'disabled size=50'; +$plugin_field['scp'][5]['description'] = PLUGIN_FILE_SCP_DEST_DIR_DESCRIPTION; + +$plugin_field['scp'][6]['type'] = 'select'; +$plugin_field['scp'][6]['name'] = 'file_scp_recursive'; +$plugin_field['scp'][6]['value'] = array('0' => NO, + '1' => YES); +$plugin_field['scp'][6]['attributes'] = ''; +$plugin_field['scp'][6]['description'] = PLUGIN_FILE_SCP_RECURSIVE_DESCRIPTION; + +$plugin_field['scp'][7]['type'] = 'select'; +$plugin_field['scp'][7]['name'] = 'file_scp_compress'; +$plugin_field['scp'][7]['value'] = array('0' => NO, + '1' => YES); +$plugin_field['scp'][7]['attributes'] = ''; +$plugin_field['scp'][7]['description'] = PLUGIN_FILE_SCP_COMPRESS_DESCRIPTION; + +$plugin_field['scp'][8]['type'] = 'text'; +$plugin_field['scp'][8]['name'] = 'file_scp_retention'; +$plugin_field['scp'][8]['value'] = '7'; +$plugin_field['scp'][8]['attributes'] = 'disabled'; +$plugin_field['scp'][8]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/file/scp/configure_metadata.php b/plugins/file/scp/configure_metadata.php new file mode 100644 index 0000000..efc7146 --- /dev/null +++ b/plugins/file/scp/configure_metadata.php @@ -0,0 +1,35 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['scp']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['scp']['mode']['description'] = PLUGIN_SCP_METADATA_MODE_DESCRIPTION; +$conf_metadata['scp']['mode']['type'] = 'select'; +$conf_metadata['scp']['mode']['name'] = 'scp-mode'; +$conf_metadata['scp']['mode']['value'] = array('nofilter' => PLUGIN_SCP_METADATA_MODE_NO_DESCRIPTION, + 'whitelist' => PLUGIN_SCP_METADATA_MODE_WHITELIST_DESCRIPTION, + 'blacklist' => PLUGIN_SCP_METADATA_MODE_BLACKLIST_DESCRIPTION); +$conf_metadata['scp']['mode']['attributes'] =''; + +$conf_metadata['scp']['rules']['description'] = PLUGIN_SCP_METADATA_ADDRESS_DESCRIPTION; +$conf_metadata['scp']['rules']['type'] = 'textarea'; +$conf_metadata['scp']['rules']['name'] = 'scp-rules'; +$conf_metadata['scp']['rules']['value'] = ";example\n localhost:/root"; +$conf_metadata['scp']['rules']['attributes'] = 'rows=50 cols=80'; +?> \ No newline at end of file diff --git a/plugins/file/scp/core.php b/plugins/file/scp/core.php new file mode 100644 index 0000000..7d30a45 --- /dev/null +++ b/plugins/file/scp/core.php @@ -0,0 +1,170 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + * @patch lucke + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +set_include_path(realpath(dirname($argv[0])) . "/lib/Pear/:" . + ini_get("include_path")); +@require_once ORTRO_CONF_PLUGINS . 'file_scp.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $log_prefix = '[job: ' . $id_job . '] '; + $loggerPlugin->trace('INFO', $log_prefix . 'Executing job'); + + $result = 0; + + //Get job info + $src_host = $job_infos['ip']; + $src_user = $parameters['file_scp_src_user']; + $src_filename = $parameters['file_scp_src_filename']; + + $dest_host = $parameters['file_scp_dest_host']; + $dest_user = $parameters['file_scp_dest_user']; + $dest_dir = $parameters['file_scp_dest_dir']; + + $enable_recursive_copy = $parameters['file_scp_recursive']; + $enable_compress = $parameters['file_scp_compress']; + + //Get whitelist/blacklist filter mode + $filter_mode = $conf['scp']['mode']; + + if ($filter_mode != 'nofilter') { + //Filter enabled + $loggerPlugin->trace('INFO', $log_prefix . 'Enabled filter: ' . $filter_mode); + //retrieve an array with specified rules + $rules = array_map('trim', explode("\n", $conf['scp']['rules'])); + + //Get the ip:path to check + $address = $dest_host . ':' . $dest_dir; + + //Check for whitelist/blacklist + $test = in_array($address, $rules); + + $msg_deny = "The specified host:path ($address) is not allowed.\nPlease contact the System Administrator"; + + $loggerPlugin->trace('DEBUG', $log_prefix . 'IP:Path to check: ' . $address); + $loggerPlugin->trace('DEBUG', $log_prefix . 'List to filter: ' . print_r($rules, true)); + switch ($filter_mode) { + case 'whitelist': + if ($test !== true) { + throw new Exception($msg_deny); + } + case 'blacklist': + if ($test === true) { + throw new Exception($msg_deny); + } + default: + throw new Exception('Filter mode "' . $filter_mode . '" not supported. Please contact the System Administrator'); + break; + } + } + + require_once 'Net/OpenSSH.php'; + require_once 'sshUtil.php'; + + $options = array('openssh_binary' => 'scp', + 'identity_file' => null, + 'option' => null, + 'port' => 22, + 'limit' => null, + 'recursive' => null, + 'src_config' => array( + array( + 'path'=>$src_filename) + ), + 'dest_config' => array('user'=>$dest_user, + 'hostname'=>$dest_host, + 'path'=>$dest_dir + ), + ); + + if ($enable_recursive_copy == 1) { + $options['recursive'] = 'y'; + } + + if ($enable_compress == 1) { + $options['option'][0] = 'Compression=yes'; + } + + $ssh_client = Net_OpenSSH::factory('Scp', $options); + + $scp_command = $ssh_client->createCommandLine(); + + $ssh = new SSHUtil(); + $start_timer = time(); + $sshCommandResult = $ssh->sshConn($src_user, $src_host, '22', $scp_command, false); + $end_timer = time(); + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + if ($exit_code == '0') { + $result = '1'; + $attachments['txt'] = $end_timer - $start_timer; + } else { + $loggerPlugin->trace('ERROR', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + $result = '0'; + } + + $msg_exec = $attachments['txt']; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['file_scp_retention']; + + $loggerPlugin->trace('INFO', $log_prefix . 'Done.'); + + //---- End plugin code ----- + +} catch (Exception $e) { + $msg_exec = $e->getMessage(); + $result = 0; +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/scp/lib/Pear/File.php b/plugins/file/scp/lib/Pear/File.php new file mode 100644 index 0000000..d3c3111 --- /dev/null +++ b/plugins/file/scp/lib/Pear/File.php @@ -0,0 +1,543 @@ + + * @author Tal Peer + * @author Michael Wallner + * @copyright 2002-2005 The Authors + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: File.php,v 1.38 2007/03/24 16:38:56 dufuz Exp $ + * @link http://pear.php.net/package/File + */ + +/** + * Requires PEAR + */ +require_once 'PEAR.php'; + +/** + * The default number of bytes for reading + */ +if (!defined('FILE_DEFAULT_READSIZE')) { + define('FILE_DEFAULT_READSIZE', 1024, true); +} + +/** + * The maximum number of bytes for reading lines + */ +if (!defined('FILE_MAX_LINE_READSIZE')) { + define('FILE_MAX_LINE_READSIZE', 40960, true); +} + +/** + * Whether file locks should block + */ +if (!defined('FILE_LOCKS_BLOCK')) { + define('FILE_LOCKS_BLOCK', true, true); +} + +/** + * Mode to use for reading from files + */ +define('FILE_MODE_READ', 'rb', true); + +/** + * Mode to use for truncating files, then writing + */ +define('FILE_MODE_WRITE', 'wb', true); + +/** + * Mode to use for appending to files + */ +define('FILE_MODE_APPEND', 'ab', true); + +/** + * Use this when a shared (read) lock is required + */ +define('FILE_LOCK_SHARED', LOCK_SH | (FILE_LOCKS_BLOCK ? 0 : LOCK_NB), true); + +/** + * Use this when an exclusive (write) lock is required + */ +define('FILE_LOCK_EXCLUSIVE', LOCK_EX | (FILE_LOCKS_BLOCK ? 0 : LOCK_NB), true); + +/** + * Class for handling files + * + * A class with common functions for writing, + * reading and handling files and directories + * + * @author Richard Heyes + * @author Tal Peer + * @author Michael Wallner + * @access public + * @package File + * + * @static + */ +class File extends PEAR +{ + /** + * Destructor + * + * Unlocks any locked file pointers and closes all filepointers + * + * @access private + */ + function _File() + { + File::closeAll(); + } + + /** + * Handles file pointers. If a file pointer needs to be opened, + * it will be. If it already exists (based on filename and mode) + * then the existing one will be returned. + * + * @access private + * @param string $filename Filename to be used + * @param string $mode Mode to open the file in + * @param mixed $lock Type of lock to use + * @return mixed PEAR_Error on error or file pointer resource on success + */ + function _getFilePointer($filename, $mode, $lock = false) + { + $filePointers = &PEAR::getStaticProperty('File', 'filePointers'); + + // Win32 is case-insensitive + if (OS_WINDOWS) { + $filename = strtolower($filename); + } + + // check if file pointer already exists + if (!isset($filePointers[$filename][$mode]) || + !is_resource($filePointers[$filename][$mode])) { + + // check if we can open the file in the desired mode + switch ($mode) + { + case FILE_MODE_READ: + if (!preg_match('/^.+(? $modes) { + foreach (array_keys($modes) as $mode) { + if (is_resource($filePointers[$fname][$mode])) { + @fclose($filePointers[$fname][$mode]); + } + unset($filePointers[$fname][$mode]); + } + } + } + } + + /** + * This closes an open file pointer + * + * @access public + * @param string $filename The filename that was opened + * @param string $mode Mode the file was opened in + * @return mixed PEAR Error on error, true otherwise + */ + function close($filename, $mode) + { + $filePointers = &PEAR::getStaticProperty('File', 'filePointers'); + + if (OS_WINDOWS) { + $filename = strToLower($filename); + } + + if (!isset($filePointers[$filename][$mode])) { + return true; + } + + $fp = $filePointers[$filename][$mode]; + unset($filePointers[$filename][$mode]); + + if (is_resource($fp)) { + // unlock file + @flock($fp, LOCK_UN); + // close file + if (!@fclose($fp)) { + return PEAR::raiseError("Cannot close file: $filename"); + } + } + + return true; + } + + /** + * This unlocks a locked file pointer. + * + * @access public + * @param string $filename The filename that was opened + * @param string $mode Mode the file was opened in + * @return mixed PEAR Error on error, true otherwise + */ + function unlock($filename, $mode) + { + $fp = File::_getFilePointer($filename, $mode); + if (PEAR::isError($fp)) { + return $fp; + } + + if (!@flock($fp, LOCK_UN)) { + return PEAR::raiseError("Cacnnot unlock file: $filename"); + } + + return true; + } + + /** + * @deprecated + */ + function stripTrailingSeparators($path, $separator = DIRECTORY_SEPARATOR) + { + if ($path === $separator) { + return $path; + } + return rtrim($path, $separator); + } + + /** + * @deprecated + */ + function stripLeadingSeparators($path, $separator = DIRECTORY_SEPARATOR) + { + if ($path === $separator) { + return $path; + } + return ltrim($path, $separator); + } + + /** + * @deprecated Use File_Util::buildPath() instead. + */ + function buildPath($parts, $separator = DIRECTORY_SEPARATOR) + { + require_once 'File/Util.php'; + return File_Util::buildPath($parts, $separator); + } + + /** + * @deprecated Use File_Util::skipRoot() instead. + */ + function skipRoot($path) + { + require_once 'File/Util.php'; + return File_Util::skipRoot($path); + } + + /** + * @deprecated Use File_Util::tmpDir() instead. + */ + function getTempDir() + { + require_once 'File/Util.php'; + return File_Util::tmpDir(); + } + + /** + * @deprecated Use File_Util::tmpFile() instead. + */ + function getTempFile($dirname = null) + { + require_once 'File/Util.php'; + return File_Util::tmpFile($dirname); + } + + /** + * @deprecated Use File_Util::isAbsolute() instead. + */ + function isAbsolute($path) + { + require_once 'File/Util.php'; + return File_Util::isAbsolute($path); + } + + /** + * @deprecated Use File_Util::relativePath() instead. + */ + function relativePath($path, $root, $separator = DIRECTORY_SEPARATOR) + { + require_once 'File/Util.php'; + return File_Util::relativePath($path, $root, $separator); + } + + /** + * @deprecated Use File_Util::realpath() instead. + */ + function realpath($path, $separator = DIRECTORY_SEPARATOR) + { + require_once 'File/Util.php'; + return File_Util::realpath($path, $separator); + } +} + +PEAR::registerShutdownFunc(array('File', '_File')); + +?> diff --git a/plugins/file/scp/lib/Pear/File/CSV.php b/plugins/file/scp/lib/Pear/File/CSV.php new file mode 100644 index 0000000..a4c5141 --- /dev/null +++ b/plugins/file/scp/lib/Pear/File/CSV.php @@ -0,0 +1,628 @@ + + * @author Helgi Þormar + * @copyright 2004-2005 The Authors + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: CSV.php,v 1.41 2007/05/20 12:25:14 dufuz Exp $ + * @link http://pear.php.net/package/File + */ + +require_once 'PEAR.php'; +require_once 'File.php'; + +/** +* File class for handling CSV files (Comma Separated Values), a common format +* for exchanging data. +* +* TODO: +* - Usage example and Doc +* - Use getPointer() in discoverFormat +* - Add a line counter for being able to output better error reports +* - Store the last error in GLOBALS and add File_CSV::getLastError() +* +* Wish: +* - Other methods like readAll(), writeAll(), numFields(), numRows() +* - Try to detect if a CSV has header or not in discoverFormat() (not possible with CSV) +* +* Known Bugs: +* (they has been analyzed but for the moment the impact in the speed for +* properly handle this uncommon cases is too high and won't be supported) +* - A field which is composed only by a single quoted separator (ie -> ;";";) +* is not handled properly +* - When there is exactly one field minus than the expected number and there +* is a field with a separator inside, the parser will throw the "wrong count" error +* +* Info about CSV and links to other sources +* http://www.shaftek.org/publications/drafts/mime-csv/draft-shafranovich-mime-csv-00.html#appendix +* +* @author Tomas V.V.Cox +* @author Helgi Þormar +* @package File +*/ +class File_CSV +{ + /** + * This raiseError method works in a different way. It will always return + * false (an error occurred) but it will call PEAR::raiseError() before + * it. If no default PEAR global handler is set, will trigger an error. + * + * @param string $error The error message + * @return bool always false + */ + function raiseError($error) + { + // If a default PEAR Error handler is not set trigger the error + // XXX Add a PEAR::isSetHandler() method? + if ($GLOBALS['_PEAR_default_error_mode'] == PEAR_ERROR_RETURN) { + PEAR::raiseError($error, null, PEAR_ERROR_TRIGGER, E_USER_WARNING); + } else { + PEAR::raiseError($error); + } + return false; + } + + /** + * Checks the configuration given by the user + * + * @access private + * @param string &$error The error will be written here if any + * @param array &$conf The configuration assoc array + * @return string error Returns a error message + */ + function _conf(&$error, &$conf) + { + // check conf + if (!is_array($conf)) { + return $error = 'Invalid configuration'; + } + + if (!isset($conf['fields']) || !(int)$conf['fields']) { + return $error = 'The number of fields must be numeric (the "fields" key)'; + } + + if (isset($conf['sep'])) { + if (strlen($conf['sep']) != 1) { + return $error = 'Separator can only be one char'; + } + } elseif ($conf['fields'] > 1) { + return $error = 'Missing separator (the "sep" key)'; + } + + if (isset($conf['quote'])) { + if (strlen($conf['quote']) != 1) { + return $error = 'The quote char must be one char (the "quote" key)'; + } + } else { + $conf['quote'] = null; + } + + if (!isset($conf['crlf'])) { + $conf['crlf'] = "\n"; + } + + if (!isset($conf['eol2unix'])) { + $conf['eol2unix'] = true; + } + } + + /** + * Return or create the file descriptor associated with a file + * + * @param string $file The name of the file + * @param array &$conf The configuration + * @param string $mode The open node (ex: FILE_MODE_READ or FILE_MODE_WRITE) + * @param boolean $reset if passed as true and resource for the file exists + * than the file pointer will be moved to the beginning + * + * @return mixed A file resource or false + */ + function getPointer($file, &$conf, $mode = FILE_MODE_READ, $reset = false) + { + static $resources = array(); + static $config; + if (isset($resources[$file][$mode])) { + $conf = $config; + if ($reset) { + fseek($resources[$file][$mode], 0); + } + return $resources[$file][$mode]; + } + File_CSV::_conf($error, $conf); + if ($error) { + return File_CSV::raiseError($error); + } + $config = $conf; + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $fp = File::_getFilePointer($file, $mode); + PEAR::popErrorHandling(); + if (PEAR::isError($fp)) { + return File_CSV::raiseError($fp); + } + $resources[$file][$mode] = $fp; + return $fp; + } + + /** + * Unquote data + * + * @param string $field The data to unquote + * @param string $quote The quote char + * @return string the unquoted data + */ + function unquote($field, $quote) + { + // Trim first the string. + $field = trim($field); + $quote = trim($quote); + + // Incase null fields (form: ;;) + if (!strlen($field)) { + return $field; + } + + // excel compat + if ($field[0] == '=' && $field[1] == '"') { + $field = str_replace('="', '"', $field); + } + + $field_len = strlen($field); + if ($quote && $field[0] == $quote && $field[$field_len - 1] == $quote) { + // Get rid of escaping quotes + $new = $prev = $c = ''; + for ($i = 0; $i < $field_len; ++$i) { + $prev = $c; + $c = $field[$i]; + // Deal with escaping quotes + if ($c == $quote && $prev == $quote) { + $c = ''; + } + + $new .= $c; + } + $field = substr($new, 1, -1); + } + + return $field; + } + + /** + * Reads a row of data as an array from a CSV file. It's able to + * read memo fields with multiline data. + * + * @param string $file The filename where to write the data + * @param array &$conf The configuration of the dest CSV + * + * @return mixed Array with the data read or false on error/no more data + */ + function readQuoted($file, &$conf) + { + if (!$fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ)) { + return false; + } + + $buff = $old = $prev = $c = ''; + $ret = array(); + $i = 1; + $in_quote = false; + $quote = $conf['quote']; + $f = $conf['fields']; + $sep = $conf['sep']; + while (false !== $ch = fgetc($fp)) { + $old = $prev; + $prev = $c; + $c = $ch; + + // Common case + if ($c != $quote && $c != $sep && $c != "\n" && $c != "\r") { + $buff .= $c; + continue; + } + + // Start quote. + if ( + $in_quote === false && + $quote && $c == $quote && + ( + $prev == $sep || $prev == "\n" || $prev === null || + $prev == "\r" || $prev == '' || $prev == ' ' + || $prev == '=' //excel compat + ) + ) { + $in_quote = true; + // excel compat, removing the = part but only if we are in a quote + if ($prev == '=') { + $buff{strlen($buff) - 1} = ''; + } + } + + if ($in_quote) { + + // When does the quote end, make sure it's not double quoted + if ($c == $sep && $prev == $quote && $old != $quote) { + $in_quote = false; + } elseif ($c == $sep && $buff == $quote.$quote) { + // In case we are dealing with double quote but empty value + $in_quote = false; + } elseif ($c == "\n" || $c == "\r") { + $sub = ($prev == "\r") ? 2 : 1; + $buff_len = strlen($buff); + if ( + $buff_len >= $sub && + $buff[$buff_len - $sub] == $quote + ) { + $in_quote = false; + } + } + } + + if (!$in_quote && ($c == $sep || $c == "\n" || $c == "\r") && $prev != '') { + // More fields than expected + if ($c == $sep && (count($ret) + 1) == $f) { + // Seek the pointer into linebreak character. + while (true) { + $c = fgetc($fp); + if ($c == "\n" || $c == "\r" || $c == '') { + break; + } + } + + // Insert last field value. + $ret[] = File_CSV::unquote($buff, $quote); + return $ret; + } + + // Less fields than expected + if (($c == "\n" || $c == "\r") && $i != $f) { + // Insert last field value. + $ret[] = File_CSV::unquote($buff, $quote); + if (count($ret) == 1 && empty($ret[0])) { + return array(); + } + + // Pair the array elements to fields count. - inserting empty values + $ret_count = count($ret); + $sum = ($f - 1) - ($ret_count - 1); + $data = array_merge($ret, array_fill($ret_count, $sum, '')); + return $data; + } + + if ($prev == "\r") { + $buff = substr($buff, 0, -1); + } + + // Convert EOL character to Unix EOL (LF). + if ($conf['eol2unix']) { + $buff = preg_replace('/(\r\n|\r)$/', "\n", $buff); + } + + $ret[] = File_CSV::unquote($buff, $quote); + if (count($ret) == $f) { + return $ret; + } + $buff = ''; + ++$i; + continue; + } + $buff .= $c; + } + + /* If it's the end of the file and we still have something in buffer + * then we process it since files can have no CL/FR at the end + */ + $feof = feof($fp); + if ($feof && !in_array($buff, array("\r", "\n", "\r\n")) && strlen($buff) > 0) { + $ret[] = File_CSV::unquote($buff, $quote); + if (count($ret) == $f) { + return $ret; + } + } + + return !$feof ? $ret : false; + } + + /** + * Reads a "row" from a CSV file and return it as an array + * + * @param string $file The CSV file + * @param array &$conf The configuration of the dest CSV + * + * @return mixed Array or false + */ + function read($file, &$conf) + { + static $headers = array(); + if (!$fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ)) { + return false; + } + + // The size is limited to 4K + if (!$line = fgets($fp, 4096)) { + return false; + } + + $fields = $conf['fields'] == 1 ? array($line) : explode($conf['sep'], $line); + + $nl = array("\n", "\r", "\r\n"); + if (in_array($fields[count($fields) - 1], $nl)) { + array_pop($fields); + } + + $field_count = count($fields); + $last =& $fields[$field_count - 1]; + $len = strlen($last); + if ( + $field_count != $conf['fields'] || + $conf['quote'] && + ( + $len !== 0 && $last[$len - 1] == "\n" + && + ( + ($last[0] == $conf['quote'] + && $last[strlen(rtrim($last)) - 1] != $conf['quote']) + || + // excel support + ($last[0] == '=' && $last[1] == $conf['quote']) + || + // if the row has spaces before the quote + preg_match('|^\s+'.preg_quote($conf['quote']) .'|Ums', $last, $match) + ) + ) + // XXX perhaps there is a separator inside a quoted field + //preg_match("|{$conf['quote']}.*{$conf['sep']}.*{$conf['quote']}|U", $line) + ) { + fseek($fp, -1 * strlen($line), SEEK_CUR); + return File_CSV::readQuoted($file, $conf); + } else { + foreach ($fields as $k => $v) { + $fields[$k] = File_CSV::unquote($v, $conf['quote']); + } + } + + if (isset($conf['header']) && empty($headers)) { + // read the first row and assign to $headers + $headers = $fields; + return $headers; + } + + if ($field_count != $conf['fields']) { + File_CSV::raiseError("Read wrong fields number count: '". $field_count . + "' expected ".$conf['fields']); + return true; + } + + if (!empty($headers)) { + $tmp = array(); + foreach ($fields as $k => $v) { + $tmp[$headers[$k]] = $v; + } + $fields = $tmp; + } + + return $fields; + } + + /** + * Internal use only, will be removed in the future + * + * @param string $str The string to debug + * @access private + */ + function _dbgBuff($str) + { + if (strpos($str, "\r") !== false) { + $str = str_replace("\r", "_r_", $str); + } + if (strpos($str, "\n") !== false) { + $str = str_replace("\n", "_n_", $str); + } + if (strpos($str, "\t") !== false) { + $str = str_replace("\t", "_t_", $str); + } + if ($str === null) { + $str = '_NULL_'; + } + if ($str === '') { + $str = 'Empty string'; + } + echo "buff: ($str)\n"; + } + + /** + * Writes a struc (array) in a file as CSV + * + * @param string $file The filename where to write the data + * @param array $fields Ordered array with the data + * @param array &$conf The configuration of the dest CSV + * + * @return bool True on success false otherwise + */ + function write($file, $fields, &$conf) + { + if (!$fp = File_CSV::getPointer($file, $conf, FILE_MODE_WRITE)) { + return false; + } + + $field_count = count($fields); + if ($field_count != $conf['fields']) { + File_CSV::raiseError("Wrong fields number count: '". $field_count . + "' expected ".$conf['fields']); + return true; + } + + $write = ''; + for ($i = 0; $i < $field_count; ++$i) { + // only quote if the field contains a sep + if (!is_numeric($fields[$i]) && $conf['quote'] + && isset($conf['sep']) && strpos($fields[$i], $conf['sep']) + ) { + $write .= $conf['quote'] . $fields[$i] . $conf['quote']; + } else { + $write .= $fields[$i]; + } + + $write .= ($i < ($field_count - 1)) ? $conf['sep']: $conf['crlf']; + } + + if (!fwrite($fp, $write, strlen($write))) { + return File_CSV::raiseError('Can not write to file'); + } + + return true; + } + + /** + * Discover the format of a CSV file (the number of fields, the separator + * and if it quote string fields) + * + * @param string the CSV file name + * @param array extra separators that should be checked for. + * @return mixed Assoc array or false + */ + function discoverFormat($file, $extraSeps = array()) + { + if (!$fp = @fopen($file, 'rb')) { + return File_CSV::raiseError("Could not open file: $file"); + } + + // Set auto detect line ending for Mac EOL support + $oldini = ini_get('auto_detect_line_endings'); + if ($oldini != '1') { + ini_set('auto_detect_line_endings', '1'); + } + + // Take the first 30 lines and store the number of ocurrences + // for each separator in each line + $lines = ''; + for ($i = 0; $i < 30 && $line = fgets($fp, 4096); $i++) { + $lines .= $line; + } + fclose($fp); + + if ($oldini != '1') { + ini_set('auto_detect_line_endings', $oldini); + } + + $seps = array("\t", ';', ':', ','); + $seps = array_merge($seps, $extraSeps); + $matches = array(); + $quotes = '"\''; + + $lines = str_replace('""', '', $lines); + while ($lines != ($newLines = preg_replace('|((["\'])[^"]*(\2))|', '\2_\2', $lines))){ + $lines = $newLines; + } + + $eol = strpos($lines, "\r") ? "\r" : "\n"; + $lines = explode($eol, $lines); + foreach ($lines as $line) { + $orgLine = $line; + foreach ($seps as $sep) { + $line = preg_replace("|^[^$quotes$sep]*$sep*([$quotes][^$quotes]*[$quotes])|sm", '_', $orgLine); + // Find all seps that are within qoutes + ///FIXME ... counts legitimit lines as bad ones + + // In case there's a whitespace infront the field + $regex = '|\s*?'; + // Match the first quote (optional), also optionally match = since it's excel stuff + $regex.= "(?:\=?[$quotes])"; + $regex.= '(.*'; + // Don't match a sep if we are inside a quote + // also don't accept the sep if it has a quote on the either side + ///FIXME has to be possible if we are inside a quote! (tests fail because of this) + $regex.= "(?:[^$quotes])$sep(?:[^$quotes])"; + $regex.= '.*)'; + // Close quote (if it's present) and the sep (optional, could be end of line) + $regex.= "(?:[$quotes](?:$sep?))|Ums"; + preg_match_all($regex, $line, $match); + // Finding all seps, within quotes or not + $sep_count = substr_count($line, $sep); + // Real count + $matches[$sep][] = $sep_count - count($match[0]); + } + } + + $final = array(); + // Group the results by amount of equal ocurrences + foreach ($matches as $sep => $res) { + $times = array(); + $times[0] = 0; + foreach ($res as $k => $num) { + if ($num > 0) { + $times[$num] = (isset($times[$num])) ? $times[$num] + 1 : 1; + } + } + arsort($times); + + // Use max fields count. + $fields[$sep] = max(array_flip($times)); + $amount[$sep] = $times[key($times)]; + } + + arsort($amount); + $sep = key($amount); + + $conf['fields'] = $fields[$sep] + 1; + $conf['sep'] = $sep; + + // Test if there are fields with quotes around in the first 30 lines + $quote = null; + + $string = implode('', $lines); + foreach (array('"', '\'') as $q) { + if (preg_match_all("|$sep(?:\s*?)(\=?[$q]).*([$q])$sep|Us", $string, $match)) { + if ($match[1][0] == $match[2][0]) { + $quote = $match[1][0]; + break; + } + } + + if ( + preg_match_all("|^(\=?[$q]).*([$q])$sep{0,1}|Ums", $string, $match) + || preg_match_all("|(\=?[$q]).*([$q])$sep\s$|Ums", $string, $match) + ) { + if ($match[1][0] == $match[2][0]) { + $quote = $match[1][0]; + break; + } + } + } + + $conf['quote'] = $quote; + return $conf; + } + + /** + * Front to call getPointer and moving the resource to the + * beginning of the file + * Reset it if you like. + * + * @param string $file The name of the file + * @param array &$conf The configuration + * @param string $mode The open node (ex: FILE_MODE_READ or FILE_MODE_WRITE) + * + * @return boolean true on success false on failure + */ + function resetPointer($file, &$conf, $mode) + { + if (!File_CSV::getPointer($file, $conf, $mode, true)) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/plugins/file/scp/lib/Pear/File/Util.php b/plugins/file/scp/lib/Pear/File/Util.php new file mode 100644 index 0000000..92de5be --- /dev/null +++ b/plugins/file/scp/lib/Pear/File/Util.php @@ -0,0 +1,482 @@ + + * @copyright 2004-2005 Michael Wallner + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Util.php,v 1.25 2007/02/20 14:19:08 mike Exp $ + * @link http://pear.php.net/package/File + */ + +/**#@+ + * Sorting Constants + */ +define('FILE_SORT_NONE', 0); +define('FILE_SORT_REVERSE', 1); +define('FILE_SORT_NAME', 2); +define('FILE_SORT_SIZE', 4); +define('FILE_SORT_DATE', 8); +define('FILE_SORT_RANDOM', 16); +/**#@-*/ + +/**#@+ + * Listing Constants + */ +define('FILE_LIST_FILES', 1); +define('FILE_LIST_DIRS', 2); +define('FILE_LIST_DOTS', 4); +define('FILE_LIST_ALL', FILE_LIST_FILES | FILE_LIST_DIRS | FILE_LIST_DOTS); +/**#@-*/ + +/** + * @ignore + */ +define('FILE_WIN32', defined('OS_WINDOWS') ? OS_WINDOWS : !strncasecmp(PHP_OS, 'win', 3)); + +/** + * File_Util + * + * File and directory utility functions. + * + * @access public + * @static + */ +class File_Util +{ + /** + * Returns a string path built from the array $pathParts. Where a join + * occurs multiple separators are removed. Joins using the optional + * separator, defaulting to the PHP DIRECTORY_SEPARATOR constant. + * + * @static + * @access public + * @param array $parts Array containing the parts to be joined + * @param string $separator The directory seperator + */ + function buildPath($parts, $separator = DIRECTORY_SEPARATOR) + { + $qs = '/^'. preg_quote($separator, '/') .'+$/'; + for ($i = 0, $c = count($parts); $i < $c; $i++) { + if (!strlen($parts[$i]) || preg_match($qs, $parts[$i])) { + unset($parts[$i]); + } elseif (0 == $i) { + $parts[$i] = rtrim($parts[$i], $separator); + } elseif ($c - 1 == $i) { + $parts[$i] = ltrim($parts[$i], $separator); + } else { + $parts[$i] = trim($parts[$i], $separator); + } + } + return implode($separator, $parts); + } + + /** + * Returns a path without leading / or C:\. If this is not + * present the path is returned as is. + * + * @static + * @access public + * @param string $path The path to be processed + * @return string The processed path or the path as is + */ + function skipRoot($path) + { + if (File_Util::isAbsolute($path)) { + if (FILE_WIN32) { + return substr($path, $path{3} == '\\' ? 4 : 3); + } + return ltrim($path, '/'); + } + return $path; + } + + /** + * Returns the temp directory according to either the TMP, TMPDIR, or + * TEMP env variables. If these are not set it will also check for the + * existence of /tmp, %WINDIR%\temp + * + * @static + * @access public + * @return string The system tmp directory + */ + function tmpDir() + { + if (FILE_WIN32) { + if (isset($_ENV['TEMP'])) { + return $_ENV['TEMP']; + } + if (isset($_ENV['TMP'])) { + return $_ENV['TMP']; + } + if (isset($_ENV['windir'])) { + return $_ENV['windir'] . '\\temp'; + } + if (isset($_ENV['SystemRoot'])) { + return $_ENV['SystemRoot'] . '\\temp'; + } + if (isset($_SERVER['TEMP'])) { + return $_SERVER['TEMP']; + } + if (isset($_SERVER['TMP'])) { + return $_SERVER['TMP']; + } + if (isset($_SERVER['windir'])) { + return $_SERVER['windir'] . '\\temp'; + } + if (isset($_SERVER['SystemRoot'])) { + return $_SERVER['SystemRoot'] . '\\temp'; + } + return '\temp'; + } + if (isset($_ENV['TMPDIR'])) { + return $_ENV['TMPDIR']; + } + if (isset($_SERVER['TMPDIR'])) { + return $_SERVER['TMPDIR']; + } + return '/tmp'; + } + + /** + * Returns a temporary filename using tempnam() and File::tmpDir(). + * + * @static + * @access public + * @param string $dirname Optional directory name for the tmp file + * @return string Filename and path of the tmp file + */ + function tmpFile($dirname = null) + { + if (!isset($dirname)) { + $dirname = File_Util::tmpDir(); + } + return tempnam($dirname, 'temp.'); + } + + /** + * Returns boolean based on whether given path is absolute or not. + * + * @static + * @access public + * @param string $path Given path + * @return boolean True if the path is absolute, false if it is not + */ + function isAbsolute($path) + { + if (preg_match('/(?:\/|\\\)\.\.(?=\/|$)/', $path)) { + return false; + } + if (FILE_WIN32) { + return preg_match('/^[a-zA-Z]:(\\\|\/)/', $path); + } + return ($path{0} == '/') || ($path{0} == '~'); + } + + /** + * Checks for a file's existence, taking the current include path + * into consideration + * + * This method can be called statically + * (e.g., File_Util::isIncludable('config.php')) + * + * @param string $file + * @param string $sep the directory separator (optional) + * @return string the includable path + * @access public + * @static + */ + function isIncludable($file, $sep = DIRECTORY_SEPARATOR) + { + foreach ((array) explode(PATH_SEPARATOR, ini_get('include_path')) as $path) { + if (file_exists($path .= $sep . $file)) { + return $path; + } + } + if (file_exists($file)) { + return $file; + } + return NULL; + } + + /** + * Get path relative to another path + * + * @static + * @access public + * @return string + * @param string $path + * @param string $root + * @param string $separator + */ + function relativePath($path, $root, $separator = DIRECTORY_SEPARATOR) + { + $path = File_Util::realpath($path, $separator); + $root = File_Util::realpath($root, $separator); + $dirs = explode($separator, $path); + $comp = explode($separator, $root); + + if (FILE_WIN32) { + if (strcasecmp($dirs[0], $comp[0])) { + return $path; + } + unset($dirs[0], $comp[0]); + } + + foreach ($comp as $i => $part) { + if (isset($dirs[$i]) && $part == $dirs[$i]) { + unset($dirs[$i], $comp[$i]); + } else { + break; + } + } + + return str_repeat('..' . $separator, count($comp)) . implode($separator, $dirs); + } + + /** + * Get real path (works with non-existant paths) + * + * @static + * @access public + * @return string + * @param string $path + * @param string $separator + */ + function realPath($path, $separator = DIRECTORY_SEPARATOR) + { + if (!strlen($path)) { + return $separator; + } + + $drive = ''; + if (FILE_WIN32) { + $path = preg_replace('/[\\\\\/]/', $separator, $path); + if (preg_match('/([a-zA-Z]\:)(.*)/', $path, $matches)) { + $drive = $matches[1]; + $path = $matches[2]; + } else { + $cwd = getcwd(); + $drive = substr($cwd, 0, 2); + if ($path{0} !== $separator{0}) { + $path = substr($cwd, 3) . $separator . $path; + } + } + } elseif ($path{0} !== $separator) { + $path = getcwd() . $separator . $path; + } + + $dirStack = array(); + foreach (explode($separator, $path) as $dir) { + if (strlen($dir) && $dir !== '.') { + if ($dir == '..') { + array_pop($dirStack); + } else { + $dirStack[] = $dir; + } + } + } + + return $drive . $separator . implode($separator, $dirStack); + } + + /** + * Check whether path is in root path + * + * @static + * @access public + * @return bool + * @param string $path + * @param string $root + */ + function pathInRoot($path, $root) + { + static $realPaths = array(); + + if (!isset($realPaths[$root])) { + $realPaths[$root] = File_Util::realPath($root); + } + + return false !== strstr(File_Util::realPath($path), $realPaths[$root]); + } + + /** + * List Directory + * + * The final argument, $cb, is a callback that either evaluates to true or + * false and performs a filter operation, or it can also modify the + * directory/file names returned. To achieve the latter effect use as + * follows: + * + * + * name, "\n"; + * } + * ?> + * + * + * @static + * @access public + * @return array + * @param string $path + * @param int $list + * @param int $sort + * @param mixed $cb + */ + function listDir($path, $list = FILE_LIST_ALL, $sort = FILE_SORT_NONE, $cb = null) + { + if (!strlen($path) || !is_dir($path)) { + return null; + } + + $entries = array(); + for ($dir = dir($path); false !== $entry = $dir->read(); ) { + if ($list & FILE_LIST_DOTS || $entry{0} !== '.') { + $isRef = ($entry === '.' || $entry === '..'); + $isDir = $isRef || is_dir($path .'/'. $entry); + if ( ((!$isDir && $list & FILE_LIST_FILES) || + ($isDir && $list & FILE_LIST_DIRS)) && + (!is_callable($cb) || + call_user_func_array($cb, array(&$entry)))) { + $entries[] = (object) array( + 'name' => $entry, + 'size' => $isDir ? null : filesize($path .'/'. $entry), + 'date' => filemtime($path .'/'. $entry), + ); + } + } + } + $dir->close(); + + if ($sort) { + $entries = File_Util::sortFiles($entries, $sort); + } + + return $entries; + } + + /** + * Sort Files + * + * @static + * @access public + * @return array + * @param array $files + * @param int $sort + */ + function sortFiles($files, $sort) + { + if (!$files) { + return array(); + } + + if (!$sort) { + return $files; + } + + if ($sort === 1) { + return array_reverse($files); + } + + if ($sort & FILE_SORT_RANDOM) { + shuffle($files); + return $files; + } + + $names = array(); + $sizes = array(); + $dates = array(); + + if ($sort & FILE_SORT_NAME) { + $r = &$names; + } elseif ($sort & FILE_SORT_DATE) { + $r = &$dates; + } elseif ($sort & FILE_SORT_SIZE) { + $r = &$sizes; + } else { + asort($files, SORT_REGULAR); + return $files; + } + + $sortFlags = array( + FILE_SORT_NAME => SORT_STRING, + FILE_SORT_DATE => SORT_NUMERIC, + FILE_SORT_SIZE => SORT_NUMERIC, + ); + + foreach ($files as $file) { + $names[] = $file->name; + $sizes[] = $file->size; + $dates[] = $file->date; + } + + if ($sort & FILE_SORT_REVERSE) { + arsort($r, $sortFlags[$sort & ~1]); + } else { + asort($r, $sortFlags[$sort]); + } + + $result = array(); + foreach ($r as $i => $f) { + $result[] = $files[$i]; + } + + return $result; + } + + /** + * Switch File Extension + * + * @static + * @access public + * @return string|array + * @param string|array $filename + * @param string $to new file extension + * @param string $from change only files with this extension + * @param bool $reverse change only files not having $from extension + */ + function switchExt($filename, $to, $from = null, $reverse = false) + { + if (is_array($filename)) { + foreach ($filename as $key => $file) { + $filename[$key] = File_Util::switchExt($file, $to, $from); + } + return $filename; + } + + if ($len = strlen($from)) { + $ext = substr($filename, -$len - 1); + $cfn = FILE_WIN32 ? 'strcasecmp' : 'strcmp'; + if (!$reverse == $cfn($ext, '.'. $from)) { + return $filename; + } + return substr($filename, 0, -$len - 1) .'.'. $to; + } + + if ($pos = strpos($filename, '.')) { + return substr($filename, 0, $pos) .'.'. $to; + } + + return $filename .'.'. $to; + } +} + +?> diff --git a/plugins/file/scp/lib/Pear/Net/OpenSSH.php b/plugins/file/scp/lib/Pear/Net/OpenSSH.php new file mode 100644 index 0000000..2fc6bcc --- /dev/null +++ b/plugins/file/scp/lib/Pear/Net/OpenSSH.php @@ -0,0 +1,331 @@ + + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ + +require_once 'System.php'; +require_once 'File.php'; +require_once 'File/Util.php'; +require_once 'Net/OpenSSH/Exception.php'; + +/** + * The method mapErrorCode in each OpenSSH implementation maps + * native codes to one of these. + * + * If you add a code here, make sure you also add a textual + * version of it in Net_OpenSSH::getMessage(). + */ + +define('OPENSSH_OK', 0); +define('OPENSSH_ERROR', 1); +define('OPENSSH_PACKAGE_NOT_FOUND', 2); +define('OPENSSH_CLASS_NOT_FOUND', 3); +define('OPENSSH_OPTION_NOT_VALID', 4); +define('OPENSSH_BINARY_NOT_FOUND', 5); +define('OPENSSH_OPTION_REQUIRED', 6); + + +/** + * Simple wrapper interface for the OpenSSH utility tools. + * + * @category Net + * @package Net_SSH + * @author Luca Corbo + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + * @link http://www.openssh.com/ + */ +class Net_OpenSSH +{ + /** + * Absolute path of the temporary script implements SSH_ASKPASS. + * + * @var string + * @link http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&sektion=1#ENVIRONMENT + */ + protected $ssh_askpass_scripts = null; + + + /** + * List of options managed by __set and __get methods + * + * @internal + * @var array + */ + protected $options = array(); + + /** + * Allowed OpenSSH tool option arguments + * List of options allowed in the wrapper implementation + * for the specific driver + * + * @var array + */ + protected $allowed_options = array(); + + /** + * Input stream + * + * @see exec() + * @var string + */ + protected $std_input = null; + + /** + * Overloading of the __get method + * + * @param string $key The name of the variable that should be retrieved + * + * @throws Net_OpenSSH_Exception If trying to get an undefined properties. + * @return mixed The value of the object on success + */ + protected function __get($key) + { + if (!key_exists($key, $this->allowed_options)) { + throw new Net_OpenSSH_Exception(Net_OpenSSH::getMessage(OPENSSH_OPTION_NOT_VALID, $key)); + } + if (isset($this->options[$key])) { + return $this->options[$key]; + } else { + //return the default value + return $this->allowed_options[$key]; + } + } + + /** + * Overloading of the __set method + * + * @param string $key The name of the properties that should be set + * @param mixed $value parameter specifies the value that the object + * should set the $key + * + * @throws Net_OpenSSH_Exception If trying to set an undefined properties. + * @return mixed True on success + */ + protected function __set($key, $value) + { + if (!key_exists($key, $this->allowed_options)) { + throw new Net_OpenSSH_Exception(Net_OpenSSH::getMessage(OPENSSH_OPTION_NOT_VALID, $key)); + } + $this->options[$key] = $value; + return true; + } + + + /** + * Attempts to return a concrete OpenSSH instance of type $wrapper + * + * @param string $wrapper The type of concrete OpenSSH subclass to return. + * Attempt to dynamically include the code for + * this subclass. + * + * @param array $options optional. An array of options used to create the + * OpenSSH object. All options must be optional and are + * represented as key-value pairs. + * + * @throws Net_OpenSSH_Exception If OpenSSH package driver does not exist or + * the class was not found. + * + * @return null + */ + function &factory($wrapper, $options = array()) + { + $class = 'Net_OpenSSH_' . $wrapper; + $classfile = 'Net/OpenSSH/' . $wrapper . '.php'; + + // Attempt to include our version of the named class. + if (!class_exists($class)) { + $include = include_once $classfile; + if (!$include) { + throw new Net_OpenSSH_Exception(Net_OpenSSH::getMessage(OPENSSH_PACKAGE_NOT_FOUND, $classfile)); + } + } + + /* If the class exists, return a new instance of it. */ + if (!class_exists($class)) { + throw new Net_OpenSSH_Exception(Net_OpenSSH::getMessage(OPENSSH_CLASS_NOT_FOUND, $class)); + } + + $obj = &new $class($options); + return $obj; + } + + + /** + * Checks if the specified tool binary exists and for valid options. + * + * @param array $options optional. An array of options used to create the + * OpenSSH object. All options must be optional and are + * represented as key-value pairs. + * + * @throws Net_OpenSSH_Exception If the specified OpenSSH binary tool was not found. + * @return void + */ + protected function init($options) + { + //Check for ssh binary + if (array_key_exists('openssh_binary', $options)) { + $this->openssh_binary = escapeshellarg($options['openssh_binary']); + } else { + $this->openssh_binary = System::which($this->allowed_options['openssh_binary']); + if (!$this->openssh_binary) { + throw new Net_OpenSSH_Exception( + Net_OpenSSH::getMessage( + OPENSSH_BINARY_NOT_FOUND, + $this->allowed_options['openssh_binary'] + ) + ); + } + } + + //Check for valid options + foreach ($options as $key => $value) { + $this->{$key} = $value; + } + } + + /** + * Overloading of the __destruct method, ensure to remove the SSH_ASKPASS + * script if created. + */ + function __destruct() + { + if ($this->ssh_askpass_scripts !== null && is_file($this->ssh_askpass_scripts)) { + System::rm($this->ssh_askpass_scripts); + } + } + + /** + * Generate the temporary ssh_askpass script + * + * @param string $password The password to use for login. + * + * @return void + */ + protected function ssh_askpass($password) + { + + $this->ssh_askpass_scripts = File_Util::tmpFile(); + + $askpass_data = 'echo ' . $password . ' < /dev/null'; + File::write($this->ssh_askpass_scripts, $askpass_data); + File::closeAll(); + chmod($this->ssh_askpass_scripts, 0700); + } + + + + /** + * Abstract implementation of the createCommandLine() method. + * + * @return false + */ + protected function createCommandLine() + { + return false; + } + + /** + * Execute the command. + * + * @param string $std_output The standard output of the executed command + * @param string $std_error The standard error of the executed command + * @param int $exit_code The return status of the executed command + * + * @return true on success + */ + function exec(&$std_output, &$std_error, &$exit_code) + { + $cmd = $this->createCommandLine(); + //This value can be set in the createCommandLine method implementation + $std_input = $this->std_input; + + $descriptorspec = array(0 => array("pty"), + 1 => array("pty"), + 2 => array("pty")); + + $process = proc_open($cmd, $descriptorspec, $pipes); + + if (is_resource($process)) { + stream_set_blocking($pipes[0], false); + stream_set_blocking($pipes[1], false); + stream_set_blocking($pipes[2], false); + + if ($std_input !== null) { + $std_output .= fgets($pipes[1], 4096); + sleep(2); + fwrite($pipes[0], $std_input . "\n"); + fflush($pipes[0]); + } + + while (!feof($pipes[1])) { + $std_output .= fgets($pipes[1], 4096); + } + + while (!feof($pipes[2])) { + $std_error .= fgets($pipes[2], 4096); + } + + fclose($pipes[0]); + fclose($pipes[1]); + fclose($pipes[2]); + $exit_code = proc_close($process); + } + return true; + } + + /** + * Return a textual message for an OpenSSH code + * + * @param int $code OpenSSH code, + * used to get the current code-message map. + * @param string $value Optional. The argument to be inserted at the first + * %-sign in the format string + * + * @return string The OpenSSH message string + * + */ + protected function getMessage($code, $value = null) + { + static $codeMessages; + if (!isset($codeMessages)) { + $codeMessages = array( + OPENSSH_OK => 'No error', + OPENSSH_ERROR => 'Unknown error', + OPENSSH_PACKAGE_NOT_FOUND => 'Unable to find package %s', + OPENSSH_CLASS_NOT_FOUND => 'Unable to load class %s', + OPENSSH_OPTION_NOT_VALID => 'Trying to use an undefined option %s for the object ' . __CLASS__, + OPENSSH_BINARY_NOT_FOUND => 'Unable to found the OpenSSH binary command "%s"', + OPENSSH_OPTION_REQUIRED => 'The option %s is required for the object ' . __CLASS__ + ); + } + return sprintf($codeMessages[$code], $value); + } +} +?> \ No newline at end of file diff --git a/plugins/file/scp/lib/Pear/Net/OpenSSH/Exception.php b/plugins/file/scp/lib/Pear/Net/OpenSSH/Exception.php new file mode 100644 index 0000000..2c87bc7 --- /dev/null +++ b/plugins/file/scp/lib/Pear/Net/OpenSSH/Exception.php @@ -0,0 +1,63 @@ + + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ + +require_once 'PEAR/Exception.php'; + +/** + * An exception thrown by Net_OpenSSH when it encounters an unrecoverable error. + * + * PHP version 5 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA + * + * @category Net + * @package Net_OpenSSH + * @author Luca Corbo + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ +class Net_OpenSSH_Exception extends PEAR_Exception +{ + +} +?> diff --git a/plugins/file/scp/lib/Pear/Net/OpenSSH/SSH.php b/plugins/file/scp/lib/Pear/Net/OpenSSH/SSH.php new file mode 100644 index 0000000..bb32dc8 --- /dev/null +++ b/plugins/file/scp/lib/Pear/Net/OpenSSH/SSH.php @@ -0,0 +1,127 @@ + + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ + +/** + * The Net_OpenSSH_SSH class is a concrete implementation of the Net_OpenSSH:: + * abstract class for the OpenSSH SSH client tool. + * + * PLEASE NOTE that you must create a Net_OpenSSH_ssh like this : + * $open_ssh =& Net_OpenSSH::factory('SSH'); + * + * @category Net + * @package Net_OpenSSH + * @author Luca Corbo + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ +class Net_OpenSSH_SSH extends Net_OpenSSH +{ + + /** + * SSH option arguments + * List of the allowed options managed by __set and __get methods + * + * @var array + * @see Net_OpenSSH_ssh::__construct() + * @link http://www.openbsd.org/cgi-bin/man.cgi?query=ssh + */ + protected $allowed_options = array('openssh_binary' => 'ssh', + 'login_name' => null, + 'password' => null, + 'hostname' => null, + 'identity_file' => null, + 'option' => null, + 'port' => 22, + 'command' => null); + + /** + * Creates a new SSH object + * + * @param array $options optional. An array of options used to create the + * SSH object. All options must be optional and are + * represented as key-value pairs. + */ + function __construct($options = array()) + { + parent::init($options); + } + + /** + * Prepare the command line to execute + * + * @return string + */ + protected function createCommandLine() + { + $cmd = escapeshellarg($this->openssh_binary); + + if ($this->identity_file !== null) { + $cmd .= ' -i ' . escapeshellarg($this->identity_file); + } + + if ($this->login_name !== null) { + $cmd .= ' -l ' . escapeshellarg($this->login_name); + } + + if ($this->option !== null) { + foreach ($this->option as $key => $option) { + $cmd .= ' -o ' . escapeshellarg($option); + } + } + + if ($this->port !== null) { + $cmd .= ' -p ' . $this->port; + } + + if ($this->password !== null) { + $this->ssh_askpass($this->password); + $cmd = "SSH_ASKPASS=" . + escapeshellarg($this->ssh_askpass_scripts) . + ' ' . $cmd; + } + + if ($this->hostname !== null) { + $cmd .= ' ' . escapeshellarg($this->hostname); + } + + if ($this->command !== null) { + //Check for input script + if (is_file($this->command)) { + //reading commands to execute from file + $cmd .= ' < ' . $this->command; + } else { + $cmd .= ' ' . $this->command; + } + } + return $cmd; + } +} +?> diff --git a/plugins/file/scp/lib/Pear/Net/OpenSSH/SSHCopyId.php b/plugins/file/scp/lib/Pear/Net/OpenSSH/SSHCopyId.php new file mode 100644 index 0000000..6c1d277 --- /dev/null +++ b/plugins/file/scp/lib/Pear/Net/OpenSSH/SSHCopyId.php @@ -0,0 +1,123 @@ + + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ + +/** + * The Net_OpenSSH_SSHCopyId class is a concrete implementation of the Net_OpenSSH + * abstract class for the OpenSSH ssh-copy-id utility. + * + * PLEASE NOTE that you must create a Net_OpenSSH_SSHCopyId like this : + * $open_ssh_copy_id =& Net_OpenSSH::factory('SSHCopyId'); + * + * @category Net + * @package Net_OpenSSH + * @author Luca Corbo + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ +class Net_OpenSSH_SSHCopyId extends Net_OpenSSH +{ + + /** + * ssh-copy-id option arguments + * List of the allowed options managed by __set and __get methods + * + * @var array + * @see Net_OpenSSH_SSHCopyId::__construct() + */ + protected $allowed_options = array('openssh_binary' => 'ssh', + 'login_name' => null, + 'password' => null, + 'hostname' => null, + 'identity_file' => null, + 'port' => 22 + ); + + /** + * Creates a new SSHCopyId object + * + * @param array $options optional. An array of options used to create the + * SSHCopyId object. All options must be optional and are + * represented as key-value pairs. + */ + function __construct($options = array()) + { + parent::init($options); + } + + /** + * Prepare the command line to execute + * + * @return string + */ + protected function createCommandLine() + { + if ($this->identity_file !== null) { + $cmd = '"' . File::readAll($this->identity_file) . '"'; + } else { + throw new Net_OpenSSH_Exception( + Net_OpenSSH::getMessage( + OPENSSH_OPTION_REQUIRED, + 'identity_file' + ) + ); + } + + $cmd .= ' | '; + + if ($this->password !== null) { + $this->ssh_askpass($this->password); + $cmd .= "SSH_ASKPASS=" . + escapeshellarg($this->ssh_askpass_scripts) . + ' '; + } + + $cmd .= escapeshellarg($this->openssh_binary); + + if ($this->login_name !== null) { + $cmd .= ' -l ' . escapeshellarg($this->login_name); + } + + if ($this->port !== null) { + $cmd .= ' -p ' . $this->port; + } + + + + if ($this->hostname !== null) { + $cmd .= ' ' . escapeshellarg($this->hostname); + } + + $cmd .= ' "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || exit 1'; + return $cmd; + } +} +?> diff --git a/plugins/file/scp/lib/Pear/Net/OpenSSH/SSHKeygen.php b/plugins/file/scp/lib/Pear/Net/OpenSSH/SSHKeygen.php new file mode 100644 index 0000000..e6ffc48 --- /dev/null +++ b/plugins/file/scp/lib/Pear/Net/OpenSSH/SSHKeygen.php @@ -0,0 +1,119 @@ + + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ + +/** + * The Net_OpenSSH_SSHKeygen class is a concrete implementation of the Net_OpenSSH + * abstract class for the ssh-keygen authentication key generation, + * management and conversion tool. + * + * PLEASE NOTE that you must create a Net_OpenSSH_ssh like this : + * $open_ssh =& Net_OpenSSH::factory('SSHKeygen'); + * + * @category Net + * @package Net_OpenSSH + * @author Luca Corbo + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ +class Net_OpenSSH_SSHKeygen extends Net_OpenSSH +{ + + /** + * ssh-keygen option arguments + * List of options managed by __set and __get methods + * + * @var array + * @see Net_OpenSSH_SSHKeygen::__construct() + * @link http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keygen + */ + protected $allowed_options = array('openssh_binary' => 'ssh-keygen', + 'silence' => null, + 'bits' => null, + 'type' => null, + 'new_passphrase' => '', + 'comment' => null, + 'output_keyfile' => null, + 'overwrite_existing_key' => null); + + /** + * Creates a new SSH-KEYGEN object + * + * @param array $options optional. An array of options used to create the + * SSH-KEYGEN object. All options must be optional + * and are represented as key-value pairs. + */ + function __construct($options = array()) + { + parent::init($options); + } + + /** + * Prepare the command to execute + * + * @return string + */ + protected function createCommandLine() + { + + $cmd = $this->openssh_binary; + + if ($this->silence) { + $cmd .= ' -q '; + } + + if ($this->bits !== null) { + $cmd .= ' -b ' . $this->bits; + } + + if ($this->type !== null) { + $cmd .= ' -t ' . $this->type; + } + + $cmd .= ' -N ' . $this->new_passphrase; + + if ($this->comment !== null) { + $cmd .= ' -C ' . $this->comment; + } + + if ($this->output_keyfile !== null) { + $cmd .= ' -f ' . $this->output_keyfile; + } + + if ($this->overwrite_existing_key) { + $this->std_input = 'y'; + } else { + $this->std_input = 'n'; + } + + return $cmd; + } +} +?> diff --git a/plugins/file/scp/lib/Pear/Net/OpenSSH/Scp.php b/plugins/file/scp/lib/Pear/Net/OpenSSH/Scp.php new file mode 100644 index 0000000..01738e5 --- /dev/null +++ b/plugins/file/scp/lib/Pear/Net/OpenSSH/Scp.php @@ -0,0 +1,142 @@ + + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ + +/** + * The Net_OpenSSH_ssh class is a concrete implementation of the Net_OpenSSH + * abstract class for the scp utility. + * + * PLEASE NOTE that you must create a Net_OpenSSH_Scp like this : + * $open_ssh =& Net_OpenSSH::factory('Scp'); + * + * @category Net + * @package Net_OpenSSH + * @author Luca Corbo + * @copyright 2009 Luca Corbo + * @license GNU/LGPL v2.1 + * @link http://pear.php.net/packages/Net_OpenSSH + */ +class Net_OpenSSH_Scp extends Net_OpenSSH +{ + + /** + * scp option arguments + * List of options managed by __set and __get methods + * + * @var array + * @see Net_OpenSSH_ssh_keygen::__construct() + * @link http://www.openbsd.org/cgi-bin/man.cgi?query=scp + */ + protected $allowed_options = array('openssh_binary' => 'scp', + 'identity_file' => null, + 'option' => null, + 'port' => 22, + 'limit' => null, + 'recursive' => null, + 'src_config' => null, + 'dest_config' => null, + 'password' => null); + + /** + * Creates a new Scp object + * + * @param array $options optional. An array of options used to create the + * Scp object. All options must be optional + * and are represented as key-value pairs. + */ + function __construct($options = array()) + { + parent::init($options); + } + + /** + * Prepare the command to execute + * + * @return string + */ + public function createCommandLine() + { + $cmd = $this->openssh_binary; + + if ($this->recursive == 'y') { + $cmd .= ' -r '; + } + + if ($this->identity_file !== null) { + $cmd .= ' -i ' . escapeshellarg($this->identity_file); + } + + if ($this->port !== null) { + $cmd .= ' -P ' . $this->port; + } + + if ($this->limit !== null) { + $cmd .= ' -l ' . $this->limit; + } + + if ($this->option !== null) { + foreach ($this->option as $key => $option) { + $cmd .= ' -o ' . escapeshellarg($option); + } + } + + if ($this->password !== null) { + $this->ssh_askpass($this->password); + $cmd = "SSH_ASKPASS=" . + escapeshellarg($this->ssh_askpass_scripts) . + ' ' . $cmd; + } + + if ($this->src_config !== null) { + foreach ($this->src_config as $key => $src_config) { + $cmd .= ' '; + if (isset ($src_config['user'])) { + $cmd .= escapeshellarg($src_config['user']) . '@'; + } + if (isset ($src_config['hostname'])) { + $cmd .= escapeshellarg($src_config['hostname']) . ':'; + } + $cmd .= escapeshellarg($src_config['path']) . ' '; + } + } + + if ($this->dest_config !== null) { + $cmd .= ' '; + if (isset ($this->dest_config['user'])) { + $cmd .= escapeshellarg($this->dest_config['user']) . '@'; + } + if (isset ($this->dest_config['hostname'])) { + $cmd .= escapeshellarg($this->dest_config['hostname']) . ':'; + } + $cmd .= escapeshellarg($this->dest_config['path']) . ' '; + } + return $cmd; + } +} +?> diff --git a/plugins/file/search/CHANGELOG b/plugins/file/search/CHANGELOG new file mode 100644 index 0000000..8278bf6 --- /dev/null +++ b/plugins/file/search/CHANGELOG @@ -0,0 +1,19 @@ +1.2.4 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.2.3 (2007.11.19) +------------------ +Use init.inc.php + +1.2.2 (2007.08.21) +------------------ +Fixed title in english translation. + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/file/search/LICENSE b/plugins/file/search/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/search/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/search/configure.php b/plugins/file/search/configure.php new file mode 100644 index 0000000..f07435b --- /dev/null +++ b/plugins/file/search/configure.php @@ -0,0 +1,90 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['search'][0]['version'] = '1.2.4'; +$plugin_field['search'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['search'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['search'][0]['description'] = PLUGIN_FILE_SEARCH_DESCRIPTION; +$plugin_field['search'][0]['title'] = PLUGIN_FILE_SEARCH_TITLE; + +$plugin_field['search'][1]['type'] = 'text'; +$plugin_field['search'][1]['name'] = 'file_search_user'; +$plugin_field['search'][1]['value'] = ''; +$plugin_field['search'][1]['attributes'] = 'disabled'; +$plugin_field['search'][1]['description'] = PLUGIN_USER; +$plugin_field['search'][1]['num_rules'] = '1'; +$plugin_field['search'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['search'][1]['rule_type'][0] = 'required'; +$plugin_field['search'][1]['rule_attribute'][0] = ''; + +$plugin_field['search'][2]['type'] = 'text'; +$plugin_field['search'][2]['name'] = 'file_search_port'; +$plugin_field['search'][2]['value'] = ''; +$plugin_field['search'][2]['attributes'] = 'disabled'; +$plugin_field['search'][2]['description'] = PLUGIN_PORT; + +$plugin_field['search'][3]['type'] = 'text'; +$plugin_field['search'][3]['name'] = 'file_search_dir_path'; +$plugin_field['search'][3]['value'] = ''; +$plugin_field['search'][3]['attributes'] = 'disabled size=90'; +$plugin_field['search'][3]['description'] = PLUGIN_FILE_SEARCH_PATH_DESCRIPTION; +$plugin_field['search'][3]['num_rules'] = '1'; +$plugin_field['search'][3]['rule_msg'][0] = PLUGIN_FILE_SEARCH_FILE_RULE_3_0; +$plugin_field['search'][3]['rule_type'][0] = 'required'; +$plugin_field['search'][3]['rule_attribute'][0] = ''; + +$plugin_field['search'][4]['type'] = 'text'; +$plugin_field['search'][4]['name'] = 'file_search_search_for'; +$plugin_field['search'][4]['value'] = ''; +$plugin_field['search'][4]['attributes'] = 'size=90 disabled'; +$plugin_field['search'][4]['description'] = PLUGIN_FILE_SEARCH_SEARCH_DESCRIPTION; +$plugin_field['search'][4]['num_rules'] = '1'; +$plugin_field['search'][4]['rule_msg'][0] = PLUGIN_FILE_SEARCH_FILE_RULE_4_0; +$plugin_field['search'][4]['rule_type'][0] = 'required'; +$plugin_field['search'][4]['rule_attribute'][0] = ''; + +$plugin_field['search'][5]['type'] = 'select'; +$plugin_field['search'][5]['name'] = 'file_search_recursive'; +$plugin_field['search'][5]['value'] = array('0' => PLUGIN_FILE_SEARCH_RECURSIVE_VALUE_FALSE, + '1' => PLUGIN_FILE_SEARCH_RECURSIVE_VALUE_TRUE); +$plugin_field['search'][5]['attributes'] = ''; +$plugin_field['search'][5]['description'] = PLUGIN_FILE_SEARCH_RECURSIVE_DESCRIPTION; + +$plugin_field['search'][6]['type'] = 'select'; +$plugin_field['search'][6]['name'] = 'file_search_operator'; +$plugin_field['search'][6]['value'] = array('-gt' => '>', '-lt' => '<', '-eq' => '=', '-ne' => '!='); +$plugin_field['search'][6]['attributes'] = ''; +$plugin_field['search'][6]['description'] = PLUGIN_FILE_SEARCH_OPERATOR_DESCRIPTION; +$plugin_field['search'][6]['num_rules'] = '0'; + +$plugin_field['search'][7]['type'] = 'text'; +$plugin_field['search'][7]['name'] = 'file_search_expected_occurrence'; +$plugin_field['search'][7]['value'] = ''; +$plugin_field['search'][7]['attributes'] = 'disabled'; +$plugin_field['search'][7]['description'] = PLUGIN_FILE_SEARCH_EXPECTED_OCCURENCE_DESCRIPTION; + +$plugin_field['search'][8]['type'] = 'select'; +$plugin_field['search'][8]['name'] = 'file_search_is_error'; +$plugin_field['search'][8]['value'] = array('success' => PLUGIN_FILE_SEARCH_IS_ERROR_VALUE_1, + 'error' => PLUGIN_FILE_SEARCH_IS_ERROR_VALUE_2); +$plugin_field['search'][8]['attributes'] = ''; +$plugin_field['search'][8]['description'] = PLUGIN_FILE_SEARCH_IS_ERROR_DESCRIPTION; +$plugin_field['search'][8]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/file/search/core.php b/plugins/file/search/core.php new file mode 100644 index 0000000..2aa4e9b --- /dev/null +++ b/plugins/file/search/core.php @@ -0,0 +1,127 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, + ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', + 'Executing job ' . $plugin_name . ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['file_search_user']; + $port = $parameters['file_search_port']; + + // The absolute path of folder to apply retention policy + $dir_path = '"' . $parameters['file_search_dir_path'] . '"'; + // The search pattern + $search_for = '"' . + str_replace('*', + '\*', + $parameters['file_search_search_for']) . + '"'; + // Is it a recursive search? (0 = false, 1 = true) + $recursive = $parameters['file_search_recursive']; + // The boolean operator + $operator = '"' . $parameters['file_search_operator'] . '"'; + // The number of occourrence expected + $expected_occurence = $parameters['file_search_expected_occurrence']; + // If test is true set job result as success or error + $on_true_set = $parameters['file_search_is_error']; + + $script_parameters = array($dir_path, + $search_for, + $recursive, + $operator, + $expected_occurence); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/script.sh'; + + $local_parameters = implode(' ', $script_parameters); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + if ($exit_code == '0') { + $result = '1'; + if ($on_true_set == 'error') { + $result = '0'; + } + } else { + $result = '0'; + if ($on_true_set == 'error') { + $result = '1'; + } + } + + + $msg_exec = $attachments['txt']; + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/search/script.sh b/plugins/file/search/script.sh new file mode 100644 index 0000000..e49eb2c --- /dev/null +++ b/plugins/file/search/script.sh @@ -0,0 +1,47 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License +# a copy of which has been included with this distribution in the LICENSE file. +# +# File Search script +# This allows you to search files using a pattern and checks for an expected number of occurences +# +# File Authors: +# Luca Corbo +# +################################################################################## + + +# The absolute path of folder to apply retention policy +DIR_PATH=$1 +# The search pattern +SEARCH_FOR=$2 +# Is it a recursive search? (0 = false, 1 = true) +RECURSIVE=$3 +# The boolean operator +OPERATOR=$4 +# The number of occourrence expected +EXPECTED_OCCURRENCE=$5 + + +TEMP_FILE="/tmp/ortro_file_search_`date +%Y%m%d`.txt" +if [ "x$RECURSIVE" = "x1" ] + then + find $DIR_PATH -name "$SEARCH_FOR" -type f > $TEMP_FILE + else + find $DIR_PATH/. ! -name . -prune -name "$SEARCH_FOR" -type f > $TEMP_FILE +fi + +NUM_OF_OCCURRENCES=`cat $TEMP_FILE | wc -l` + +#List of files found +echo "Files found:" +cat $TEMP_FILE + +#Remove temp file +rm $TEMP_FILE + +`test $NUM_OF_OCCURRENCES $OPERATOR $EXPECTED_OCCURRENCE` +exit $? \ No newline at end of file diff --git a/plugins/file/size_check/CHANGELOG b/plugins/file/size_check/CHANGELOG new file mode 100644 index 0000000..1b7d49b --- /dev/null +++ b/plugins/file/size_check/CHANGELOG @@ -0,0 +1,15 @@ +1.2.3 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/file/size_check/LICENSE b/plugins/file/size_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/size_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/size_check/configure.php b/plugins/file/size_check/configure.php new file mode 100644 index 0000000..c049873 --- /dev/null +++ b/plugins/file/size_check/configure.php @@ -0,0 +1,79 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['size_check'][0]['version'] = '1.2.3'; +$plugin_field['size_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['size_check'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['size_check'][0]['description'] = PLUGIN_FILE_SIZE_CHECK_DESCRIPTION; +$plugin_field['size_check'][0]['title'] = PLUGIN_FILE_SIZE_CHECK_TITLE; + +$plugin_field['size_check'][1]['type'] = 'text'; +$plugin_field['size_check'][1]['name'] = 'file_size_check_user'; +$plugin_field['size_check'][1]['value'] = ''; +$plugin_field['size_check'][1]['attributes'] = 'disabled'; +$plugin_field['size_check'][1]['description'] = PLUGIN_USER; +$plugin_field['size_check'][1]['num_rules'] = '1'; +$plugin_field['size_check'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['size_check'][1]['rule_type'][0] = 'required'; +$plugin_field['size_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['size_check'][2]['type'] = 'text'; +$plugin_field['size_check'][2]['name'] = 'file_size_check_port'; +$plugin_field['size_check'][2]['value'] = ''; +$plugin_field['size_check'][2]['attributes'] = 'disabled'; +$plugin_field['size_check'][2]['description'] = PLUGIN_PORT; + +$plugin_field['size_check'][3]['type'] = 'text'; +$plugin_field['size_check'][3]['name'] = 'file_size_check_dir_path'; +$plugin_field['size_check'][3]['value'] = ''; +$plugin_field['size_check'][3]['attributes'] = 'disabled size=70'; +$plugin_field['size_check'][3]['description'] = PLUGIN_FILE_SIZE_CHECK_PATH_DESCRIPTION; +$plugin_field['size_check'][3]['num_rules'] = '1'; +$plugin_field['size_check'][3]['rule_msg'][0] = PLUGIN_FILE_SIZE_CHECK_RULE_3_0; +$plugin_field['size_check'][3]['rule_type'][0] = 'required'; +$plugin_field['size_check'][3]['rule_attribute'][0] = ''; + +$plugin_field['size_check'][4]['type'] = 'text'; +$plugin_field['size_check'][4]['name'] = 'file_size_check_search_for'; +$plugin_field['size_check'][4]['value'] = ''; +$plugin_field['size_check'][4]['attributes'] = 'disabled'; +$plugin_field['size_check'][4]['description'] = PLUGIN_FILE_SIZE_CHECK_SEARCH_DESCRIPTION; +$plugin_field['size_check'][4]['num_rules'] = '1'; +$plugin_field['size_check'][4]['rule_msg'][0] = PLUGIN_FILE_SIZE_CHECK_RULE_4_0; +$plugin_field['size_check'][4]['rule_type'][0] = 'required'; +$plugin_field['size_check'][4]['rule_attribute'][0] = ''; + +$plugin_field['size_check'][5]['type'] = 'select'; +$plugin_field['size_check'][5]['name'] = 'file_size_check_recursive'; +$plugin_field['size_check'][5]['value'] = array('0' => PLUGIN_FILE_SIZE_CHECK_RECURSIVE_VALUE_FALSE, + '1' => PLUGIN_FILE_SIZE_CHECK_RECURSIVE_VALUE_TRUE); +$plugin_field['size_check'][5]['attributes'] = ''; +$plugin_field['size_check'][5]['description'] = PLUGIN_FILE_SIZE_CHECK_RECURSIVE_DESCRIPTION; + +$plugin_field['size_check'][6]['type'] = 'text'; +$plugin_field['size_check'][6]['name'] = 'file_size_check_size'; +$plugin_field['size_check'][6]['value'] = ''; +$plugin_field['size_check'][6]['attributes'] = 'disabled'; +$plugin_field['size_check'][6]['description'] = PLUGIN_FILE_SIZE_CHECK_THRESHOLD_DESCRIPTION; +$plugin_field['size_check'][6]['num_rules'] = '1'; +$plugin_field['size_check'][6]['rule_msg'][0] = PLUGIN_FILE_SIZE_CHECK_RULE_6_0; +$plugin_field['size_check'][6]['rule_type'][0] = 'required'; +$plugin_field['size_check'][6]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/file/size_check/core.php b/plugins/file/size_check/core.php new file mode 100644 index 0000000..4b17af1 --- /dev/null +++ b/plugins/file/size_check/core.php @@ -0,0 +1,114 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, + ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', + 'Executing job ' . $plugin_name . ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['file_size_check_user']; + $port = $parameters['file_size_check_port']; + + // The absolute path of folder to apply retention policy + $dir_path = '"' . $parameters['file_size_check_dir_path'] . '"'; + // The search pattern + $search_for = '"' . + str_replace('*', + '\*', + $parameters['file_size_check_search_for']) . + '"'; + // Is it a recursive search? (0 = false, 1 = true) + $recursive = $parameters['file_size_check_recursive']; + // File size threshold (bytes) + $size = $parameters['file_size_check_size']; + + $script_parameters = array($dir_path, + $search_for, + $recursive, + $size); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/script.sh'; + + $local_parameters = implode(' ', $script_parameters); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $attachments['txt'] = implode("\n", $stdout); + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['html'] = implode("
", $stdout); + + $msg_exec = $attachments['txt']; + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/size_check/script.sh b/plugins/file/size_check/script.sh new file mode 100644 index 0000000..39f9577 --- /dev/null +++ b/plugins/file/size_check/script.sh @@ -0,0 +1,41 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License +# a copy of which has been included with this distribution in the LICENSE file. +# +# File Size Check. +# This script allows you to monitor the files size undere a specified diretory +# +# File Authors: +# Luca Corbo +# +################################################################################## + + +# The absolute path of folder to apply retention policy +DIR_PATH=$1 +# The search pattern +SEARCH_FOR=$2 +# Is it a recursive search? (0 = false, 1 = true) +RECURSIVE=$3 +# File size threshold (bytes) +SIZE_TRESHOLD=$4 + +if [ "x$RECURSIVE" = "x1" ] + then + FILES_OVER_SIZE=`find $DIR_PATH -name "$SEARCH_FOR" -type f -size +"$SIZE_TRESHOLD"c` + else + FILES_OVER_SIZE=`find $DIR_PATH/. ! -name . -prune -name "$SEARCH_FOR" -type f -size +"$SIZE_TRESHOLD"c` +fi +if [ "x$FILES_OVER_SIZE" != "x" ] +then + for i in $FILES_OVER_SIZE + do + FILE_NAME=`basename $i` + FILE_SIZE=`ls -l $i | awk '{ print $5 }'` + echo "$FILE_NAME size -> $FILE_SIZE bytes" + done + exit 1 +fi \ No newline at end of file diff --git a/plugins/file/watch/CHANGELOG b/plugins/file/watch/CHANGELOG new file mode 100644 index 0000000..d375161 --- /dev/null +++ b/plugins/file/watch/CHANGELOG @@ -0,0 +1,7 @@ +1.0.1 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.0 (2008.09.08) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/file/watch/LICENSE b/plugins/file/watch/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/file/watch/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/file/watch/configure.php b/plugins/file/watch/configure.php new file mode 100644 index 0000000..7b870c4 --- /dev/null +++ b/plugins/file/watch/configure.php @@ -0,0 +1,71 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$_plugin_name = 'watch'; +$plugin_field['watch'][0]['version'] = '1.0.1'; +$plugin_field['watch'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['watch'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['watch'][0]['description'] = PLUGIN_FILE_WATCH_DESCRIPTION; +$plugin_field['watch'][0]['title'] = PLUGIN_FILE_WATCH_TITLE; + +$plugin_field['watch'][1]['type'] = 'text'; +$plugin_field['watch'][1]['name'] = 'file_watch_user'; +$plugin_field['watch'][1]['value'] = ''; +$plugin_field['watch'][1]['attributes'] = 'disabled'; +$plugin_field['watch'][1]['description'] = PLUGIN_USER; +$plugin_field['watch'][1]['num_rules'] = '1'; +$plugin_field['watch'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['watch'][1]['rule_type'][0] = 'required'; +$plugin_field['watch'][1]['rule_attribute'][0] = ''; + +$plugin_field['watch'][2]['type'] = 'text'; +$plugin_field['watch'][2]['name'] = 'file_watch_port'; +$plugin_field['watch'][2]['value'] = ''; +$plugin_field['watch'][2]['attributes'] = 'disabled'; +$plugin_field['watch'][2]['description'] = PLUGIN_PORT; + +$plugin_field['watch'][3]['type'] = 'text'; +$plugin_field['watch'][3]['name'] = 'file_watch_path'; +$plugin_field['watch'][3]['value'] = ''; +$plugin_field['watch'][3]['attributes'] = 'disabled size=70'; +$plugin_field['watch'][3]['description'] = PLUGIN_FILE_WATCH_PATH_DESCRIPTION; +$plugin_field['watch'][3]['num_rules'] = '1'; +$plugin_field['watch'][3]['rule_msg'][0] = PLUGIN_FILE_WATCH_RULE_3_0; +$plugin_field['watch'][3]['rule_type'][0] = 'required'; +$plugin_field['watch'][3]['rule_attribute'][0] = ''; + +$plugin_field['watch'][4]['type'] = 'text'; +$plugin_field['watch'][4]['name'] = 'file_watch_pattern'; +$plugin_field['watch'][4]['value'] = ''; +$plugin_field['watch'][4]['attributes'] = 'disabled size=70'; +$plugin_field['watch'][4]['description'] = PLUGIN_FILE_WATCH_PATTERN_DESCRIPTION; +$plugin_field['watch'][4]['num_rules'] = '1'; +$plugin_field['watch'][4]['rule_msg'][0] = PLUGIN_FILE_WATCH_RULE_4_0; +$plugin_field['watch'][4]['rule_type'][0] = 'required'; +$plugin_field['watch'][4]['rule_attribute'][0] = ''; + +$plugin_field['watch'][5]['type'] = 'select'; +$plugin_field['watch'][5]['name'] = 'file_watch_is_error'; +$plugin_field['watch'][5]['value'] = array('0' => PLUGIN_FILE_WATCH_SUCCESS, + '1' => PLUGIN_FILE_WATCH_ERROR); +$plugin_field['watch'][5]['attributes'] = ''; +$plugin_field['watch'][5]['description'] = PLUGIN_FILE_WATCH_ERROR_DESCRIPTION ; +$plugin_field['watch'][5]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/file/watch/core.php b/plugins/file/watch/core.php new file mode 100644 index 0000000..d1730e5 --- /dev/null +++ b/plugins/file/watch/core.php @@ -0,0 +1,145 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', + 'Executing job ' . $plugin_name . ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['file_watch_user']; + $port = $parameters['file_watch_port']; + $match_is_error = $parameters['file_watch_is_error']; + + $init_size = 0; + + if (is_file(ORTRO_TEMP . $id_job)) { + //get the file size at the last check + $init_size = file_get_contents(ORTRO_TEMP . $id_job); + + } + + $loggerPlugin->trace('DEBUG', 'Script parameters: ' . print_r($job_infos, true)); + + // The absolute path of the file to watch + $log_file_path = '"' . $parameters['file_watch_path'] . '"'; + + // The search pattern + $pattern = '\'' . $parameters['file_watch_pattern'] . '\''; + + $script_parameters = array($log_file_path, + $pattern, + $init_size); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/script.sh'; + + $local_parameters = implode(' ', $script_parameters); + + $loggerPlugin->trace('DEBUG', 'Script parameters: ' . print_r($script_parameters, true)); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + + if ($exit_code == 0) {//an occurence with the pattern search was found + //store the actual size of the monitored file. + $actual_size = array_shift($stdout); + file_put_contents(ORTRO_TEMP . $id_job, $actual_size); + + if ($match_is_error == 1) {//pattern match is an error + $exit_code = 1; + } + } + + if ($exit_code == 2) {//an occurence with the pattern search was not found + //store the actual size of the monitored file. + $actual_size = array_shift($stdout); + file_put_contents(ORTRO_TEMP . $id_job, $actual_size); + + if ($match_is_error == 1) {//pattern match is an error + $exit_code = 0; + } else { + $exit_code = 1; + } + } + + $loggerPlugin->trace('DEBUG', 'init_size: ' . $init_size); + $loggerPlugin->trace('DEBUG', 'actual_size: ' . $actual_size); + + $attachments['txt'] = implode("\n", $stdout); + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['html'] = implode("
", $stdout); + + $msg_exec = $attachments['txt']; + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/file/watch/script.sh b/plugins/file/watch/script.sh new file mode 100644 index 0000000..2508d25 --- /dev/null +++ b/plugins/file/watch/script.sh @@ -0,0 +1,50 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License +# a copy of which has been included with this distribution in the LICENSE file. +# +# File Size Check. +# This script allows you to monitor the files size undere a specified diretory +# +# File Authors: +# Luca Corbo +# +################################################################################## + + +#!/bin/sh + +if [ $# != 3 ]; then + echo "Usage: $0 log_file reg_exp init_size" + exit 1 +fi + +LOG_FILE=$1 +REG_EXP=$2 +INIT_SIZE=$3 +TMP_FILE="/tmp/check_log_$$.tmp" + +ACTUAL_SIZE=`ls -l ${LOG_FILE} | awk '{print $5}'` + +if [ ${ACTUAL_SIZE} -lt $INIT_SIZE ]; then + INIT_SIZE=0 +fi + +echo ${ACTUAL_SIZE} > ${TMP_FILE} + +tail -c +$((${INIT_SIZE} + 1)) "${LOG_FILE}" | egrep "${REG_EXP}" >> ${TMP_FILE} + +EXIT_CODE=$? + +if [ $? -eq 0 ]; then + EXIT_CODE=0 +else + EXIT_CODE=2 +fi + +cat ${TMP_FILE} +rm ${TMP_FILE} + +exit ${EXIT_CODE} \ No newline at end of file diff --git a/plugins/general/custom_script/CHANGELOG b/plugins/general/custom_script/CHANGELOG new file mode 100644 index 0000000..ee66465 --- /dev/null +++ b/plugins/general/custom_script/CHANGELOG @@ -0,0 +1,15 @@ +1.2.3 (2009.04.03) +------------------ +#111 Execute local custom script on remote server + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support diff --git a/plugins/general/custom_script/LICENSE b/plugins/general/custom_script/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/general/custom_script/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/general/custom_script/configure.php b/plugins/general/custom_script/configure.php new file mode 100644 index 0000000..8acc3d3 --- /dev/null +++ b/plugins/general/custom_script/configure.php @@ -0,0 +1,70 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['custom_script'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['custom_script'][0]['action'] = 'plugin'; +$plugin_actions['custom_script'][0]['file'] = 'display_archive_results'; +$plugin_actions['custom_script'][0]['image'] = 'archive.png'; + +$plugin_field['custom_script'][0]['version'] = '1.2.3'; +$plugin_field['custom_script'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['custom_script'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['custom_script'][0]['description'] = PLUGIN_GENERAL_CUSTOM_SCRIPT_DESCRIPTION; +$plugin_field['custom_script'][0]['title'] = PLUGIN_GENERAL_CUSTOM_SCRIPT_TITLE; + +$plugin_field['custom_script'][1]['type'] = 'select'; +$plugin_field['custom_script'][1]['name'] = 'custom_script_location'; +$plugin_field['custom_script'][1]['value'] = array('remote' => PLUGIN_GENERAL_CUSTOM_SCRIPT_SCRIPT_LOCATION_REMOTE, + 'local' => PLUGIN_GENERAL_CUSTOM_SCRIPT_SCRIPT_LOCATION_LOCAL); +$plugin_field['custom_script'][1]['attributes'] = ''; +$plugin_field['custom_script'][1]['description'] = PLUGIN_GENERAL_CUSTOM_SCRIPT_SCRIPT_LOCATION_DESCRIPTION; + +$plugin_field['custom_script'][2]['type'] = 'text'; +$plugin_field['custom_script'][2]['name'] = 'custom_script_path'; +$plugin_field['custom_script'][2]['value'] = ''; +$plugin_field['custom_script'][2]['attributes'] = 'disabled size=70'; +$plugin_field['custom_script'][2]['description'] = PLUGIN_GENERAL_CUSTOM_SCRIPT_PATH_DESCRIPTION; +$plugin_field['custom_script'][2]['num_rules'] = '1'; +$plugin_field['custom_script'][2]['rule_msg'][0] = PLUGIN_GENERAL_CUSTOM_SCRIPT_RULE_1_0; +$plugin_field['custom_script'][2]['rule_type'][0] = 'required'; +$plugin_field['custom_script'][2]['rule_attribute'][0] = ''; + +$plugin_field['custom_script'][3]['type'] = 'text'; +$plugin_field['custom_script'][3]['name'] = 'custom_script_user'; +$plugin_field['custom_script'][3]['value'] = ''; +$plugin_field['custom_script'][3]['attributes'] = 'disabled'; +$plugin_field['custom_script'][3]['description'] = PLUGIN_USER; +$plugin_field['custom_script'][3]['num_rules'] = '1'; +$plugin_field['custom_script'][3]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['custom_script'][3]['rule_type'][0] = 'required'; +$plugin_field['custom_script'][3]['rule_attribute'][0] = ''; + +$plugin_field['custom_script'][4]['type'] = 'text'; +$plugin_field['custom_script'][4]['name'] = 'custom_script_port'; +$plugin_field['custom_script'][4]['value'] = ''; +$plugin_field['custom_script'][4]['attributes'] = 'disabled'; +$plugin_field['custom_script'][4]['description'] = PLUGIN_PORT; + +$plugin_field['custom_script'][5]['type'] = 'text'; +$plugin_field['custom_script'][5]['name'] = 'custom_script_retention'; +$plugin_field['custom_script'][5]['value'] = ''; +$plugin_field['custom_script'][5]['attributes'] = 'disabled'; +$plugin_field['custom_script'][5]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/general/custom_script/core.php b/plugins/general/custom_script/core.php new file mode 100644 index 0000000..56bb8d5 --- /dev/null +++ b/plugins/general/custom_script/core.php @@ -0,0 +1,105 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, + ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', + 'Executing job ' . $plugin_name . ' with id=' . $id_job); + + $result = 0; + + $bg_execution = false; + $local = false; + + //Get the params required by plugin from argv + + $path_script = $parameters['custom_script_path']; + $user = $parameters['custom_script_user']; + $port = $parameters['custom_script_port']; + + if ($parameters['custom_script_location'] == 'local') { + $local = true; + } + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $path_script, $local); + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + if ($exit_code == '0') { + $result = '1'; + } else { + $loggerPlugin->trace('ERROR', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + $result = '0'; + } + + $msg_exec = $attachments['txt']; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['custom_script_retention']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> diff --git a/plugins/general/spreadsheet_to_db/CHANGELOG b/plugins/general/spreadsheet_to_db/CHANGELOG new file mode 100644 index 0000000..c7bc8ab --- /dev/null +++ b/plugins/general/spreadsheet_to_db/CHANGELOG @@ -0,0 +1,16 @@ +1.0.3 (2007.11.19) +------------------ +Use init.inc.php + +1.0.2 (2007.10.30) +------------------ +Added capability to escape or remove quotes in a cell field. + +1.0.1 (2007.10.22) +------------------ +Removed http download for spreadsheet, please create a task and use HTTP Download File plugin if you need to download via http. +Added quote for the db identifiers + +1.0.0 (2007.09.28) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/general/spreadsheet_to_db/COPYRIGHT b/plugins/general/spreadsheet_to_db/COPYRIGHT new file mode 100644 index 0000000..0420c2f --- /dev/null +++ b/plugins/general/spreadsheet_to_db/COPYRIGHT @@ -0,0 +1,25 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +phpExcelReader +============== +Copyright: http://sourceforge.net/projects/phpexcelreader/ +License: LGPL \ No newline at end of file diff --git a/plugins/general/spreadsheet_to_db/LICENSE b/plugins/general/spreadsheet_to_db/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/general/spreadsheet_to_db/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/general/spreadsheet_to_db/configure.php b/plugins/general/spreadsheet_to_db/configure.php new file mode 100644 index 0000000..6b59bdf --- /dev/null +++ b/plugins/general/spreadsheet_to_db/configure.php @@ -0,0 +1,86 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['spreadsheet_to_db'][0]['version'] = '1.0.3'; +$plugin_field['spreadsheet_to_db'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['spreadsheet_to_db'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['spreadsheet_to_db'][0]['description'] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_DESCRIPTION; +$plugin_field['spreadsheet_to_db'][0]['title'] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_TITLE; + +$plugin_field['spreadsheet_to_db'][1]['type'] = 'text'; +$plugin_field['spreadsheet_to_db'][1]['name'] = 'db_spreadsheet_to_db_identity'; +$plugin_field['spreadsheet_to_db'][1]['value'] = ''; +$plugin_field['spreadsheet_to_db'][1]['attributes'] = 'disabled readonly'; +$plugin_field['spreadsheet_to_db'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['spreadsheet_to_db'][1]['num_rules'] = '1'; +$plugin_field['spreadsheet_to_db'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['spreadsheet_to_db'][1]['rule_type'][0] = 'required'; +$plugin_field['spreadsheet_to_db'][1]['rule_attribute'][0] = ''; + +$plugin_field['spreadsheet_to_db'][2]['type'] = 'text'; +$plugin_field['spreadsheet_to_db'][2]['name'] = 'db_spreadsheet_to_db_table_name'; +$plugin_field['spreadsheet_to_db'][2]['value'] = ''; +$plugin_field['spreadsheet_to_db'][2]['attributes'] = 'disabled'; +$plugin_field['spreadsheet_to_db'][2]['description'] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_TABLE_NAME_DESCRIPTION ; +$plugin_field['spreadsheet_to_db'][2]['num_rules'] = '1'; +$plugin_field['spreadsheet_to_db'][2]['rule_msg'][0] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_RULE_2_0; +$plugin_field['spreadsheet_to_db'][2]['rule_type'][0] = 'required'; +$plugin_field['spreadsheet_to_db'][2]['rule_attribute'][0] = ''; + +$plugin_field['spreadsheet_to_db'][3]['type'] = 'textarea'; +$plugin_field['spreadsheet_to_db'][3]['name'] = 'db_spreadsheet_to_db_table_definition'; +$plugin_field['spreadsheet_to_db'][3]['value'] = ' + column_1 + integer + + 1 + + + column_2 + text + 30 + 1 + '; + +$plugin_field['spreadsheet_to_db'][3]['attributes'] = 'disabled rows=30 cols=80'; +$plugin_field['spreadsheet_to_db'][3]['description'] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_TABLE_DEFINITION_DESCRIPTION ; +$plugin_field['spreadsheet_to_db'][3]['num_rules'] = '1'; +$plugin_field['spreadsheet_to_db'][3]['rule_msg'][0] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_RULE_3_0; +$plugin_field['spreadsheet_to_db'][3]['rule_type'][0] = 'required'; +$plugin_field['spreadsheet_to_db'][3]['rule_attribute'][0] = ''; + +$plugin_field['spreadsheet_to_db'][4]['type'] = 'text'; +$plugin_field['spreadsheet_to_db'][4]['name'] = 'db_spreadsheet_to_db_spreadsheet_filename'; +$plugin_field['spreadsheet_to_db'][4]['value'] = ''; +$plugin_field['spreadsheet_to_db'][4]['attributes'] = 'disabled size=50'; +$plugin_field['spreadsheet_to_db'][4]['description'] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_SPREADSHEET_PATH_DESCRIPTION; +$plugin_field['spreadsheet_to_db'][4]['num_rules'] = '1'; +$plugin_field['spreadsheet_to_db'][4]['rule_msg'][0] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_RULE_4_0; +$plugin_field['spreadsheet_to_db'][4]['rule_type'][0] = 'required'; +$plugin_field['spreadsheet_to_db'][4]['rule_attribute'][0] = ''; + +$plugin_field['spreadsheet_to_db'][5]['type'] = 'select'; +$plugin_field['spreadsheet_to_db'][5]['name'] = 'febo_spreadsheet_to_db_field_with_quote'; +$plugin_field['spreadsheet_to_db'][5]['value'] = array('escape' => PLUGIN_GENERAL_SPREADSHEET_TO_DB_FIELD_WITH_QUOTE_VALUE_1, + 'remove' => PLUGIN_GENERAL_SPREADSHEET_TO_DB_FIELD_WITH_QUOTE_VALUE_2); +$plugin_field['spreadsheet_to_db'][5]['attributes'] = ''; +$plugin_field['spreadsheet_to_db'][5]['description'] = PLUGIN_GENERAL_SPREADSHEET_TO_DB_FIELD_WITH_QUOTE_DESCRIPTION; +$plugin_field['spreadsheet_to_db'][5]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/general/spreadsheet_to_db/core.php b/plugins/general/spreadsheet_to_db/core.php new file mode 100644 index 0000000..b3f7f9d --- /dev/null +++ b/plugins/general/spreadsheet_to_db/core.php @@ -0,0 +1,211 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +set_include_path(realpath(dirname($argv[0])) . "/lib/:".ini_get("include_path")); +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + include_once 'dbUtil.php'; + include_once 'Pear/MDB2/Schema.php'; + + $loggerPlugin = new LogUtil($plugin_name, + ORTRO_LOG_PLUGINS . $plugin_name); + $log_prefix = '[job: ' . $id_job . '] '; + $loggerPlugin->trace('INFO', $log_prefix . 'Executing job'); + + $result = 0; + + //---- Start plugin code ----- + + //Get the params required by plugin from argv + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $id_system = $job_infos['id_system']; + + $query = $parameters['db_custom_query_query']; + $table_name = $parameters['db_spreadsheet_to_db_table_name']; + $table_definition = ' + db_name + table_name + ' . + $parameters['db_spreadsheet_to_db_table_definition'] . + ' +
+
'; + + $spreadsheet_filename = $parameters['db_spreadsheet_to_db_spreadsheet_filename']; + + if ($parameters['febo_spreadsheet_to_db_field_with_quote'] == 'escape') { + $replace_quote_with = "\'"; + } else { + $replace_quote_with = ''; + } + + $ip = $job_infos['ip']; + $dbms = $job_infos['dbms']; + $sid = $job_infos['sid']; + $port = $job_infos['port']; + + //Generate the xml database schema file + $path = dirname($argv[0]); + $temp_file_prefix = $path . DS . $id_job . time() . rand(); + $temp_file_xml = $temp_file_prefix . '.xml'; + + try { + + //Generate the database schema file + $fh = fopen($temp_file_xml, 'w+'); + fwrite($fh, $table_definition); + fclose($fh); + + //check for existing file + $spreadsheet_full_path = ORTRO_INCOMING . $id_system . DS . + $spreadsheet_filename; + if (!file_exists($spreadsheet_full_path)) { + $error_msg = 'The file "' . + $spreadsheet_full_path . + '" does not exist...'; + throw new Exception($error_msg); + } + $loggerPlugin->trace('DEBUG', $log_prefix . + 'File found: ' . + $spreadsheet_full_path . + ' ...'); + + $dbUtil = new DbUtil(); + $dbh = $dbUtil->dbOpenConn($dbms, $ip, $port, $sid, $user, $pwd); + + $query_drop_if_exists_table = 'drop table ' . $table_name; + + $loggerPlugin->trace('DEBUG', $log_prefix . + 'Trying to drop table ' . + $table_name . ' ...'); + $result = $dbh->exec($query_drop_if_exists_table); + + if (PEAR::isError($result)) { + $loggerPlugin->trace('DEBUG', $log_prefix . + 'Table ' . + $table_name . + ' does not exist continue...'); + } else { + $loggerPlugin->trace('DEBUG', $log_prefix . + 'Table ' . + $table_name . + ' dropped...'); + } + + $options = array('quote_identifier' => true); + $schema =& MDB2_Schema::factory($dbUtil->getDSN(), $options); + if (PEAR::isError($schema)) { + $loggerPlugin->trace('ERROR', $log_prefix . + $schema->getMessage() . '\n' . + $schema->getDebugInfo()); + } + + $variables = array('db_name'=> $sid, 'table_name'=> $table_name); + + $result = $schema->updateDatabase($temp_file_xml, false, $variables); + if (PEAR::isError($result)) { + $loggerPlugin->trace('ERROR', $log_prefix . + $result->getMessage() . '\n' . + $result->getDebugInfo()); + } else { + $loggerPlugin->trace('DEBUG', $log_prefix . + 'Table ' . + $table_name . + ' created...'); + } + //remove xml schema + @unlink($temp_file_xml); + + include_once 'Excel/reader.php'; + // ExcelFile($filename, $encoding); + $data = new Spreadsheet_Excel_Reader(); + // Set output Encoding. + $data->setOutputEncoding('CP1251'); + $data->read($spreadsheet_full_path); + + $rows = $data->sheets[0]['numRows']; + $cols = $data->sheets[0]['numCols']; + $cells = $data->sheets[0]['cells']; + $loggerPlugin->trace('DEBUG', $log_prefix . + 'rows: ' . + $rows . + ' cols: ' . + $cols); + for ($i = 1; $i <= $rows; $i++) { + $line = ''; + for ($j = 1; $j < $cols; $j++) { + $line .= str_replace("'", + $replace_quote_with, + $cells[$i][$j]) . '","'; + } + $query_insert_row = 'insert into ' . + $table_name . + ' values("' . $line . '")'; + $dbUtil->dbExec($dbh, $query_insert_row); + } + + $dbh = $dbUtil->dbCloseConn($dbh); + unset($dbh); + $result = 1; + + $msg_exec = 'OK'; + } catch (Exception $e) { + $result = 0; + $msg_exec = $e->getMessage(); + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); + } + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/general/spreadsheet_to_db/lib/Excel/oleread.inc b/plugins/general/spreadsheet_to_db/lib/Excel/oleread.inc new file mode 100644 index 0000000..c7241aa --- /dev/null +++ b/plugins/general/spreadsheet_to_db/lib/Excel/oleread.inc @@ -0,0 +1,271 @@ +=4294967294) + { + $value=-2; + } + return $value; +} + + +class OLERead { + var $data = ''; + + + function OLERead(){ + + + } + + function read($sFileName){ + + // check if file exist and is readable (Darko Miljanovic) + if(!is_readable($sFileName)) { + $this->error = 1; + return false; + } + + $this->data = @file_get_contents($sFileName); + if (!$this->data) { + $this->error = 1; + return false; + } + //echo IDENTIFIER_OLE; + //echo 'start'; + if (substr($this->data, 0, 8) != IDENTIFIER_OLE) { + $this->error = 1; + return false; + } + $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); + $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS); + $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS); + $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS); + $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS); + + /* + echo $this->numBigBlockDepotBlocks." "; + echo $this->sbdStartBlock." "; + echo $this->rootStartBlock." "; + echo $this->extensionBlock." "; + echo $this->numExtensionBlocks." "; + */ + //echo "sbdStartBlock = $this->sbdStartBlock\n"; + $bigBlockDepotBlocks = array(); + $pos = BIG_BLOCK_DEPOT_BLOCKS_POS; + // echo "pos = $pos"; + $bbdBlocks = $this->numBigBlockDepotBlocks; + + if ($this->numExtensionBlocks != 0) { + $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; + } + + for ($i = 0; $i < $bbdBlocks; $i++) { + $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); + $pos += 4; + } + + + for ($j = 0; $j < $this->numExtensionBlocks; $j++) { + $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE; + $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1); + + for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) { + $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); + $pos += 4; + } + + $bbdBlocks += $blocksToRead; + if ($bbdBlocks < $this->numBigBlockDepotBlocks) { + $this->extensionBlock = GetInt4d($this->data, $pos); + } + } + + // var_dump($bigBlockDepotBlocks); + + // readBigBlockDepot + $pos = 0; + $index = 0; + $this->bigBlockChain = array(); + + for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) { + $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE; + //echo "pos = $pos"; + for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) { + $this->bigBlockChain[$index] = GetInt4d($this->data, $pos); + $pos += 4 ; + $index++; + } + } + + //var_dump($this->bigBlockChain); + //echo '=====2'; + // readSmallBlockDepot(); + $pos = 0; + $index = 0; + $sbdBlock = $this->sbdStartBlock; + $this->smallBlockChain = array(); + + while ($sbdBlock != -2) { + + $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE; + + for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) { + $this->smallBlockChain[$index] = GetInt4d($this->data, $pos); + $pos += 4; + $index++; + } + + $sbdBlock = $this->bigBlockChain[$sbdBlock]; + } + + + // readData(rootStartBlock) + $block = $this->rootStartBlock; + $pos = 0; + $this->entry = $this->__readData($block); + + /* + while ($block != -2) { + $pos = ($block + 1) * BIG_BLOCK_SIZE; + $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE); + $block = $this->bigBlockChain[$block]; + } + */ + //echo '==='.$this->entry."==="; + $this->__readPropertySets(); + + } + + function __readData($bl) { + $block = $bl; + $pos = 0; + $data = ''; + + while ($block != -2) { + $pos = ($block + 1) * BIG_BLOCK_SIZE; + $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE); + //echo "pos = $pos data=$data\n"; + $block = $this->bigBlockChain[$block]; + } + return $data; + } + + function __readPropertySets(){ + $offset = 0; + //var_dump($this->entry); + while ($offset < strlen($this->entry)) { + $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE); + + $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8); + + $type = ord($d[TYPE_POS]); + //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1; + + $startBlock = GetInt4d($d, START_BLOCK_POS); + $size = GetInt4d($d, SIZE_POS); + + $name = ''; + for ($i = 0; $i < $nameSize ; $i++) { + $name .= $d[$i]; + } + + $name = str_replace("\x00", "", $name); + + $this->props[] = array ( + 'name' => $name, + 'type' => $type, + 'startBlock' => $startBlock, + 'size' => $size); + + if (($name == "Workbook") || ($name == "Book")) { + $this->wrkbook = count($this->props) - 1; + } + + if ($name == "Root Entry") { + $this->rootentry = count($this->props) - 1; + } + + //echo "name ==$name=\n"; + + + $offset += PROPERTY_STORAGE_BLOCK_SIZE; + } + + } + + + function getWorkBook(){ + if ($this->props[$this->wrkbook]['size'] < SMALL_BLOCK_THRESHOLD){ +// getSmallBlockStream(PropertyStorage ps) + + $rootdata = $this->__readData($this->props[$this->rootentry]['startBlock']); + + $streamData = ''; + $block = $this->props[$this->wrkbook]['startBlock']; + //$count = 0; + $pos = 0; + while ($block != -2) { + $pos = $block * SMALL_BLOCK_SIZE; + $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE); + + $block = $this->smallBlockChain[$block]; + } + + return $streamData; + + + }else{ + + $numBlocks = $this->props[$this->wrkbook]['size'] / BIG_BLOCK_SIZE; + if ($this->props[$this->wrkbook]['size'] % BIG_BLOCK_SIZE != 0) { + $numBlocks++; + } + + if ($numBlocks == 0) return ''; + + //echo "numBlocks = $numBlocks\n"; + //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE]; + //print_r($this->wrkbook); + $streamData = ''; + $block = $this->props[$this->wrkbook]['startBlock']; + //$count = 0; + $pos = 0; + //echo "block = $block"; + while ($block != -2) { + $pos = ($block + 1) * BIG_BLOCK_SIZE; + $streamData .= substr($this->data, $pos, BIG_BLOCK_SIZE); + $block = $this->bigBlockChain[$block]; + } + //echo 'stream'.$streamData; + return $streamData; + } + } + +} +?> \ No newline at end of file diff --git a/plugins/general/spreadsheet_to_db/lib/Excel/reader.php b/plugins/general/spreadsheet_to_db/lib/Excel/reader.php new file mode 100644 index 0000000..b2b1a5b --- /dev/null +++ b/plugins/general/spreadsheet_to_db/lib/Excel/reader.php @@ -0,0 +1,1082 @@ + +* @license http://www.php.net/license/3_0.txt PHP License 3.0 +* @version CVS: $Id: reader.php 19 2007-03-13 12:42:41Z shangxiao $ +* @link http://pear.php.net/package/Spreadsheet_Excel_Reader +* @see OLE, Spreadsheet_Excel_Writer +*/ + + +require_once 'oleread.inc'; + +define('SPREADSHEET_EXCEL_READER_BIFF8', 0x600); +define('SPREADSHEET_EXCEL_READER_BIFF7', 0x500); +define('SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS', 0x5); +define('SPREADSHEET_EXCEL_READER_WORKSHEET', 0x10); + +define('SPREADSHEET_EXCEL_READER_TYPE_BOF', 0x809); +define('SPREADSHEET_EXCEL_READER_TYPE_EOF', 0x0a); +define('SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET', 0x85); +define('SPREADSHEET_EXCEL_READER_TYPE_DIMENSION', 0x200); +define('SPREADSHEET_EXCEL_READER_TYPE_ROW', 0x208); +define('SPREADSHEET_EXCEL_READER_TYPE_DBCELL', 0xd7); +define('SPREADSHEET_EXCEL_READER_TYPE_FILEPASS', 0x2f); +define('SPREADSHEET_EXCEL_READER_TYPE_NOTE', 0x1c); +define('SPREADSHEET_EXCEL_READER_TYPE_TXO', 0x1b6); +define('SPREADSHEET_EXCEL_READER_TYPE_RK', 0x7e); +define('SPREADSHEET_EXCEL_READER_TYPE_RK2', 0x27e); +define('SPREADSHEET_EXCEL_READER_TYPE_MULRK', 0xbd); +define('SPREADSHEET_EXCEL_READER_TYPE_MULBLANK', 0xbe); +define('SPREADSHEET_EXCEL_READER_TYPE_INDEX', 0x20b); +define('SPREADSHEET_EXCEL_READER_TYPE_SST', 0xfc); +define('SPREADSHEET_EXCEL_READER_TYPE_EXTSST', 0xff); +define('SPREADSHEET_EXCEL_READER_TYPE_CONTINUE', 0x3c); +define('SPREADSHEET_EXCEL_READER_TYPE_LABEL', 0x204); +define('SPREADSHEET_EXCEL_READER_TYPE_LABELSST', 0xfd); +define('SPREADSHEET_EXCEL_READER_TYPE_NUMBER', 0x203); +define('SPREADSHEET_EXCEL_READER_TYPE_NAME', 0x18); +define('SPREADSHEET_EXCEL_READER_TYPE_ARRAY', 0x221); +define('SPREADSHEET_EXCEL_READER_TYPE_STRING', 0x207); +define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA', 0x406); +define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA2', 0x6); +define('SPREADSHEET_EXCEL_READER_TYPE_FORMAT', 0x41e); +define('SPREADSHEET_EXCEL_READER_TYPE_XF', 0xe0); +define('SPREADSHEET_EXCEL_READER_TYPE_BOOLERR', 0x205); +define('SPREADSHEET_EXCEL_READER_TYPE_UNKNOWN', 0xffff); +define('SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR', 0x22); +define('SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS', 0xE5); + +define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS' , 25569); +define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904', 24107); +define('SPREADSHEET_EXCEL_READER_MSINADAY', 86400); +//define('SPREADSHEET_EXCEL_READER_MSINADAY', 24 * 60 * 60); + +//define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%.2f"); +define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%s"); + + +/* +* Place includes, constant defines and $_GLOBAL settings here. +* Make sure they have appropriate docblocks to avoid phpDocumentor +* construing they are documented by the page-level docblock. +*/ + +/** +* A class for reading Microsoft Excel Spreadsheets. +* +* Originally developed by Vadim Tkachenko under the name PHPExcelReader. +* (http://sourceforge.net/projects/phpexcelreader) +* Based on the Java version by Andy Khan (http://www.andykhan.com). Now +* maintained by David Sanders. Reads only Biff 7 and Biff 8 formats. +* +* @category Spreadsheet +* @package Spreadsheet_Excel_Reader +* @author Vadim Tkachenko +* @copyright 1997-2005 The PHP Group +* @license http://www.php.net/license/3_0.txt PHP License 3.0 +* @version Release: @package_version@ +* @link http://pear.php.net/package/PackageName +* @see OLE, Spreadsheet_Excel_Writer +*/ +class Spreadsheet_Excel_Reader +{ + /** + * Array of worksheets found + * + * @var array + * @access public + */ + var $boundsheets = array(); + + /** + * Array of format records found + * + * @var array + * @access public + */ + var $formatRecords = array(); + + /** + * todo + * + * @var array + * @access public + */ + var $sst = array(); + + /** + * Array of worksheets + * + * The data is stored in 'cells' and the meta-data is stored in an array + * called 'cellsInfo' + * + * Example: + * + * $sheets --> 'cells' --> row --> column --> Interpreted value + * --> 'cellsInfo' --> row --> column --> 'type' - Can be 'date', 'number', or 'unknown' + * --> 'raw' - The raw data that Excel stores for that data cell + * + * @var array + * @access public + */ + var $sheets = array(); + + /** + * The data returned by OLE + * + * @var string + * @access public + */ + var $data; + + /** + * OLE object for reading the file + * + * @var OLE object + * @access private + */ + var $_ole; + + /** + * Default encoding + * + * @var string + * @access private + */ + var $_defaultEncoding; + + /** + * Default number format + * + * @var integer + * @access private + */ + var $_defaultFormat = SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT; + + /** + * todo + * List of formats to use for each column + * + * @var array + * @access private + */ + var $_columnsFormat = array(); + + /** + * todo + * + * @var integer + * @access private + */ + var $_rowoffset = 1; + + /** + * todo + * + * @var integer + * @access private + */ + var $_coloffset = 1; + + /** + * List of default date formats used by Excel + * + * @var array + * @access public + */ + var $dateFormats = array ( + 0xe => "d/m/Y", + 0xf => "d-M-Y", + 0x10 => "d-M", + 0x11 => "M-Y", + 0x12 => "h:i a", + 0x13 => "h:i:s a", + 0x14 => "H:i", + 0x15 => "H:i:s", + 0x16 => "d/m/Y H:i", + 0x2d => "i:s", + 0x2e => "H:i:s", + 0x2f => "i:s.S"); + + /** + * Default number formats used by Excel + * + * @var array + * @access public + */ + var $numberFormats = array( + 0x1 => "%1.0f", // "0" + 0x2 => "%1.2f", // "0.00", + 0x3 => "%1.0f", //"#,##0", + 0x4 => "%1.2f", //"#,##0.00", + 0x5 => "%1.0f", /*"$#,##0;($#,##0)",*/ + 0x6 => '$%1.0f', /*"$#,##0;($#,##0)",*/ + 0x7 => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x8 => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x9 => '%1.0f%%', // "0%" + 0xa => '%1.2f%%', // "0.00%" + 0xb => '%1.2f', // 0.00E00", + 0x25 => '%1.0f', // "#,##0;(#,##0)", + 0x26 => '%1.0f', //"#,##0;(#,##0)", + 0x27 => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x28 => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x29 => '%1.0f', //"#,##0;(#,##0)", + 0x2a => '$%1.0f', //"$#,##0;($#,##0)", + 0x2b => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x2c => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x30 => '%1.0f'); //"##0.0E0"; + + // }}} + // {{{ Spreadsheet_Excel_Reader() + + /** + * Constructor + * + * Some basic initialisation + */ + function Spreadsheet_Excel_Reader() + { + $this->_ole =& new OLERead(); + $this->setUTFEncoder('iconv'); + } + + // }}} + // {{{ setOutputEncoding() + + /** + * Set the encoding method + * + * @param string Encoding to use + * @access public + */ + function setOutputEncoding($encoding) + { + $this->_defaultEncoding = $encoding; + } + + // }}} + // {{{ setUTFEncoder() + + /** + * $encoder = 'iconv' or 'mb' + * set iconv if you would like use 'iconv' for encode UTF-16LE to your encoding + * set mb if you would like use 'mb_convert_encoding' for encode UTF-16LE to your encoding + * + * @access public + * @param string Encoding type to use. Either 'iconv' or 'mb' + */ + function setUTFEncoder($encoder = 'iconv') + { + $this->_encoderFunction = ''; + + if ($encoder == 'iconv') { + $this->_encoderFunction = function_exists('iconv') ? 'iconv' : ''; + } elseif ($encoder == 'mb') { + $this->_encoderFunction = function_exists('mb_convert_encoding') ? + 'mb_convert_encoding' : + ''; + } + } + + // }}} + // {{{ setRowColOffset() + + /** + * todo + * + * @access public + * @param offset + */ + function setRowColOffset($iOffset) + { + $this->_rowoffset = $iOffset; + $this->_coloffset = $iOffset; + } + + // }}} + // {{{ setDefaultFormat() + + /** + * Set the default number format + * + * @access public + * @param Default format + */ + function setDefaultFormat($sFormat) + { + $this->_defaultFormat = $sFormat; + } + + // }}} + // {{{ setColumnFormat() + + /** + * Force a column to use a certain format + * + * @access public + * @param integer Column number + * @param string Format + */ + function setColumnFormat($column, $sFormat) + { + $this->_columnsFormat[$column] = $sFormat; + } + + + // }}} + // {{{ read() + + /** + * Read the spreadsheet file using OLE, then parse + * + * @access public + * @param filename + * @todo return a valid value + */ + function read($sFileName) + { + /* + require_once 'OLE.php'; + $ole = new OLE(); + $ole->read($sFileName); + + foreach ($ole->_list as $i => $pps) { + if (($pps->Name == 'Workbook' || $pps->Name == 'Book') && + $pps->Size >= SMALL_BLOCK_THRESHOLD) { + + $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); + } elseif ($pps->Name == 'Root Entry') { + $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); + } + //var_dump(strlen($ole->getData($i, 0, $ole->getDataLength($i))), $pps->Name, md5($this->data), $ole->getDataLength($i)); + } +//exit; + $this->_parse(); + + return sizeof($this->sheets) > 0; + */ + + $res = $this->_ole->read($sFileName); + + // oops, something goes wrong (Darko Miljanovic) + if($res === false) { + // check error code + if($this->_ole->error == 1) { + // bad file + die('The filename ' . $sFileName . ' is not readable'); + } + // check other error codes here (eg bad fileformat, etc...) + } + + $this->data = $this->_ole->getWorkBook(); + + + /* + $res = $this->_ole->read($sFileName); + + if ($this->isError($res)) { +// var_dump($res); + return $this->raiseError($res); + } + + $total = $this->_ole->ppsTotal(); + for ($i = 0; $i < $total; $i++) { + if ($this->_ole->isFile($i)) { + $type = unpack("v", $this->_ole->getData($i, 0, 2)); + if ($type[''] == 0x0809) { // check if it's a BIFF stream + $this->_index = $i; + $this->data = $this->_ole->getData($i, 0, $this->_ole->getDataLength($i)); + break; + } + } + } + + if ($this->_index === null) { + return $this->raiseError("$file doesn't seem to be an Excel file"); + } + + */ + + //echo "data =".$this->data; + //$this->readRecords(); + $this->_parse(); + } + + + // }}} + // {{{ _parse() + + /** + * Parse a workbook + * + * @access private + * @return bool + */ + function _parse() + { + $pos = 0; + + $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; + $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; + + $version = ord($this->data[$pos + 4]) | ord($this->data[$pos + 5])<<8; + $substreamType = ord($this->data[$pos + 6]) | ord($this->data[$pos + 7])<<8; + //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; + + if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && + ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { + return false; + } + + if ($substreamType != SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS){ + return false; + } + + //print_r($rec); + $pos += $length + 4; + + $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; + $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; + + while ($code != SPREADSHEET_EXCEL_READER_TYPE_EOF) { + switch ($code) { + case SPREADSHEET_EXCEL_READER_TYPE_SST: + //echo "Type_SST\n"; + $spos = $pos + 4; + $limitpos = $spos + $length; + $uniqueStrings = $this->_GetInt4d($this->data, $spos+4); + $spos += 8; + for ($i = 0; $i < $uniqueStrings; $i++) { + // Read in the number of characters + if ($spos == $limitpos) { + $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + if ($opcode != 0x3c) { + return -1; + } + $spos += 4; + $limitpos = $spos + $conlength; + } + $numChars = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); + //echo "i = $i pos = $pos numChars = $numChars "; + $spos += 2; + $optionFlags = ord($this->data[$spos]); + $spos++; + $asciiEncoding = (($optionFlags & 0x01) == 0) ; + $extendedString = ( ($optionFlags & 0x04) != 0); + + // See if string contains formatting information + $richString = ( ($optionFlags & 0x08) != 0); + + if ($richString) { + // Read in the crun + $formattingRuns = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); + $spos += 2; + } + + if ($extendedString) { + // Read in cchExtRst + $extendedRunLength = $this->_GetInt4d($this->data, $spos); + $spos += 4; + } + + $len = ($asciiEncoding)? $numChars : $numChars*2; + if ($spos + $len < $limitpos) { + $retstr = substr($this->data, $spos, $len); + $spos += $len; + }else{ + // found countinue + $retstr = substr($this->data, $spos, $limitpos - $spos); + $bytesRead = $limitpos - $spos; + $charsLeft = $numChars - (($asciiEncoding) ? $bytesRead : ($bytesRead / 2)); + $spos = $limitpos; + + while ($charsLeft > 0){ + $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + if ($opcode != 0x3c) { + return -1; + } + $spos += 4; + $limitpos = $spos + $conlength; + $option = ord($this->data[$spos]); + $spos += 1; + if ($asciiEncoding && ($option == 0)) { + $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); + $retstr .= substr($this->data, $spos, $len); + $charsLeft -= $len; + $asciiEncoding = true; + }elseif (!$asciiEncoding && ($option != 0)){ + $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); + $retstr .= substr($this->data, $spos, $len); + $charsLeft -= $len/2; + $asciiEncoding = false; + }elseif (!$asciiEncoding && ($option == 0)) { + // Bummer - the string starts off as Unicode, but after the + // continuation it is in straightforward ASCII encoding + $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); + for ($j = 0; $j < $len; $j++) { + $retstr .= $this->data[$spos + $j].chr(0); + } + $charsLeft -= $len; + $asciiEncoding = false; + }else{ + $newstr = ''; + for ($j = 0; $j < strlen($retstr); $j++) { + $newstr = $retstr[$j].chr(0); + } + $retstr = $newstr; + $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); + $retstr .= substr($this->data, $spos, $len); + $charsLeft -= $len/2; + $asciiEncoding = false; + //echo "Izavrat\n"; + } + $spos += $len; + + } + } + $retstr = ($asciiEncoding) ? $retstr : $this->_encodeUTF16($retstr); +// echo "Str $i = $retstr\n"; + if ($richString){ + $spos += 4 * $formattingRuns; + } + + // For extended strings, skip over the extended string data + if ($extendedString) { + $spos += $extendedRunLength; + } + //if ($retstr == 'Derby'){ + // echo "bb\n"; + //} + $this->sst[]=$retstr; + } + /*$continueRecords = array(); + while ($this->getNextCode() == Type_CONTINUE) { + $continueRecords[] = &$this->nextRecord(); + } + //echo " 1 Type_SST\n"; + $this->shareStrings = new SSTRecord($r, $continueRecords); + //print_r($this->shareStrings->strings); + */ + // echo 'SST read: '.($time_end-$time_start)."\n"; + break; + + case SPREADSHEET_EXCEL_READER_TYPE_FILEPASS: + return false; + break; + case SPREADSHEET_EXCEL_READER_TYPE_NAME: + //echo "Type_NAME\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_FORMAT: + $indexCode = ord($this->data[$pos+4]) | ord($this->data[$pos+5]) << 8; + + if ($version == SPREADSHEET_EXCEL_READER_BIFF8) { + $numchars = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; + if (ord($this->data[$pos+8]) == 0){ + $formatString = substr($this->data, $pos+9, $numchars); + } else { + $formatString = substr($this->data, $pos+9, $numchars*2); + } + } else { + $numchars = ord($this->data[$pos+6]); + $formatString = substr($this->data, $pos+7, $numchars*2); + } + + $this->formatRecords[$indexCode] = $formatString; + // echo "Type.FORMAT\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_XF: + //global $dateFormats, $numberFormats; + $indexCode = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; + //echo "\nType.XF ".count($this->formatRecords['xfrecords'])." $indexCode "; + if (array_key_exists($indexCode, $this->dateFormats)) { + //echo "isdate ".$dateFormats[$indexCode]; + $this->formatRecords['xfrecords'][] = array( + 'type' => 'date', + 'format' => $this->dateFormats[$indexCode] + ); + }elseif (array_key_exists($indexCode, $this->numberFormats)) { + //echo "isnumber ".$this->numberFormats[$indexCode]; + $this->formatRecords['xfrecords'][] = array( + 'type' => 'number', + 'format' => $this->numberFormats[$indexCode] + ); + }else{ + $isdate = FALSE; + if ($indexCode > 0){ + if (isset($this->formatRecords[$indexCode])) + $formatstr = $this->formatRecords[$indexCode]; + //echo '.other.'; + //echo "\ndate-time=$formatstr=\n"; + if ($formatstr) + if (preg_match("/[^hmsday\/\-:\s]/i", $formatstr) == 0) { // found day and time format + $isdate = TRUE; + $formatstr = str_replace('mm', 'i', $formatstr); + $formatstr = str_replace('h', 'H', $formatstr); + //echo "\ndate-time $formatstr \n"; + } + } + + if ($isdate){ + $this->formatRecords['xfrecords'][] = array( + 'type' => 'date', + 'format' => $formatstr, + ); + }else{ + $this->formatRecords['xfrecords'][] = array( + 'type' => 'other', + 'format' => '', + 'code' => $indexCode + ); + } + } + //echo "\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR: + //echo "Type.NINETEENFOUR\n"; + $this->nineteenFour = (ord($this->data[$pos+4]) == 1); + break; + case SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET: + //echo "Type.BOUNDSHEET\n"; + $rec_offset = $this->_GetInt4d($this->data, $pos+4); + $rec_typeFlag = ord($this->data[$pos+8]); + $rec_visibilityFlag = ord($this->data[$pos+9]); + $rec_length = ord($this->data[$pos+10]); + + if ($version == SPREADSHEET_EXCEL_READER_BIFF8){ + $chartype = ord($this->data[$pos+11]); + if ($chartype == 0){ + $rec_name = substr($this->data, $pos+12, $rec_length); + } else { + $rec_name = $this->_encodeUTF16(substr($this->data, $pos+12, $rec_length*2)); + } + }elseif ($version == SPREADSHEET_EXCEL_READER_BIFF7){ + $rec_name = substr($this->data, $pos+11, $rec_length); + } + $this->boundsheets[] = array('name'=>$rec_name, + 'offset'=>$rec_offset); + + break; + + } + + //echo "Code = ".base_convert($r['code'],10,16)."\n"; + $pos += $length + 4; + $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; + $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; + + //$r = &$this->nextRecord(); + //echo "1 Code = ".base_convert($r['code'],10,16)."\n"; + } + + foreach ($this->boundsheets as $key=>$val){ + $this->sn = $key; + $this->_parsesheet($val['offset']); + } + return true; + + } + + /** + * Parse a worksheet + * + * @access private + * @param todo + * @todo fix return codes + */ + function _parsesheet($spos) + { + $cont = true; + // read BOF + $code = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + + $version = ord($this->data[$spos + 4]) | ord($this->data[$spos + 5])<<8; + $substreamType = ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8; + + if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { + return -1; + } + + if ($substreamType != SPREADSHEET_EXCEL_READER_WORKSHEET){ + return -2; + } + //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; + $spos += $length + 4; + //var_dump($this->formatRecords); + //echo "code $code $length"; + while($cont) { + //echo "mem= ".memory_get_usage()."\n"; +// $r = &$this->file->nextRecord(); + $lowcode = ord($this->data[$spos]); + if ($lowcode == SPREADSHEET_EXCEL_READER_TYPE_EOF) break; + $code = $lowcode | ord($this->data[$spos+1])<<8; + $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $spos += 4; + $this->sheets[$this->sn]['maxrow'] = $this->_rowoffset - 1; + $this->sheets[$this->sn]['maxcol'] = $this->_coloffset - 1; + //echo "Code=".base_convert($code,10,16)." $code\n"; + unset($this->rectype); + $this->multiplier = 1; // need for format with % + switch ($code) { + case SPREADSHEET_EXCEL_READER_TYPE_DIMENSION: + //echo 'Type_DIMENSION '; + if (!isset($this->numRows)) { + if (($length == 10) || ($version == SPREADSHEET_EXCEL_READER_BIFF7)){ + $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+2]) | ord($this->data[$spos+3]) << 8; + $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+6]) | ord($this->data[$spos+7]) << 8; + } else { + $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; + $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+10]) | ord($this->data[$spos+11]) << 8; + } + } + //echo 'numRows '.$this->numRows.' '.$this->numCols."\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS: + $cellRanges = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + for ($i = 0; $i < $cellRanges; $i++) { + $fr = ord($this->data[$spos + 8*$i + 2]) | ord($this->data[$spos + 8*$i + 3])<<8; + $lr = ord($this->data[$spos + 8*$i + 4]) | ord($this->data[$spos + 8*$i + 5])<<8; + $fc = ord($this->data[$spos + 8*$i + 6]) | ord($this->data[$spos + 8*$i + 7])<<8; + $lc = ord($this->data[$spos + 8*$i + 8]) | ord($this->data[$spos + 8*$i + 9])<<8; + //$this->sheets[$this->sn]['mergedCells'][] = array($fr + 1, $fc + 1, $lr + 1, $lc + 1); + if ($lr - $fr > 0) { + $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['rowspan'] = $lr - $fr + 1; + } + if ($lc - $fc > 0) { + $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['colspan'] = $lc - $fc + 1; + } + } + //echo "Merged Cells $cellRanges $lr $fr $lc $fc\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_RK: + case SPREADSHEET_EXCEL_READER_TYPE_RK2: + //echo 'SPREADSHEET_EXCEL_READER_TYPE_RK'."\n"; + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $rknum = $this->_GetInt4d($this->data, $spos + 6); + $numValue = $this->_GetIEEE754($rknum); + //echo $numValue." "; + if ($this->isDate($spos)) { + list($string, $raw) = $this->createDate($numValue); + }else{ + $raw = $numValue; + if (isset($this->_columnsFormat[$column + 1])){ + $this->curformat = $this->_columnsFormat[$column + 1]; + } + $string = sprintf($this->curformat, $numValue * $this->multiplier); + //$this->addcell(RKRecord($r)); + } + $this->addcell($row, $column, $string, $raw); + //echo "Type_RK $row $column $string $raw {$this->curformat}\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_LABELSST: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5])<<8; + $index = $this->_GetInt4d($this->data, $spos + 6); + //var_dump($this->sst); + $this->addcell($row, $column, $this->sst[$index]); + //echo "LabelSST $row $column $string\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_MULRK: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $colFirst = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $colLast = ord($this->data[$spos + $length - 2]) | ord($this->data[$spos + $length - 1])<<8; + $columns = $colLast - $colFirst + 1; + $tmppos = $spos+4; + for ($i = 0; $i < $columns; $i++) { + $numValue = $this->_GetIEEE754($this->_GetInt4d($this->data, $tmppos + 2)); + if ($this->isDate($tmppos-4)) { + list($string, $raw) = $this->createDate($numValue); + }else{ + $raw = $numValue; + if (isset($this->_columnsFormat[$colFirst + $i + 1])){ + $this->curformat = $this->_columnsFormat[$colFirst + $i + 1]; + } + $string = sprintf($this->curformat, $numValue * $this->multiplier); + } + //$rec['rknumbers'][$i]['xfindex'] = ord($rec['data'][$pos]) | ord($rec['data'][$pos+1]) << 8; + $tmppos += 6; + $this->addcell($row, $colFirst + $i, $string, $raw); + //echo "MULRK $row ".($colFirst + $i)." $string\n"; + } + //MulRKRecord($r); + // Get the individual cell records from the multiple record + //$num = ; + + break; + case SPREADSHEET_EXCEL_READER_TYPE_NUMBER: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent + if ($this->isDate($spos)) { + list($string, $raw) = $this->createDate($tmp['double']); + // $this->addcell(DateRecord($r, 1)); + }else{ + //$raw = $tmp['']; + if (isset($this->_columnsFormat[$column + 1])){ + $this->curformat = $this->_columnsFormat[$column + 1]; + } + $raw = $this->createNumber($spos); + $string = sprintf($this->curformat, $raw * $this->multiplier); + + // $this->addcell(NumberRecord($r)); + } + $this->addcell($row, $column, $string, $raw); + //echo "Number $row $column $string\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_FORMULA: + case SPREADSHEET_EXCEL_READER_TYPE_FORMULA2: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + if ((ord($this->data[$spos+6])==0) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //String formula. Result follows in a STRING record + //echo "FORMULA $row $column Formula with a string
\n"; + } elseif ((ord($this->data[$spos+6])==1) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //Boolean formula. Result is in +2; 0=false,1=true + } elseif ((ord($this->data[$spos+6])==2) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //Error formula. Error code is in +2; + } elseif ((ord($this->data[$spos+6])==3) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { + //Formula result is a null string. + } else { + // result is a number, so first 14 bytes are just like a _NUMBER record + $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent + if ($this->isDate($spos)) { + list($string, $raw) = $this->createDate($tmp['double']); + // $this->addcell(DateRecord($r, 1)); + }else{ + //$raw = $tmp['']; + if (isset($this->_columnsFormat[$column + 1])){ + $this->curformat = $this->_columnsFormat[$column + 1]; + } + $raw = $this->createNumber($spos); + $string = sprintf($this->curformat, $raw * $this->multiplier); + + // $this->addcell(NumberRecord($r)); + } + $this->addcell($row, $column, $string, $raw); + //echo "Number $row $column $string\n"; + } + break; + case SPREADSHEET_EXCEL_READER_TYPE_BOOLERR: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $string = ord($this->data[$spos+6]); + $this->addcell($row, $column, $string); + //echo 'Type_BOOLERR '."\n"; + break; + case SPREADSHEET_EXCEL_READER_TYPE_ROW: + case SPREADSHEET_EXCEL_READER_TYPE_DBCELL: + case SPREADSHEET_EXCEL_READER_TYPE_MULBLANK: + break; + case SPREADSHEET_EXCEL_READER_TYPE_LABEL: + $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; + $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; + $this->addcell($row, $column, substr($this->data, $spos + 8, ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8)); + + // $this->addcell(LabelRecord($r)); + break; + + case SPREADSHEET_EXCEL_READER_TYPE_EOF: + $cont = false; + break; + default: + //echo ' unknown :'.base_convert($r['code'],10,16)."\n"; + break; + + } + $spos += $length; + } + + if (!isset($this->sheets[$this->sn]['numRows'])) + $this->sheets[$this->sn]['numRows'] = $this->sheets[$this->sn]['maxrow']; + if (!isset($this->sheets[$this->sn]['numCols'])) + $this->sheets[$this->sn]['numCols'] = $this->sheets[$this->sn]['maxcol']; + + } + + /** + * Check whether the current record read is a date + * + * @param todo + * @return boolean True if date, false otherwise + */ + function isDate($spos) + { + //$xfindex = GetInt2d(, 4); + $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; + //echo 'check is date '.$xfindex.' '.$this->formatRecords['xfrecords'][$xfindex]['type']."\n"; + //var_dump($this->formatRecords['xfrecords'][$xfindex]); + if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'date') { + $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; + $this->rectype = 'date'; + return true; + } else { + if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'number') { + $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; + $this->rectype = 'number'; + if (($xfindex == 0x9) || ($xfindex == 0xa)){ + $this->multiplier = 100; + } + }else{ + $this->curformat = $this->_defaultFormat; + $this->rectype = 'unknown'; + } + return false; + } + } + + //}}} + //{{{ createDate() + + /** + * Convert the raw Excel date into a human readable format + * + * Dates in Excel are stored as number of seconds from an epoch. On + * Windows, the epoch is 30/12/1899 and on Mac it's 01/01/1904 + * + * @access private + * @param integer The raw Excel value to convert + * @return array First element is the converted date, the second element is number a unix timestamp + */ + function createDate($numValue) + { + if ($numValue > 1) { + $utcDays = $numValue - ($this->nineteenFour ? SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904 : SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS); + $utcValue = round(($utcDays+1) * SPREADSHEET_EXCEL_READER_MSINADAY); + $string = date ($this->curformat, $utcValue); + $raw = $utcValue; + } else { + $raw = $numValue; + $hours = floor($numValue * 24); + $mins = floor($numValue * 24 * 60) - $hours * 60; + $secs = floor($numValue * SPREADSHEET_EXCEL_READER_MSINADAY) - $hours * 60 * 60 - $mins * 60; + $string = date ($this->curformat, mktime($hours, $mins, $secs)); + } + + return array($string, $raw); + } + + function createNumber($spos) + { + $rknumhigh = $this->_GetInt4d($this->data, $spos + 10); + $rknumlow = $this->_GetInt4d($this->data, $spos + 6); + //for ($i=0; $i<8; $i++) { echo ord($this->data[$i+$spos+6]) . " "; } echo "
"; + $sign = ($rknumhigh & 0x80000000) >> 31; + $exp = ($rknumhigh & 0x7ff00000) >> 20; + $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); + $mantissalow1 = ($rknumlow & 0x80000000) >> 31; + $mantissalow2 = ($rknumlow & 0x7fffffff); + $value = $mantissa / pow( 2 , (20- ($exp - 1023))); + if ($mantissalow1 != 0) $value += 1 / pow (2 , (21 - ($exp - 1023))); + $value += $mantissalow2 / pow (2 , (52 - ($exp - 1023))); + //echo "Sign = $sign, Exp = $exp, mantissahighx = $mantissa, mantissalow1 = $mantissalow1, mantissalow2 = $mantissalow2
\n"; + if ($sign) {$value = -1 * $value;} + return $value; + } + + function addcell($row, $col, $string, $raw = '') + { + //echo "ADD cel $row-$col $string\n"; + $this->sheets[$this->sn]['maxrow'] = max($this->sheets[$this->sn]['maxrow'], $row + $this->_rowoffset); + $this->sheets[$this->sn]['maxcol'] = max($this->sheets[$this->sn]['maxcol'], $col + $this->_coloffset); + $this->sheets[$this->sn]['cells'][$row + $this->_rowoffset][$col + $this->_coloffset] = $string; + if ($raw) + $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['raw'] = $raw; + if (isset($this->rectype)) + $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['type'] = $this->rectype; + + } + + + function _GetIEEE754($rknum) + { + if (($rknum & 0x02) != 0) { + $value = $rknum >> 2; + } else { +//mmp +// first comment out the previously existing 7 lines of code here +// $tmp = unpack("d", pack("VV", 0, ($rknum & 0xfffffffc))); +// //$value = $tmp['']; +// if (array_key_exists(1, $tmp)) { +// $value = $tmp[1]; +// } else { +// $value = $tmp['']; +// } +// I got my info on IEEE754 encoding from +// http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html +// The RK format calls for using only the most significant 30 bits of the +// 64 bit floating point value. The other 34 bits are assumed to be 0 +// So, we use the upper 30 bits of $rknum as follows... + $sign = ($rknum & 0x80000000) >> 31; + $exp = ($rknum & 0x7ff00000) >> 20; + $mantissa = (0x100000 | ($rknum & 0x000ffffc)); + $value = $mantissa / pow( 2 , (20- ($exp - 1023))); + if ($sign) {$value = -1 * $value;} +//end of changes by mmp + + } + + if (($rknum & 0x01) != 0) { + $value /= 100; + } + return $value; + } + + function _encodeUTF16($string) + { + $result = $string; + if ($this->_defaultEncoding){ + switch ($this->_encoderFunction){ + case 'iconv' : $result = iconv('UTF-16LE', $this->_defaultEncoding, $string); + break; + case 'mb_convert_encoding' : $result = mb_convert_encoding($string, $this->_defaultEncoding, 'UTF-16LE' ); + break; + } + } + return $result; + } + + function _GetInt4d($data, $pos) + { + $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24); + if ($value>=4294967294) + { + $value=-2; + } + return $value; + } + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/plugins/general/telnet_custom_script/CHANGELOG b/plugins/general/telnet_custom_script/CHANGELOG new file mode 100755 index 0000000..6065b2f --- /dev/null +++ b/plugins/general/telnet_custom_script/CHANGELOG @@ -0,0 +1,3 @@ +1.0.0 (2008.03.13) +------------------ +Initial release with i18n support diff --git a/plugins/general/telnet_custom_script/LICENSE b/plugins/general/telnet_custom_script/LICENSE new file mode 100755 index 0000000..d511905 --- /dev/null +++ b/plugins/general/telnet_custom_script/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/general/telnet_custom_script/configure.php b/plugins/general/telnet_custom_script/configure.php new file mode 100755 index 0000000..52b2932 --- /dev/null +++ b/plugins/general/telnet_custom_script/configure.php @@ -0,0 +1,86 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['telnet_custom_script'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['telnet_custom_script'][0]['action'] = 'plugin'; +$plugin_actions['telnet_custom_script'][0]['file'] = 'display_archive_results'; +$plugin_actions['telnet_custom_script'][0]['image'] = 'archive.png'; + +$plugin_field['telnet_custom_script'][0]['version'] = '1.0.0'; +$plugin_field['telnet_custom_script'][0]['min_ortro_version'] = '1.2.0'; + +$plugin_field['telnet_custom_script'][0]['authors'][0] = 'Danilo Alfano '; +$plugin_field['telnet_custom_script'][0]['description'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_DESCRIPTION; +$plugin_field['telnet_custom_script'][0]['title'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_TITLE; + +$plugin_field['telnet_custom_script'][1]['type'] = 'text'; +$plugin_field['telnet_custom_script'][1]['name'] = 'telnet_custom_script_script'; +$plugin_field['telnet_custom_script'][1]['value'] = ''; +$plugin_field['telnet_custom_script'][1]['attributes'] = 'disabled size=70'; +$plugin_field['telnet_custom_script'][1]['description'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_PATH_COMMAND; +$plugin_field['telnet_custom_script'][1]['num_rules'] = '1'; +$plugin_field['telnet_custom_script'][1]['rule_msg'][0] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_RULE_1_0; +$plugin_field['telnet_custom_script'][1]['rule_type'][0] = 'required'; +$plugin_field['telnet_custom_script'][1]['rule_attribute'][0] = ''; + +$plugin_field['telnet_custom_script'][2]['type'] = 'text'; +$plugin_field['telnet_custom_script'][2]['name'] = 'db_telnet_custom_script_identity'; +$plugin_field['telnet_custom_script'][2]['value'] = ''; +$plugin_field['telnet_custom_script'][2]['attributes'] = 'disabled readonly'; +$plugin_field['telnet_custom_script'][2]['description'] = PLUGIN_IDENTITY; +$plugin_field['telnet_custom_script'][2]['num_rules'] = '1'; +$plugin_field['telnet_custom_script'][2]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['telnet_custom_script'][2]['rule_type'][0] = 'required'; +$plugin_field['telnet_custom_script'][2]['rule_attribute'][0] = ''; + +$plugin_field['telnet_custom_script'][3]['type'] = 'text'; +$plugin_field['telnet_custom_script'][3]['name'] = 'telnet_custom_script_port'; +$plugin_field['telnet_custom_script'][3]['value'] = ''; +$plugin_field['telnet_custom_script'][3]['attributes'] = 'disabled'; +$plugin_field['telnet_custom_script'][3]['description'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_PORT; + +$plugin_field['telnet_custom_script'][4]['type'] = 'select'; +$plugin_field['telnet_custom_script'][4]['name'] = 'telnet_custom_script_operator'; +$plugin_field['telnet_custom_script'][4]['value'] = array('>' => '>', '<' => '<', '=' => '=', '!=' => '!='); +$plugin_field['telnet_custom_script'][4]['attributes'] = ''; +$plugin_field['telnet_custom_script'][4]['description'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_OPERATOR_DESCRIPTION; +$plugin_field['telnet_custom_script'][4]['num_rules'] = '0'; + +$plugin_field['telnet_custom_script'][5]['type'] = 'text'; +$plugin_field['telnet_custom_script'][5]['name'] = 'telnet_custom_script_threshold'; +$plugin_field['telnet_custom_script'][5]['value'] = ''; +$plugin_field['telnet_custom_script'][5]['attributes'] = 'disabled'; +$plugin_field['telnet_custom_script'][5]['description'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_THRESHOLD_DESCRIPTION; +$plugin_field['telnet_custom_script'][5]['num_rules'] = '0'; + +$plugin_field['telnet_custom_script'][6]['type'] = 'select'; +$plugin_field['telnet_custom_script'][6]['name'] = 'telnet_custom_script_is_error'; +$plugin_field['telnet_custom_script'][6]['value'] = array('0' => PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_SUCCESS, + '1' => PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_ERROR); +$plugin_field['telnet_custom_script'][6]['attributes'] = ''; +$plugin_field['telnet_custom_script'][6]['description'] = PLUGIN_GENERAL_TELNET_CUSTOM_SCRIPT_ERROR_DESCRIPTION; +$plugin_field['telnet_custom_script'][6]['num_rules'] = '0'; + +$plugin_field['telnet_custom_script'][7]['type'] = 'text'; +$plugin_field['telnet_custom_script'][7]['name'] = 'check_telnet_retention'; +$plugin_field['telnet_custom_script'][7]['value'] = ''; +$plugin_field['telnet_custom_script'][7]['attributes'] = 'disabled'; +$plugin_field['telnet_custom_script'][7]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/general/telnet_custom_script/core.php b/plugins/general/telnet_custom_script/core.php new file mode 100755 index 0000000..4bd72e4 --- /dev/null +++ b/plugins/general/telnet_custom_script/core.php @@ -0,0 +1,135 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + //---- Retrieve job parameters for execution ----// + + $ip = $job_infos['ip']; + $path = dirname($argv[0]); + $hostname = $job_infos['ip']; + $port = $parameters['telnet_custom_script_port']; + + if ( ! isset ($port) || $port == "" ) $port=23; + + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + $script = $parameters['telnet_custom_script_script']; + + + $command_string = $path . '/telnet.sh ' . $hostname . ' ' + . $port . ' ' + . $user . ' ' + . $pwd . ' ' + . ' "echo ; echo Begin Telnet Custom;' + . $script . '"' + . ' 2>&1' ; + + exec($command_string, $stdout, $exit_code); + + // Searching the begin of the script + $searchKey = array_search('Begin Telnet Custom', $stdout); + // Slice aray after Begin script + $stdout_sliced = array_slice($stdout, $searchKey); + // Eliminate the Begin script tag + array_shift($stdout_sliced); + // Eliminate the end script "connection closed" + array_pop($stdout_sliced); + + //---- Set the attachments -----// + $attachments['txt'] = implode("\n", $stdout_sliced); + $attachments['html'] = implode("
", $stdout_sliced); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- For debug uses ----// + //$msg_exec = $command_string; + + // $msg_exec = $parameters['telnet_custom_script_is_error']; + //---- Check Result if Threshold is specified or return exit code value ----// + + //---- Retrieve job parameter for result check ----// + $operator = $parameters['telnet_custom_script_operator']; + $threshold = $parameters['telnet_custom_script_threshold']; + $is_error = $parameters['telnet_custom_script_is_error']; + $testValue = $attachments['txt']; + + if (!isset ($threshold) || $threshold == "") { + if ($exit_code == '0') { + $result = '1'; + } else { + $loggerPlugin->trace('ERROR', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + $result = '0'; + } + } else { + $result = notifyUtil::test($testValue, $threshold, $operator, $is_error); + } + + //---- Archive job result ----// + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['telnet_custom_script_retention']; + var_dump($retention_data); + + //---- End plugin code ----// + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); + +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> diff --git a/plugins/general/telnet_custom_script/telnet.sh b/plugins/general/telnet_custom_script/telnet.sh new file mode 100755 index 0000000..3e69900 --- /dev/null +++ b/plugins/general/telnet_custom_script/telnet.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +DATA=`date +%Y%m%d__%H_%M_%S` + + +if [ "$5" = "" ] + +then echo "\nUsing telnet.sh without parameters shows this Menu\n" + echo "Using telnet.sh host port user password command or remote script\n" + +# Please, if the connection is a little slow set a greater sleep parameter. + +else ( echo open $1 $2 +sleep 3 +echo $3 "\r" +sleep 3 +echo $4 +sleep 3 +echo $5 +sleep 3 +) | telnet 2>./telnet$DATA.log + +ERROR=`cat ./telnet$DATA.log` +if [ "$ERROR" = "Connection closed by foreign host." ] +then + exit 0 +else + exit 1 +fi + +#Remove standard error file +rm ./telnet$DATA.log + +fi diff --git a/plugins/general/windows_remote_execution/CHANGELOG b/plugins/general/windows_remote_execution/CHANGELOG new file mode 100644 index 0000000..c710cd8 --- /dev/null +++ b/plugins/general/windows_remote_execution/CHANGELOG @@ -0,0 +1,7 @@ +1.0.1 (2007.11.19) +------------------ +Use init.inc.php + +1.0.0 (2007.08.02) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/general/windows_remote_execution/LICENSE b/plugins/general/windows_remote_execution/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/general/windows_remote_execution/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/general/windows_remote_execution/configure.php b/plugins/general/windows_remote_execution/configure.php new file mode 100644 index 0000000..7867b55 --- /dev/null +++ b/plugins/general/windows_remote_execution/configure.php @@ -0,0 +1,53 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['windows_remote_execution'][0]['version'] = '1.0.1'; +$plugin_field['windows_remote_execution'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['windows_remote_execution'][0]['authors'][0] = 'Danilo Alfano'; +$plugin_field['windows_remote_execution'][0]['description'] = PLUGIN_WINDOWS_REMOTE_EXECUTION_DESCRIPTION; +$plugin_field['windows_remote_execution'][0]['title'] = PLUGIN_WINDOWS_REMOTE_EXECUTION_TITLE; + +$plugin_field['windows_remote_execution'][1]['type'] = 'text'; +$plugin_field['windows_remote_execution'][1]['name'] = 'windows_remote_execution_identity'; +$plugin_field['windows_remote_execution'][1]['value'] = ''; +$plugin_field['windows_remote_execution'][1]['attributes'] = 'disabled readonly'; +$plugin_field['windows_remote_execution'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['windows_remote_execution'][1]['num_rules'] = '1'; +$plugin_field['windows_remote_execution'][1]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['windows_remote_execution'][1]['rule_type'][0] = 'required'; +$plugin_field['windows_remote_execution'][1]['rule_attribute'][0] = ''; + +$plugin_field['windows_remote_execution'][2]['type'] = 'text'; +$plugin_field['windows_remote_execution'][2]['name'] = 'windows_remote_execution_domain'; +$plugin_field['windows_remote_execution'][2]['value'] = ''; +$plugin_field['windows_remote_execution'][2]['attributes'] = 'disabled'; +$plugin_field['windows_remote_execution'][2]['description'] = PLUGIN_WINDOWS_REMOTE_EXECUTION_DOMAIN_DESCRIPTION; +$plugin_field['windows_remote_execution'][2]['num_rules'] = '0'; + +$plugin_field['windows_remote_execution'][3]['type'] = 'text'; +$plugin_field['windows_remote_execution'][3]['name'] = 'windows_remote_execution_command'; +$plugin_field['windows_remote_execution'][3]['value'] = ''; +$plugin_field['windows_remote_execution'][3]['attributes'] = 'disabled'; +$plugin_field['windows_remote_execution'][3]['description'] = PLUGIN_WINDOWS_REMOTE_EXECUTION_COMMAND_DESCRIPTION; +$plugin_field['windows_remote_execution'][3]['num_rules'] = '1'; +$plugin_field['windows_remote_execution'][3]['rule_msg'][0] = PLUGIN_WINDOWS_REMOTE_EXECUTION_RULE_2_0; +$plugin_field['windows_remote_execution'][3]['rule_type'][0] = 'required'; +$plugin_field['windows_remote_execution'][3]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/general/windows_remote_execution/configure_metadata.php b/plugins/general/windows_remote_execution/configure_metadata.php new file mode 100644 index 0000000..91a9530 --- /dev/null +++ b/plugins/general/windows_remote_execution/configure_metadata.php @@ -0,0 +1,35 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/* Environment configuration */ + +$conf_metadata['windows_remote_execution']['description'] = PLUGIN_METADATA_CONFIGURATION; + +$conf_metadata['windows_remote_execution']['winexe_path']['description'] = PLUGIN_WINDOWS_REMOTE_EXECUTION_METADATA_WINEXE_PATH_DESCRIPTION; +$conf_metadata['windows_remote_execution']['winexe_path']['type'] = 'text'; +$conf_metadata['windows_remote_execution']['winexe_path']['name'] = 'windows_remote_execution-winexe_path'; +$conf_metadata['windows_remote_execution']['winexe_path']['value'] = '/usr/bin/winexe'; +$conf_metadata['windows_remote_execution']['winexe_path']['attributes'] = 'size=30'; +$conf_metadata['windows_remote_execution']['winexe_path']['num_rules'] = '1'; +$conf_metadata['windows_remote_execution']['winexe_path']['rule_msg'][0] = PLUGIN_WINDOWS_REMOTE_EXECUTION_METADATA_RULE_1_0; +$conf_metadata['windows_remote_execution']['winexe_path']['rule_type'][0] = 'required'; +$conf_metadata['windows_remote_execution']['winexe_path']['rule_attribute'][0] = ''; +?> diff --git a/plugins/general/windows_remote_execution/core.php b/plugins/general/windows_remote_execution/core.php new file mode 100644 index 0000000..f33e9f5 --- /dev/null +++ b/plugins/general/windows_remote_execution/core.php @@ -0,0 +1,98 @@ + + * @author Danilo Alfano + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +@require_once ORTRO_CONF_PLUGINS . 'general_windows_remote_execution.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +//---- Start plugin code ----- + +$loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); +$loggerPlugin->trace('INFO', + 'Executing job ' . $plugin_name . ' with id=' . $id_job); + +//Get the params required by plugin from argv +$user = $job_infos['identity']['username']; +$pwd = $job_infos['identity']['password']; + +$domain = $parameters['windows_remote_execution_domain']; +$command = $parameters['windows_remote_execution_command']; + +$ip = $job_infos['ip']; +$winexe_path = $conf['windows_remote_execution']['winexe_path']; + +// winexe -U DOMAIN/USER%PASSWORD //IP "command" +$cmdLine = $winexe_path . ' -U ' . + $domain . '/' . + $user . '%' . + $pwd . ' //' . + $ip . ' "' . 'cmd /C ' . + $command . '" 2>&1'; + +exec($cmdLine, $stdout, $exit_code); + +if (strpos($stdout[0], 'EPOLL_CTL_ADD') !== false) { + //remove not useful error message + array_shift($stdout); +} + +$attachments['txt'] = implode("\n", $stdout); +$attachments['html'] = implode("
", $stdout); + +if ($exit_code != '0') { + $loggerPlugin->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . implode("\n", $stdout)); + + $result = '0'; +} else { + $result = '1'; +} + +$msg_exec = $attachments['html']; +$loggerPlugin->trace('INFO', 'cmd='.$cmdLine); +$loggerPlugin->trace('INFO', 'id=' . $id_job . + ' output: ' . $attachments['txt']); +$loggerPlugin->trace('INFO', 'id=' . $id_job . + ' exit_code: ' . $exit_code); +$loggerPlugin->trace('INFO', 'Job ' . $plugin_name . + ' with id=' . $id_job . ' done.'); +//---- End plugin code ----- + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/init.inc.php b/plugins/init.inc.php new file mode 100644 index 0000000..d972034 --- /dev/null +++ b/plugins/init.inc.php @@ -0,0 +1,22 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once realpath(dirname(__FILE__) . '/../conf/init.php'); +?> \ No newline at end of file diff --git a/plugins/notification/jabber/CHANGELOG b/plugins/notification/jabber/CHANGELOG new file mode 100644 index 0000000..cd03bd6 --- /dev/null +++ b/plugins/notification/jabber/CHANGELOG @@ -0,0 +1,14 @@ +1.2.3 (2007.12.06) +Added. [1824200] Jabber notification plugin SSL support + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/notification/jabber/COPYRIGHT b/plugins/notification/jabber/COPYRIGHT new file mode 100644 index 0000000..0a3f2e0 --- /dev/null +++ b/plugins/notification/jabber/COPYRIGHT @@ -0,0 +1,24 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +Jabber class +================ +Copyright: 2006 Flyspray.org \ No newline at end of file diff --git a/plugins/notification/jabber/LICENSE b/plugins/notification/jabber/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/notification/jabber/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/notification/jabber/configure.php b/plugins/notification/jabber/configure.php new file mode 100644 index 0000000..fcb3180 --- /dev/null +++ b/plugins/notification/jabber/configure.php @@ -0,0 +1,46 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['jabber'][0]['version'] = '1.2.3'; +$plugin_field['jabber'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['jabber'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['jabber'][0]['authors'][1] = 'David Black '; +$plugin_field['jabber'][0]['title'] = PLUGIN_JABBER_TITLE; +$plugin_field['jabber'][0]['description'] = PLUGIN_JABBER_DESCRIPTION; + +$plugin_field['jabber'][1]['type'] = 'text'; +$plugin_field['jabber'][1]['name'] = 'jabber_to'; +$plugin_field['jabber'][1]['value'] = ''; +$plugin_field['jabber'][1]['attributes'] = 'disabled size=70'; +$plugin_field['jabber'][1]['description'] = PLUGIN_JABBER_TO_DESCRIPTION; +$plugin_field['jabber'][1]['description_detail'] = PLUGIN_JABBER_TO_DESCRIPTION_DETAIL; + +$plugin_field['jabber'][2]['type'] = 'textarea'; +$plugin_field['jabber'][2]['name'] = 'jabber_message'; +$plugin_field['jabber'][2]['value'] = ''; +$plugin_field['jabber'][2]['attributes'] = 'disabled rows=10 cols=50'; +$plugin_field['jabber'][2]['description'] = PLUGIN_JABBER_MESSAGE_DESCRIPTION; + +$plugin_field['jabber'][3]['type'] = 'checkbox'; +$plugin_field['jabber'][3]['name'] = 'jabber_attach_result'; +$plugin_field['jabber'][3]['value'] = ''; +$plugin_field['jabber'][3]['attributes'] = ''; +$plugin_field['jabber'][3]['description'] = PLUGIN_ATTACH_RESULT; +?> \ No newline at end of file diff --git a/plugins/notification/jabber/configure_metadata.php b/plugins/notification/jabber/configure_metadata.php new file mode 100644 index 0000000..c5a5056 --- /dev/null +++ b/plugins/notification/jabber/configure_metadata.php @@ -0,0 +1,53 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['jabber']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['jabber']['host']['description'] = PLUGIN_JABBER_METADATA_SERVER_DESCRIPTION; +$conf_metadata['jabber']['host']['type'] = 'text'; +$conf_metadata['jabber']['host']['name'] = 'jabber-host'; +$conf_metadata['jabber']['host']['value'] = 'localhost'; +$conf_metadata['jabber']['host']['attributes'] = 'size=30'; + +$conf_metadata['jabber']['security']['description'] = PLUGIN_JABBER_METADATA_SECURITY_DESCRIPTION; +$conf_metadata['jabber']['security']['type'] = 'select'; +$conf_metadata['jabber']['security']['name'] = 'jabber-security'; +$conf_metadata['jabber']['security']['value'] = array('none' => PLUGIN_JABBER_METADATA_SECURITY_NONE, + 'ssl' => PLUGIN_JABBER_METADATA_SECURITY_SSL, + 'tsl' => PLUGIN_JABBER_METADATA_SECURITY_TSL); +$conf_metadata['jabber']['security']['attributes'] = ''; + +$conf_metadata['jabber']['port']['description'] = PLUGIN_JABBER_METADATA_PORT_DESCRIPTION; +$conf_metadata['jabber']['port']['type'] = 'text'; +$conf_metadata['jabber']['port']['name'] = 'jabber-port'; +$conf_metadata['jabber']['port']['value'] = ''; +$conf_metadata['jabber']['port']['attributes'] = 'size=5'; + +$conf_metadata['jabber']['username']['description'] = PLUGIN_JABBER_METADATA_USER_DESCRIPTION; +$conf_metadata['jabber']['username']['type'] = 'text'; +$conf_metadata['jabber']['username']['name'] = 'jabber-username'; +$conf_metadata['jabber']['username']['value'] = ''; +$conf_metadata['jabber']['username']['attributes'] = 'size=30'; + +$conf_metadata['jabber']['password']['description'] = PLUGIN_JABBER_METADATA_PASSWORD_DESCRIPTION; +$conf_metadata['jabber']['password']['type'] = 'password'; +$conf_metadata['jabber']['password']['name'] = 'jabber-password'; +$conf_metadata['jabber']['password']['value'] = ''; +$conf_metadata['jabber']['password']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/notification/jabber/core.php b/plugins/notification/jabber/core.php new file mode 100644 index 0000000..e9b672f --- /dev/null +++ b/plugins/notification/jabber/core.php @@ -0,0 +1,100 @@ + + * @author David Black + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; +require_once 'lib/class.jabber2.php'; + +global $conf; +require_once ORTRO_CONF_PLUGINS . 'notification_jabber.php'; + +/** + * Sends an Instant Message using the Jabber protocol + * + * @param array $elements The user form values + * @param array $attachments The files to attach + * + * @return void + */ +function jabberNotify($elements, $attachments) +{ + $logger = new LogUtil('jabber_notification'); + + $jabber_server = $GLOBALS['conf']['jabber']['host']; + $jabber_port = $GLOBALS['conf']['jabber']['port']; + $jabber_username = $GLOBALS['conf']['jabber']['username']; + $jabber_password = $GLOBALS['conf']['jabber']['password']; + + switch ($GLOBALS['conf']['jabber']['security']) { + case 'ssl': + $jabber_smode = SECURITY_SSL; + break; + case 'tsl': + $jabber_smode = SECURITY_TSL; + break; + default: + $jabber_smode = SECURITY_NONE; + break; + } + + $logger->trace('INFO', "Sending jabber IM to " . + $elements['jabber_to'] . + ", username=" . $jabber_username . + ", smode=" . $jabber_smode . + ", port=" . $jabber_port . + ", server=" . $jabber_server); + + try { + $JABBER = new Jabber($jabber_username, + $jabber_password, + $jabber_smode, + $jabber_port, + $jabber_server); + + if ($logger->logLevel != 'DEBUG') { + //disable jabber_class logging + $JABBER->log_enabled = false; + $JABBER->log = null; + } + + $JABBER->login(); + + $data_message = $elements['jabber_message']; + + if ($elements['jabber_attach_result']=='1' + && array_key_exists('txt', $attachments)) { + $data_message .= $attachments['txt']; + } + + $JABBER->send_message($elements['jabber_to'], + $data_message); + + $logger->trace('DEBUG', print_r($JABBER->log, true)); + + $JABBER->disconnect(); + } catch (Exception $e) { + $logger->trace('ERROR', $e->getMessage()); + } + + $logger->trace('INFO', 'Done.'); + return true; +} +?> diff --git a/plugins/notification/jabber/lib/class.jabber2.php b/plugins/notification/jabber/lib/class.jabber2.php new file mode 100644 index 0000000..75cb15a --- /dev/null +++ b/plugins/notification/jabber/lib/class.jabber2.php @@ -0,0 +1,962 @@ +log($error_msg); + throw new Exception($error_msg); + } + + //bug in php 5.2.1 renders this stuff more or less useless. + if ((version_compare(phpversion(), '5.2.1', '>=') && version_compare(phpversion(), '5.2.3RC2', '<')) && $security != SECURITY_NONE) { + $error_msg = 'Error: PHP ' . phpversion() . ' + SSL is incompatible with jabber, see http://bugs.php.net/41236'; + $this->log($error_msg); + throw new Exception($error_msg); + } + + if (!Jabber::check_jid($login)) { + $error_msg = 'Error: Jabber ID is not valid: ' . $login; + $this->log($error_msg); + throw new Exception($error_msg); + } + + // Extract data from user@server.org + list($username, $server) = explode('@', $login); + + // Decide whether or not to use encryption + if ($security == SECURITY_SSL && !Jabber::can_use_ssl()) { + $this->log('Warning: SSL encryption is not supported (openssl required). Falling back to no encryption.'); + $security = SECURITY_NONE; + } + if ($security == SECURITY_TLS && !Jabber::can_use_tls()) { + $this->log('Warning: TLS encryption is not supported (openssl and stream_socket_enable_crypto() required). Falling back to no encryption.'); + $security = SECURITY_NONE; + } + + $this->session['security'] = $security; + $this->server = $server; + $this->user = $username; + $this->password = $password; + + if ($this->open_socket( ($host != '') ? $host : $server, $port, $security == SECURITY_SSL)) { + $this->send("\n"); + $this->send("\n"); + } else { + return false; + } + // Now we listen what the server has to say...and give appropriate responses + $this->response($this->listen()); + } + + /** + * Sets the resource which is used. No validation is done here, only escaping. + * @param string $$name + * @access public + */ + function SetResource($name) + { + $this->resource = $name; + } + + /** + * Send data to the Jabber server + * @param string $xml + * @access public + * @return bool + */ + function send($xml) + { + if ($this->connected()) { + $xml = trim($xml); + $this->log('SEND: '. $xml); + return fwrite($this->connection, $xml); + } else { + $error_msg = 'Error: Could not send, connection lost (flood?).'; + $this->log($error_msg); + throw new Exception($error_msg); + } + } + + /** + * OpenSocket + * @param string $server host to connect to + * @param int $port port number + * @param bool $ssl use ssl or not + * @access public + * @return bool + */ + function open_socket($server, $port, $ssl = false) + { + if (function_exists("dns_get_record")) { + $record = dns_get_record("_xmpp-client._tcp.$server", DNS_SRV); + if (!empty($record)) { + $server = $record[0]['target']; + } + } else { + $this->log('Warning: dns_get_record function not found. gtalk will not work.'); + } + + $server = $ssl ? 'ssl://' . $server : $server; + + if ($ssl) { + $this->session['ssl'] = true; + } + + if ($this->connection = @fsockopen($server, $port, $errorno, $errorstr, $this->timeout)) { + socket_set_blocking($this->connection, 0); + socket_set_timeout($this->connection, 60); + + return true; + } + // Apparently an error occured... + $error_msg = 'Error: ' . $errorstr; + $this->log($error_msg); + throw new Exception($error_msg); + } + + function log($msg) + { + if ($this->log_enabled) { + $this->log[] = $msg; + return true; + } + + return false; + } + + /** + * Listens to the connection until it gets data or the timeout is reached. + * Thus, it should only be called if data is expected to be received. + * @access public + * @return mixed either false for timeout or an array with the received data + */ + function listen($timeout = 10, $wait = false) + { + if (!$this->connected()) { + return false; + } + + // Wait for a response until timeout is reached + $start = time(); + $data = ''; + + do { + $read = trim(fread($this->connection, 4096)); + $data .= $read; + } while (time() <= $start + $timeout && !feof($this->connection) && ($wait || $data == '' || $read != '' + || (substr(rtrim($data), -1) != '>'))); + + if ($data != '') { + $this->log('RECV: '. $data); + return Jabber::xmlize($data); + } else { + $this->log('Timeout, no response from server.'); + return false; + } + } + + /** + * Initiates login (using data from contructor) + * @access public + * @return bool + */ + function login() + { + if (!count($this->features)) { + $error_msg = 'Error: No feature information from server available.'; + $this->log($error_msg); + throw new Exception($error_msg); + } + + return $this->response($this->features); + } + + /** + * Initiates account registration (based on data used for contructor) + * @access public + * @return bool + */ + function register() + { + if (!isset($this->session['id']) || isset($this->session['jid'])) { + $error_msg = 'Error: Cannot initiate registration.'; + $this->log($error_msg); + throw new Exception($error_msg); + } + + $this->send(" + + "); + return $this->response($this->listen()); + } + + /** + * Initiates account un-registration (based on data used for contructor) + * @access public + * @return bool + */ + function unregister() + { + if (!isset($this->session['id']) || !isset($this->session['jid'])) { + $error_msg = 'Error: Cannot initiate un-registration.'; + $this->log($error_msg); + throw new Exception($error_msg); + } + + $this->send(" + + + + "); + return $this->response($this->listen(2)); // maybe we don't even get a response + } + + /** + * Sets account presence. No additional info required (default is "online" status) + * @param $type dnd, away, chat, xa or nothing + * @param $message + * @param $unavailable set this to true if you want to become unavailable + * @access public + * @return bool + */ + function presence($type = '', $message = '', $unavailable = false) + { + if (!isset($this->session['jid'])) { + $error_msg = 'Error: Cannot set presence at this point.'; + $this->log($error_msg); + throw new Exception($error_msg); + } + + if (in_array($type, array('dnd', 'away', 'chat', 'xa'))) { + $type = ''. $type .''; + } else { + $type = ''; + } + + $unavailable = ($unavailable) ? " type='unavailable'" : ''; + $message = ($message) ? '' . Jabber::jspecialchars($message) .'' : ''; + + $this->session['sent_presence'] = !$unavailable; + + return $this->send("" . + $type . + $message . + ''); + } + + /** + * This handles all the different XML elements + * @param array $xml + * @access public + * @return bool + */ + function response($xml) + { + if (!is_array($xml) || !count($xml)) { + return false; + } + + // did we get multiple elements? do one after another + // array('message' => ..., 'presence' => ...) + if (count($xml) > 1) { + foreach ($xml as $key => $value) { + $this->response(array($key => $value)); + } + return; + } else + // or even multiple elements of the same type? + // array('message' => array(0 => ..., 1 => ...)) + if (count(reset($xml)) > 1) { + foreach (reset($xml) as $value) { + $this->response(array(key($xml) => array(0 => $value))); + } + return; + } + + switch (key($xml)) { + case 'stream:stream': + // Connection initialised (or after authentication). Not much to do here... + if (isset($xml['stream:stream'][0]['#']['stream:features'])) { + // we already got all info we need + $this->features = $xml['stream:stream'][0]['#']; + } else { + $this->features = $this->listen(); + } + $second_time = isset($this->session['id']); + $this->session['id'] = $xml['stream:stream'][0]['@']['id']; + if ($second_time) { + // If we are here for the second time after TLS, we need to continue logging in + $this->login(); + return; + } + + // go on with authentication? + if (isset($this->features['stream:features'][0]['#']['bind'])) { + return $this->response($this->features); + } + break; + + case 'stream:features': + // Resource binding after successful authentication + if (isset($this->session['authenticated'])) { + // session required? + $this->session['sess_required'] = isset($xml['stream:features'][0]['#']['session']); + + $this->send(" + + " . Jabber::jspecialchars($this->resource) . " + + "); + return $this->response($this->listen()); + } + // Let's use TLS if SSL is not enabled and we can actually use it + if ($this->session['security'] == SECURITY_TLS && isset($xml['stream:features'][0]['#']['starttls'])) { + $this->log('Switching to TLS.'); + $this->send("\n"); + return $this->response($this->listen()); + } + // Does the server support SASL authentication? + + // I hope so, because we do (and no other method). + if (isset($xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns']) && + $xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns'] == 'urn:ietf:params:xml:ns:xmpp-sasl') { + // Now decide on method + $methods = array(); + foreach ($xml['stream:features'][0]['#']['mechanisms'][0]['#']['mechanism'] as $value) { + $methods[] = $value['#']; + } + + // we prefer this one + if (in_array('DIGEST-MD5', $methods)) { + $this->send(""); + // we don't want to use this (neither does the server usually) if no encryption is in place + # http://www.xmpp.org/extensions/attic/jep-0078-1.7.html + # The plaintext mechanism SHOULD NOT be used unless the underlying stream is encrypted (using SSL or TLS) + # and the client has verified that the server certificate is signed by a trusted certificate authority. + } else if (in_array('PLAIN', $methods) && (isset($this->session['ssl']) || isset($this->session['tls']))) { + $this->send("" + . base64_encode(chr(0) . $this->user . '@' . $this->server . chr(0) . $this->password) . + ""); + } else if (in_array('ANONYMOUS', $methods)) { + $this->send(""); + // not good... + } else { + $error_msg = 'Error: No authentication method supported.'; + $this->log($error_msg); + $this->disconnect(); + throw new Exception($error_msg); + } + return $this->response($this->listen()); + + } else { + // ok, this is it. bye. + $this->log($error_msg); + $error_msg = 'Error: Server does not offer SASL authentication.'; + $this->disconnect(); + throw new Exception($error_msg); + } + break; + + case 'challenge': + // continue with authentication...a challenge literally -_- + $decoded = base64_decode($xml['challenge'][0]['#']); + $decoded = Jabber::parse_data($decoded); + if (!isset($decoded['digest-uri'])) { + $decoded['digest-uri'] = 'xmpp/'. $this->server; + } + + // better generate a cnonce, maybe it's needed + $str = ''; + mt_srand((double)microtime()*10000000); + for ($i = 0; $i < 32; $i++) { + $str .= chr(mt_rand(0, 255)); + } + $decoded['cnonce'] = base64_encode($str); + + // second challenge? + if (isset($decoded['rspauth'])) { + $this->send(""); + } else { + $response = array('username' => $this->user, + 'response' => $this->encrypt_password(array_merge($decoded, array('nc' => '00000001'))), + 'charset' => 'utf-8', + 'nc' => '00000001', + 'qop' => 'auth'); // the only option we support anyway + + foreach (array('nonce', 'digest-uri', 'realm', 'cnonce') as $key) { + if (isset($decoded[$key])) { + $response[$key] = $decoded[$key]; + } + } + + $this->send("" . + base64_encode(Jabber::implode_data($response)) + . ""); + } + + return $this->response($this->listen()); + + case 'failure': + $error_msg = 'Error: Server sent "failure".'; + $this->disconnect(); + $this->log($error_msg); + throw new Exception($error_msg); + + case 'proceed': + // continue switching to TLS + $meta = stream_get_meta_data($this->connection); + socket_set_blocking($this->connection, 1); + if (!stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { + $error_msg = 'Error: TLS mode change failed.'; + $this->log($error_msg); + throw new Exception($error_msg); + } + socket_set_blocking($this->connection, $meta['blocked']); + $this->session['tls'] = true; + // new stream + $this->send("\n"); + $this->send("\n"); + + return $this->response($this->listen()); + + case 'success': + // Yay, authentication successful. + $this->send("\n"); + $this->session['authenticated'] = true; + return $this->response($this->listen()); // we have to wait for another response + + case 'iq': + // we are not interested in IQs we did not expect + if (!isset($xml['iq'][0]['@']['id'])) { + return false; + } + // multiple possibilities here + switch ($xml['iq'][0]['@']['id']) + { + case 'bind_1': + $this->session['jid'] = $xml['iq'][0]['#']['bind'][0]['#']['jid'][0]['#']; + // and (maybe) yet another request to be able to send messages *finally* + if ($this->session['sess_required']) { + $this->send(" + + "); + return $this->response($this->listen()); + } + return true; + + case 'sess_1': + return true; + + case 'reg_1': + $this->send(" + + " . Jabber::jspecialchars($this->user) . " + " . Jabber::jspecialchars($this->password) . " + + "); + return $this->response($this->listen()); + + case 'reg_2': + // registration end + if (isset($xml['iq'][0]['#']['error'])) { + $this->log('Warning: Registration failed.'); + return false; + } + return true; + + case 'unreg_1': + return true; + + default: + $this->log('Notice: Received unexpected IQ.'); + return false; + } + break; + + case 'message': + // we are only interested in content... + if (!isset($xml['message'][0]['#']['body'])) { + return false; + } + + $message['body'] = $xml['message'][0]['#']['body'][0]['#']; + $message['from'] = $xml['message'][0]['@']['from']; + if (isset($xml['message'][0]['#']['subject'])) { + $message['subject'] = $xml['message'][0]['#']['subject'][0]['#']; + } + $this->session['messages'][] = $message; + break; + + default: + // hm...don't know this response + $this->log('Notice: Unknown server response (' . key($xml) . ')'); + return false; + } + } + + function send_message($to, $text, $subject = '', $type = 'normal') + { + if (!isset($this->session['jid'])) { + return false; + } + + if (!in_array($type, array('chat', 'normal', 'error', 'groupchat', 'headline'))) { + $type = 'normal'; + } + + return $this->send(" + " . Jabber::jspecialchars($subject) . " + " . Jabber::jspecialchars($text) . " + "); + } + + function get_messages($waitfor = 3) + { + if (!isset($this->session['sent_presence']) || !$this->session['sent_presence']) { + $this->presence(); + } + + if ($waitfor > 0) { + $this->response($this->listen($waitfor, $wait = true)); // let's see if any messages fly in + } + + return isset($this->session['messages']) ? $this->session['messages'] : array(); + } + + function connected() + { + return is_resource($this->connection) && !feof($this->connection); + } + + function disconnect() + { + if ($this->connected()) { + // disconnect gracefully + if (isset($this->session['sent_presence'])) { + $this->presence('', 'offline', $unavailable = true); + } + $this->send(''); + $this->session = array(); + return fclose($this->connection); + } + return false; + } + + function can_use_ssl() + { + return extension_loaded('openssl'); + } + + function can_use_tls() + { + return Jabber::can_use_ssl() && function_exists('stream_socket_enable_crypto'); + } + + /** + * Encrypts a password as in RFC 2831 + * @param array $data Needs data from the client-server connection + * @access public + * @return string + */ + function encrypt_password($data) + { + // let's me think about again... + foreach (array('realm', 'cnonce', 'digest-uri') as $key) { + if (!isset($data[$key])) { + $data[$key] = ''; + } + } + + $pack = md5($this->user . ':' . $data['realm'] . ':' . $this->password); + if (isset($data['authzid'])) { + $a1 = pack('H32', $pack) . sprintf(':%s:%s:%s', $data['nonce'], $data['cnonce'], $data['authzid']); + } else { + $a1 = pack('H32', $pack) . sprintf(':%s:%s', $data['nonce'], $data['cnonce']); + } + + // should be: qop = auth + $a2 = 'AUTHENTICATE:'. $data['digest-uri']; + + return md5(sprintf('%s:%s:%s:%s:%s:%s', md5($a1), $data['nonce'], $data['nc'], $data['cnonce'], $data['qop'], md5($a2))); + } + + /** + * parse_data like a="b",c="d",... + * @param string $data + * @access public + * @return array a => b ... + */ + function parse_data($data) + { + // super basic, but should suffice + $data = explode(',', $data); + $pairs = array(); + foreach ($data as $pair) { + $dd = strpos($pair, '='); + if ($dd) { + $pairs[substr($pair, 0, $dd)] = trim(substr($pair, $dd + 1), '"'); + } + } + return $pairs; + } + + /** + * opposite of Jabber::parse_data() + * @param array $data + * @access public + * @return string + */ + function implode_data($data) + { + $return = array(); + foreach ($data as $key => $value) { + $return[] = $key . '="' . $value . '"'; + } + return implode(',', $return); + } + + /** + * Checks whether or not a Jabber ID is valid (FS#1131) + * @param string $jid + * @access public + * @return string + */ + function check_jid($jid) + { + $i = strpos($jid, '@'); + if ($i === false) { + return false; + } + + $username = substr($jid, 0, $i); + $realm = substr($jid, $i + 1); + + if (strlen($username) == 0 || strlen($realm) < 3) { + return false; + } + + $arr = explode('.', $realm); + + if (count($arr) == 0) { + return false; + } + + foreach ($arr as $part) + { + if (substr($part, 0, 1) == '-' || substr($part, -1, 1) == '-') { + return false; + } + + if (preg_match("@^[a-zA-Z0-9-.]+$@", $part) == false) { + return false; + } + } + + $b = array(array(0, 127), array(192, 223), array(224, 239), + array(240, 247), array(248, 251), array(252, 253)); + + // Prohibited Characters RFC3454 + RFC3920 + $p = array( + // Table C.1.1 + array(0x0020, 0x0020), // SPACE + // Table C.1.2 + array(0x00A0, 0x00A0), // NO-BREAK SPACE + array(0x1680, 0x1680), // OGHAM SPACE MARK + array(0x2000, 0x2001), // EN QUAD + array(0x2001, 0x2001), // EM QUAD + array(0x2002, 0x2002), // EN SPACE + array(0x2003, 0x2003), // EM SPACE + array(0x2004, 0x2004), // THREE-PER-EM SPACE + array(0x2005, 0x2005), // FOUR-PER-EM SPACE + array(0x2006, 0x2006), // SIX-PER-EM SPACE + array(0x2007, 0x2007), // FIGURE SPACE + array(0x2008, 0x2008), // PUNCTUATION SPACE + array(0x2009, 0x2009), // THIN SPACE + array(0x200A, 0x200A), // HAIR SPACE + array(0x200B, 0x200B), // ZERO WIDTH SPACE + array(0x202F, 0x202F), // NARROW NO-BREAK SPACE + array(0x205F, 0x205F), // MEDIUM MATHEMATICAL SPACE + array(0x3000, 0x3000), // IDEOGRAPHIC SPACE + // Table C.2.1 + array(0x0000, 0x001F), // [CONTROL CHARACTERS] + array(0x007F, 0x007F), // DELETE + // Table C.2.2 + array(0x0080, 0x009F), // [CONTROL CHARACTERS] + array(0x06DD, 0x06DD), // ARABIC END OF AYAH + array(0x070F, 0x070F), // SYRIAC ABBREVIATION MARK + array(0x180E, 0x180E), // MONGOLIAN VOWEL SEPARATOR + array(0x200C, 0x200C), // ZERO WIDTH NON-JOINER + array(0x200D, 0x200D), // ZERO WIDTH JOINER + array(0x2028, 0x2028), // LINE SEPARATOR + array(0x2029, 0x2029), // PARAGRAPH SEPARATOR + array(0x2060, 0x2060), // WORD JOINER + array(0x2061, 0x2061), // FUNCTION APPLICATION + array(0x2062, 0x2062), // INVISIBLE TIMES + array(0x2063, 0x2063), // INVISIBLE SEPARATOR + array(0x206A, 0x206F), // [CONTROL CHARACTERS] + array(0xFEFF, 0xFEFF), // ZERO WIDTH NO-BREAK SPACE + array(0xFFF9, 0xFFFC), // [CONTROL CHARACTERS] + array(0x1D173, 0x1D17A), // [MUSICAL CONTROL CHARACTERS] + // Table C.3 + array(0xE000, 0xF8FF), // [PRIVATE USE, PLANE 0] + array(0xF0000, 0xFFFFD), // [PRIVATE USE, PLANE 15] + array(0x100000, 0x10FFFD), // [PRIVATE USE, PLANE 16] + // Table C.4 + array(0xFDD0, 0xFDEF), // [NONCHARACTER CODE POINTS] + array(0xFFFE, 0xFFFF), // [NONCHARACTER CODE POINTS] + array(0x1FFFE, 0x1FFFF), // [NONCHARACTER CODE POINTS] + array(0x2FFFE, 0x2FFFF), // [NONCHARACTER CODE POINTS] + array(0x3FFFE, 0x3FFFF), // [NONCHARACTER CODE POINTS] + array(0x4FFFE, 0x4FFFF), // [NONCHARACTER CODE POINTS] + array(0x5FFFE, 0x5FFFF), // [NONCHARACTER CODE POINTS] + array(0x6FFFE, 0x6FFFF), // [NONCHARACTER CODE POINTS] + array(0x7FFFE, 0x7FFFF), // [NONCHARACTER CODE POINTS] + array(0x8FFFE, 0x8FFFF), // [NONCHARACTER CODE POINTS] + array(0x9FFFE, 0x9FFFF), // [NONCHARACTER CODE POINTS] + array(0xAFFFE, 0xAFFFF), // [NONCHARACTER CODE POINTS] + array(0xBFFFE, 0xBFFFF), // [NONCHARACTER CODE POINTS] + array(0xCFFFE, 0xCFFFF), // [NONCHARACTER CODE POINTS] + array(0xDFFFE, 0xDFFFF), // [NONCHARACTER CODE POINTS] + array(0xEFFFE, 0xEFFFF), // [NONCHARACTER CODE POINTS] + array(0xFFFFE, 0xFFFFF), // [NONCHARACTER CODE POINTS] + array(0x10FFFE, 0x10FFFF), // [NONCHARACTER CODE POINTS] + // Table C.5 + array(0xD800, 0xDFFF), // [SURROGATE CODES] + // Table C.6 + array(0xFFF9, 0xFFF9), // INTERLINEAR ANNOTATION ANCHOR + array(0xFFFA, 0xFFFA), // INTERLINEAR ANNOTATION SEPARATOR + array(0xFFFB, 0xFFFB), // INTERLINEAR ANNOTATION TERMINATOR + array(0xFFFC, 0xFFFC), // OBJECT REPLACEMENT CHARACTER + array(0xFFFD, 0xFFFD), // REPLACEMENT CHARACTER + // Table C.7 + array(0x2FF0, 0x2FFB), // [IDEOGRAPHIC DESCRIPTION CHARACTERS] + // Table C.8 + array(0x0340, 0x0340), // COMBINING GRAVE TONE MARK + array(0x0341, 0x0341), // COMBINING ACUTE TONE MARK + array(0x200E, 0x200E), // LEFT-TO-RIGHT MARK + array(0x200F, 0x200F), // RIGHT-TO-LEFT MARK + array(0x202A, 0x202A), // LEFT-TO-RIGHT EMBEDDING + array(0x202B, 0x202B), // RIGHT-TO-LEFT EMBEDDING + array(0x202C, 0x202C), // POP DIRECTIONAL FORMATTING + array(0x202D, 0x202D), // LEFT-TO-RIGHT OVERRIDE + array(0x202E, 0x202E), // RIGHT-TO-LEFT OVERRIDE + array(0x206A, 0x206A), // INHIBIT SYMMETRIC SWAPPING + array(0x206B, 0x206B), // ACTIVATE SYMMETRIC SWAPPING + array(0x206C, 0x206C), // INHIBIT ARABIC FORM SHAPING + array(0x206D, 0x206D), // ACTIVATE ARABIC FORM SHAPING + array(0x206E, 0x206E), // NATIONAL DIGIT SHAPES + array(0x206F, 0x206F), // NOMINAL DIGIT SHAPES + // Table C.9 + array(0xE0001, 0xE0001), // LANGUAGE TAG + array(0xE0020, 0xE007F), // [TAGGING CHARACTERS] + // RFC3920 + array(0x22, 0x22), // " + array(0x26, 0x26), // & + array(0x27, 0x27), // ' + array(0x2F, 0x2F), // / + array(0x3A, 0x3A), // : + array(0x3C, 0x3C), // < + array(0x3E, 0x3E), // > + array(0x40, 0x40) // @ + ); + + $pos = 0; + $result = true; + + while ($pos < strlen($username)) + { + $len = 0; + $uni = 0; + for ($i = 0; $i <= 5; $i++) + { + if (ord($username[$pos]) >= $b[$i][0] && ord($username[$pos]) <= $b[$i][1]) + { + $len = $i + 1; + + $uni = (ord($username[$pos]) - $b[$i][0]) * pow(2, $i * 6); + + for ($k = 1; $k < $len; $k++) { + $uni += (ord($username[$pos + $k]) - 128) * pow(2, ($i - $k) * 6); + } + + break; + } + } + + if ($len == 0) { + return false; + } + + foreach ($p as $pval) + { + if ($uni >= $pval[0] && $uni <= $pval[1]) { + $result = false; + break 2; + } + } + + $pos = $pos + $len; + } + + return $result; + } + + function jspecialchars($data) + { + return htmlspecialchars($data, ENT_QUOTES, 'utf-8'); + } + + // ====================================================================== + // Third party code, taken from old jabber lib (the only usable code left) + // ====================================================================== + + // xmlize() + // (c) Hans Anderson / http://www.hansanderson.com/php/xml/ + + function xmlize($data, $WHITE=1, $encoding='UTF-8') { + + $data = trim($data); + if (substr($data, 0, 5) != ''. $data . ''; // mod + } + $vals = $array = array(); + $parser = xml_parser_create($encoding); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $WHITE); + xml_parse_into_struct($parser, $data, $vals); + xml_parser_free($parser); + + $i = 0; + + $tagname = $vals[$i]['tag']; + if ( isset ($vals[$i]['attributes'] ) ) + { + $array[$tagname][0]['@'] = $vals[$i]['attributes']; // mod + } else { + $array[$tagname][0]['@'] = array(); // mod + } + + $array[$tagname][0]["#"] = Jabber::_xml_depth($vals, $i); // mod + if (substr($data, 0, 5) != ' diff --git a/plugins/notification/mail/CHANGELOG b/plugins/notification/mail/CHANGELOG new file mode 100644 index 0000000..8b141db --- /dev/null +++ b/plugins/notification/mail/CHANGELOG @@ -0,0 +1,28 @@ +1.2.6 (2009.09.22) +------------------ +Changed. Updated Pear libraries. + +1.2.5 (2008.03.11) +------------------ +Fixed. [1911952] Cannot redeclare class Net_Socket +Changed. Updated Pear library. + +1.2.4 (2008.02.20) +------------------ +Changed. Updated Pear SMTP library to version 1.2.11 + +1.2.3 (2007.12.05) +------------------ +Fixed. [1824271] Mail notification plugin in SMTP mode issues invalid HELO + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/notification/mail/COPYRIGHT b/plugins/notification/mail/COPYRIGHT new file mode 100644 index 0000000..9578ae4 --- /dev/null +++ b/plugins/notification/mail/COPYRIGHT @@ -0,0 +1,43 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +Pear packages: +============== + +Mail +------ +Copyright: 1997-2003 The PHP Group +License: PHP license + +Mail_Mime +----------- +Copyright: 1002-2003, Richard Heyes, 2003-2006, PEAR +License: BSD Style + +Net/SMTP +-------------- +Copyright: 1997-2003 The PHP Group +License: PHP license + +Net/Socket +-------------- +Copyright: 1997-2003 The PHP Group +License: PHP license \ No newline at end of file diff --git a/plugins/notification/mail/LICENSE b/plugins/notification/mail/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/notification/mail/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/notification/mail/configure.php b/plugins/notification/mail/configure.php new file mode 100644 index 0000000..229c88d --- /dev/null +++ b/plugins/notification/mail/configure.php @@ -0,0 +1,78 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['mail'][0]['version'] = '1.2.6'; +$plugin_field['mail'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['mail'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['mail'][0]['title'] = PLUGIN_MAIL_TITLE; +$plugin_field['mail'][0]['description'] = PLUGIN_MAIL_DESCRIPTION; + + +$plugin_field['mail'][1]['type'] = 'text'; +$plugin_field['mail'][1]['name'] = 'mail_subject'; +$plugin_field['mail'][1]['value'] = ''; +$plugin_field['mail'][1]['attributes'] = 'disabled size=70'; +$plugin_field['mail'][1]['description'] = PLUGIN_MAIL_SUBJECT_DESCRIPTION; +$plugin_field['mail'][1]['num_rules'] = '1'; +$plugin_field['mail'][1]['rule_msg'][0] = PLUGIN_MAIL_RULE_1_0; +$plugin_field['mail'][1]['rule_type'][0] = 'required'; +$plugin_field['mail'][1]['rule_attribute'][0] = ''; + +$plugin_field['mail'][2]['type'] = 'text'; +$plugin_field['mail'][2]['name'] = 'mail_to'; +$plugin_field['mail'][2]['value'] = ''; +$plugin_field['mail'][2]['attributes'] = 'disabled size=70'; +$plugin_field['mail'][2]['description'] = PLUGIN_MAIL_TO_DESCRIPTION; +$plugin_field['mail'][2]['num_rules'] = '2'; +$plugin_field['mail'][2]['rule_msg'][0] = PLUGIN_MAIL_RULE_2_0; +$plugin_field['mail'][2]['rule_type'][0] = 'required'; +$plugin_field['mail'][2]['rule_attribute'][0] = ''; +$plugin_field['mail'][2]['rule_msg'][1] = PLUGIN_MAIL_RULE_2_1; +$plugin_field['mail'][2]['rule_type'][1] = 'regex'; +$plugin_field['mail'][2]['rule_attribute'][1] = '/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+[a-zA-Z0-9]{2,4}(\s*,\s*([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+[a-zA-Z0-9]{2,4})*$/'; + +$plugin_field['mail'][3]['type'] = 'text'; +$plugin_field['mail'][3]['name'] = 'mail_cc'; +$plugin_field['mail'][3]['value'] = ''; +$plugin_field['mail'][3]['attributes'] = 'disabled size=70'; +$plugin_field['mail'][3]['description'] = PLUGIN_MAIL_CC_DESCRIPTION; +$plugin_field['mail'][3]['num_rules'] = '1'; +$plugin_field['mail'][3]['rule_msg'][0] = PLUGIN_MAIL_RULE_3_0; +$plugin_field['mail'][3]['rule_type'][0] = 'regex'; +$plugin_field['mail'][3]['rule_attribute'][0] = '/^(([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+[a-zA-Z0-9]{2,4}(\s*,\s*([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+[a-zA-Z0-9]{2,4})*)*$/'; + +$plugin_field['mail'][4]['type'] = 'textarea'; +$plugin_field['mail'][4]['name'] = 'mail_html'; +$plugin_field['mail'][4]['value'] = ''; +$plugin_field['mail'][4]['attributes'] = 'disabled htmlarea rows=10 cols=50'; +$plugin_field['mail'][4]['description'] = PLUGIN_MAIL_BODY_DESCRIPTION; + +$plugin_field['mail'][5]['type'] = 'checkbox'; +$plugin_field['mail'][5]['name'] = 'mail_attach_result'; +$plugin_field['mail'][5]['value'] = ''; +$plugin_field['mail'][5]['attributes'] = ''; +$plugin_field['mail'][5]['description'] = PLUGIN_ATTACH_RESULT; + +$plugin_field['mail'][6]['type'] = 'checkbox'; +$plugin_field['mail'][6]['name'] = 'mail_attach_timestamp'; +$plugin_field['mail'][6]['value'] = ''; +$plugin_field['mail'][6]['attributes'] = ''; +$plugin_field['mail'][6]['description'] = PLUGIN_ATTACH_DATE; +?> \ No newline at end of file diff --git a/plugins/notification/mail/configure_metadata.php b/plugins/notification/mail/configure_metadata.php new file mode 100644 index 0000000..989294f --- /dev/null +++ b/plugins/notification/mail/configure_metadata.php @@ -0,0 +1,102 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['mail']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['mail']['type']['description'] = PLUGIN_MAIL_METADATA_NAME_DESCRIPTION; +$conf_metadata['mail']['type']['type'] = 'select'; +$conf_metadata['mail']['type']['name'] = 'mail-type'; +$conf_metadata['mail']['type']['value'] = array('smtp' => 'smtp', + 'sendmail' => 'sendmail', + 'mail' => 'mail'); +$conf_metadata['mail']['type']['attributes'] =''; + +$conf_metadata['mail']['from']['description'] = PLUGIN_MAIL_METADATA_ADDRESS_DESCRIPTION; +$conf_metadata['mail']['from']['type'] = 'text'; +$conf_metadata['mail']['from']['name'] = 'mail-from'; +$conf_metadata['mail']['from']['value'] = 'ortro@myserver.com'; +$conf_metadata['mail']['from']['attributes'] = 'size=30'; + +$conf_metadata['mail']['reply_to']['description'] = PLUGIN_MAIL_METADATA_REPLY_TO_DESCRIPTION; +$conf_metadata['mail']['reply_to']['type'] = 'text'; +$conf_metadata['mail']['reply_to']['name'] = 'mail-reply_to'; +$conf_metadata['mail']['reply_to']['value'] = 'ortro@myserver.com'; +$conf_metadata['mail']['reply_to']['attributes'] = 'size=30'; + +$conf_metadata['mail']['signature']['description'] = PLUGIN_MAIL_METADATA_SIGNATURE_DESCRIPTION; +$conf_metadata['mail']['signature']['type'] = 'textarea'; +$conf_metadata['mail']['signature']['name'] = 'mail-signature'; +$conf_metadata['mail']['signature']['value'] = '

--
This mail was generated automatically by Ortro. Please do not reply to it.
For further information please contact Ortro administrator.'; +$conf_metadata['mail']['signature']['attributes'] = 'rows=6 cols=70'; + +$conf_metadata['mail']['sendmail_path']['description'] = PLUGIN_MAIL_METADATA_PATH_DESCRIPTION; +$conf_metadata['mail']['sendmail_path']['type'] = 'text'; +$conf_metadata['mail']['sendmail_path']['name'] = 'mail-sendmail_path'; +$conf_metadata['mail']['sendmail_path']['value'] = ''; +$conf_metadata['mail']['sendmail_path']['attributes'] = 'size=30'; + +$conf_metadata['mail']['sendmail_args']['description'] = PLUGIN_MAIL_METADATA_PARAMETERS_DESCRIPTION; +$conf_metadata['mail']['sendmail_args']['type'] = 'text'; +$conf_metadata['mail']['sendmail_args']['name'] = 'mail-sendmail_args'; +$conf_metadata['mail']['sendmail_args']['value'] = ''; +$conf_metadata['mail']['sendmail_args']['attributes'] = 'size=30'; + +$conf_metadata['mail']['host']['description'] = PLUGIN_MAIL_METADATA_SERVER_DESCRIPTION; +$conf_metadata['mail']['host']['type'] = 'text'; +$conf_metadata['mail']['host']['name'] = 'mail-host'; +$conf_metadata['mail']['host']['value'] = 'localhost'; +$conf_metadata['mail']['host']['attributes'] = 'size=30'; + +$conf_metadata['mail']['port']['description'] = PLUGIN_MAIL_METADATA_PORT_DESCRIPTION; +$conf_metadata['mail']['port']['type'] = 'text'; +$conf_metadata['mail']['port']['name'] = 'mail-port'; +$conf_metadata['mail']['port']['value'] = '25'; +$conf_metadata['mail']['port']['attributes'] = 'size=30'; + +$conf_metadata['mail']['auth']['description'] = PLUGIN_MAIL_METADATA_SMTP_DESCRIPTION; +$conf_metadata['mail']['auth']['type'] = 'select'; +$conf_metadata['mail']['auth']['name'] = 'mail-auth'; +$conf_metadata['mail']['auth']['value'] = array('0' => 'false', + '1' => 'true'); +$conf_metadata['mail']['auth']['attributes'] = ''; + +$conf_metadata['mail']['username']['description'] = PLUGIN_MAIL_METADATA_USER_DESCRIPTION; +$conf_metadata['mail']['username']['type'] = 'text'; +$conf_metadata['mail']['username']['name'] = 'mail-username'; +$conf_metadata['mail']['username']['value'] = ''; +$conf_metadata['mail']['username']['attributes'] = 'size=30'; + +$conf_metadata['mail']['password']['description'] = PLUGIN_MAIL_METADATA_PASSWORD_DESCRIPTION; +$conf_metadata['mail']['password']['type'] = 'password'; +$conf_metadata['mail']['password']['name'] = 'mail-password'; +$conf_metadata['mail']['password']['value'] = ''; +$conf_metadata['mail']['password']['attributes'] = 'size=30'; + +$conf_metadata['mail']['localhost']['description'] = PLUGIN_MAIL_METADATA_HELO_DESCRIPTION; +$conf_metadata['mail']['localhost']['type'] = 'text'; +$conf_metadata['mail']['localhost']['name'] = 'mail-localhost'; +$conf_metadata['mail']['localhost']['value'] = php_uname('n'); +$conf_metadata['mail']['localhost']['attributes'] ='size=30'; + +$conf_metadata['mail']['timeout']['description'] = PLUGIN_MAIL_METADATA_TIMEOUT_DESCRIPTION; +$conf_metadata['mail']['timeout']['type'] = 'text'; +$conf_metadata['mail']['timeout']['name'] = 'mail-timeout'; +$conf_metadata['mail']['timeout']['value'] = ''; +$conf_metadata['mail']['timeout']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/notification/mail/core.php b/plugins/notification/mail/core.php new file mode 100644 index 0000000..097ee74 --- /dev/null +++ b/plugins/notification/mail/core.php @@ -0,0 +1,154 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; +set_include_path(ini_get("include_path") . ":" . + ORTRO_NOTIFICATION_PLUGINS. + "mail/lib/Pear/" + ); +require_once 'Mail.php'; +@require_once 'Mail/mime.php'; + +global $conf; +require_once ORTRO_CONF_PLUGINS . 'notification_mail.php'; + +/** + * Sends a notification using email. + * + * @param array $elements The user form values + * @param array $attachments The files to attach + * + * @return void + */ +function mailNotify($elements, $attachments) +{ + $logger = new LogUtil('mail_notification'); + $crlf = "\n"; + $recipients = array(); + + $headers = array('From' => $GLOBALS['conf']['mail']['from'], + 'Subject' => $elements['mail_subject']); + + if (isset($GLOBALS['conf']['mail']['reply_to']) && + $GLOBALS['conf']['mail']['reply_to'] != '') { + $headers['Reply-To'] = $GLOBALS['conf']['mail']['reply_to']; + } + + $logger->trace('DEBUG', "Sending mail with subject: " . + $elements['mail_subject']); + + if (isset($elements['mail_to'])) { + $headers['To'] = $elements['mail_to']; + $recipients['To'] = $elements['mail_to']; + } + + if (isset($elements['mail_cc'])) { + $headers['Cc'] = $elements['mail_cc']; + $recipients['Cc'] = $elements['mail_cc']; + } + + if (isset($elements['mail_bcc'])) { + $recipients['Bcc'] = $elements['mail_bcc']; + } + + $mime = new Mail_Mime($crlf); + + $txt_body = ''; + $html_body = ''; + + if (isset($elements['mail_text'])) { + $txt_body = $elements['mail_text']; + } + + if (isset($elements['mail_html'])) { + //fix FCKEditor strange behavior + $html_body = str_replace('\\\\\\\'', + "'", + $elements['mail_html']); + } + + if ($elements['mail_attach_result']=='1') { + if (array_key_exists('html', $attachments)) { + $html_body .= '

' . $attachments['html']; + } + + if (array_key_exists('file', $attachments)) { + foreach ($attachments['file'] as $file) { + $mime->addAttachment($file); + } + } + } + + if ($elements['mail_attach_timestamp']=='1') { + $txt_body .= "\n\n" . 'Date: ' . date('Y-m-d H:i'); + $html_body .= '

Date: ' . date('Y-m-d H:i'); + } + + //Add signature + $html_body .= $GLOBALS['conf']['mail']['signature']; + + $mime->setTxtBody($txt_body); + $mime->setHtmlBody($html_body); + + $body = $mime->get(); + + $hdrs = $mime->headers($headers); + + switch ($GLOBALS['conf']['mail']['type']) { + case 'sendmail': + $mail = &Mail::factory('sendmail', $GLOBALS['conf']['mail']); + break; + + case 'smtp': + switch ($GLOBALS['conf']['mail']['auth']) { + case '1': + $GLOBALS['conf']['mail']['auth'] = true; + break; + + case '0': + $GLOBALS['conf']['mail']['auth'] = false; + break; + + default: + break; + + } + + if (isset($GLOBALS['conf']['mail']['timeout']) && + $GLOBALS['conf']['mail']['timeout'] == '') { + $GLOBALS['conf']['mail']['timeout'] = null; + } + + $mail = &Mail::factory('smtp', $GLOBALS['conf']['mail']); + break; + + default: + $mail = &Mail::factory('mail'); + break; + } + + $ret = $mail->send($recipients, $hdrs, $body); + if (PEAR::isError($ret)) { + $logger->trace('DEBUG', "Delivery mail failed:" . $ret->getMessage()); + } + $logger->trace('DEBUG', 'Done.'); +} +?> \ No newline at end of file diff --git a/plugins/notification/mail/lib/Pear/Mail.php b/plugins/notification/mail/lib/Pear/Mail.php new file mode 100644 index 0000000..3a0c1a9 --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail.php @@ -0,0 +1,238 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Mail.php,v 1.17 2006/09/15 03:41:18 jon Exp $ + +require_once 'PEAR.php'; + +/** + * PEAR's Mail:: interface. Defines the interface for implementing + * mailers under the PEAR hierarchy, and provides supporting functions + * useful in multiple mailer backends. + * + * @access public + * @version $Revision: 1.17 $ + * @package Mail + */ +class Mail +{ + /** + * Line terminator used for separating header lines. + * @var string + */ + var $sep = "\r\n"; + + /** + * Provides an interface for generating Mail:: objects of various + * types + * + * @param string $driver The kind of Mail:: object to instantiate. + * @param array $params The parameters to pass to the Mail:: object. + * @return object Mail a instance of the driver class or if fails a PEAR Error + * @access public + */ + function &factory($driver, $params = array()) + { + $driver = strtolower($driver); + @include_once 'Mail/' . $driver . '.php'; + $class = 'Mail_' . $driver; + if (class_exists($class)) { + $mailer = new $class($params); + return $mailer; + } else { + return PEAR::raiseError('Unable to find class for driver ' . $driver); + } + } + + /** + * Implements Mail::send() function using php's built-in mail() + * command. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + * @deprecated use Mail_mail::send instead + */ + function send($recipients, $headers, $body) + { + $this->_sanitizeHeaders($headers); + + // if we're passed an array of recipients, implode it. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // get the Subject out of the headers array so that we can + // pass it as a seperate argument to mail(). + $subject = ''; + if (isset($headers['Subject'])) { + $subject = $headers['Subject']; + unset($headers['Subject']); + } + + // flatten the headers out. + list(,$text_headers) = Mail::prepareHeaders($headers); + + return mail($recipients, $subject, $body, $text_headers); + + } + + /** + * Sanitize an array of mail headers by removing any additional header + * strings present in a legitimate header's value. The goal of this + * filter is to prevent mail injection attacks. + * + * @param array $headers The associative array of headers to sanitize. + * + * @access private + */ + function _sanitizeHeaders(&$headers) + { + foreach ($headers as $key => $value) { + $headers[$key] = + preg_replace('=((||0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', + null, $value); + } + } + + /** + * Take an array of mail headers and return a string containing + * text usable in sending a message. + * + * @param array $headers The array of headers to prepare, in an associative + * array, where the array key is the header name (ie, + * 'Subject'), and the array value is the header + * value (ie, 'test'). The header produced from those + * values would be 'Subject: test'. + * + * @return mixed Returns false if it encounters a bad address, + * otherwise returns an array containing two + * elements: Any From: address found in the headers, + * and the plain text version of the headers. + * @access private + */ + function prepareHeaders($headers) + { + $lines = array(); + $from = null; + + foreach ($headers as $key => $value) { + if (strcasecmp($key, 'From') === 0) { + include_once 'Mail/RFC822.php'; + $parser = &new Mail_RFC822(); + $addresses = $parser->parseAddressList($value, 'localhost', false); + if (PEAR::isError($addresses)) { + return $addresses; + } + + $from = $addresses[0]->mailbox . '@' . $addresses[0]->host; + + // Reject envelope From: addresses with spaces. + if (strstr($from, ' ')) { + return false; + } + + $lines[] = $key . ': ' . $value; + } elseif (strcasecmp($key, 'Received') === 0) { + $received = array(); + if (is_array($value)) { + foreach ($value as $line) { + $received[] = $key . ': ' . $line; + } + } + else { + $received[] = $key . ': ' . $value; + } + // Put Received: headers at the top. Spam detectors often + // flag messages with Received: headers after the Subject: + // as spam. + $lines = array_merge($received, $lines); + } else { + // If $value is an array (i.e., a list of addresses), convert + // it to a comma-delimited string of its elements (addresses). + if (is_array($value)) { + $value = implode(', ', $value); + } + $lines[] = $key . ': ' . $value; + } + } + + return array($from, join($this->sep, $lines)); + } + + /** + * Take a set of recipients and parse them, returning an array of + * bare addresses (forward paths) that can be passed to sendmail + * or an smtp server with the rcpt to: command. + * + * @param mixed Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. + * + * @return mixed An array of forward paths (bare addresses) or a PEAR_Error + * object if the address list could not be parsed. + * @access private + */ + function parseRecipients($recipients) + { + include_once 'Mail/RFC822.php'; + + // if we're passed an array, assume addresses are valid and + // implode them before parsing. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // Parse recipients, leaving out all personal info. This is + // for smtp recipients, etc. All relevant personal information + // should already be in the headers. + $addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false); + + // If parseAddressList() returned a PEAR_Error object, just return it. + if (PEAR::isError($addresses)) { + return $addresses; + } + + $recipients = array(); + if (is_array($addresses)) { + foreach ($addresses as $ob) { + $recipients[] = $ob->mailbox . '@' . $ob->host; + } + } + + return $recipients; + } + +} diff --git a/plugins/notification/mail/lib/Pear/Mail/RFC822.php b/plugins/notification/mail/lib/Pear/Mail/RFC822.php new file mode 100644 index 0000000..aca910e --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/RFC822.php @@ -0,0 +1,923 @@ + | +// | Chuck Hagenbuch | +// +-----------------------------------------------------------------------+ + +/** + * RFC 822 Email address list validation Utility + * + * What is it? + * + * This class will take an address string, and parse it into it's consituent + * parts, be that either addresses, groups, or combinations. Nested groups + * are not supported. The structure it returns is pretty straight forward, + * and is similar to that provided by the imap_rfc822_parse_adrlist(). Use + * print_r() to view the structure. + * + * How do I use it? + * + * $address_string = 'My Group: "Richard" (A comment), ted@example.com (Ted Bloggs), Barney;'; + * $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true) + * print_r($structure); + * + * @author Richard Heyes + * @author Chuck Hagenbuch + * @version $Revision: 1.23 $ + * @license BSD + * @package Mail + */ +class Mail_RFC822 { + + /** + * The address being parsed by the RFC822 object. + * @var string $address + */ + var $address = ''; + + /** + * The default domain to use for unqualified addresses. + * @var string $default_domain + */ + var $default_domain = 'localhost'; + + /** + * Should we return a nested array showing groups, or flatten everything? + * @var boolean $nestGroups + */ + var $nestGroups = true; + + /** + * Whether or not to validate atoms for non-ascii characters. + * @var boolean $validate + */ + var $validate = true; + + /** + * The array of raw addresses built up as we parse. + * @var array $addresses + */ + var $addresses = array(); + + /** + * The final array of parsed address information that we build up. + * @var array $structure + */ + var $structure = array(); + + /** + * The current error message, if any. + * @var string $error + */ + var $error = null; + + /** + * An internal counter/pointer. + * @var integer $index + */ + var $index = null; + + /** + * The number of groups that have been found in the address list. + * @var integer $num_groups + * @access public + */ + var $num_groups = 0; + + /** + * A variable so that we can tell whether or not we're inside a + * Mail_RFC822 object. + * @var boolean $mailRFC822 + */ + var $mailRFC822 = true; + + /** + * A limit after which processing stops + * @var int $limit + */ + var $limit = null; + + /** + * Sets up the object. The address must either be set here or when + * calling parseAddressList(). One or the other. + * + * @access public + * @param string $address The address(es) to validate. + * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. + * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. + * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. + * + * @return object Mail_RFC822 A new Mail_RFC822 object. + */ + function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) + { + if (isset($address)) $this->address = $address; + if (isset($default_domain)) $this->default_domain = $default_domain; + if (isset($nest_groups)) $this->nestGroups = $nest_groups; + if (isset($validate)) $this->validate = $validate; + if (isset($limit)) $this->limit = $limit; + } + + /** + * Starts the whole process. The address must either be set here + * or when creating the object. One or the other. + * + * @access public + * @param string $address The address(es) to validate. + * @param string $default_domain Default domain/host etc. + * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. + * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. + * + * @return array A structured array of addresses. + */ + function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) + { + if (!isset($this) || !isset($this->mailRFC822)) { + $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); + return $obj->parseAddressList(); + } + + if (isset($address)) $this->address = $address; + if (isset($default_domain)) $this->default_domain = $default_domain; + if (isset($nest_groups)) $this->nestGroups = $nest_groups; + if (isset($validate)) $this->validate = $validate; + if (isset($limit)) $this->limit = $limit; + + $this->structure = array(); + $this->addresses = array(); + $this->error = null; + $this->index = null; + + // Unfold any long lines in $this->address. + $this->address = preg_replace('/\r?\n/', "\r\n", $this->address); + $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address); + + while ($this->address = $this->_splitAddresses($this->address)); + + if ($this->address === false || isset($this->error)) { + require_once 'PEAR.php'; + return PEAR::raiseError($this->error); + } + + // Validate each address individually. If we encounter an invalid + // address, stop iterating and return an error immediately. + foreach ($this->addresses as $address) { + $valid = $this->_validateAddress($address); + + if ($valid === false || isset($this->error)) { + require_once 'PEAR.php'; + return PEAR::raiseError($this->error); + } + + if (!$this->nestGroups) { + $this->structure = array_merge($this->structure, $valid); + } else { + $this->structure[] = $valid; + } + } + + return $this->structure; + } + + /** + * Splits an address into separate addresses. + * + * @access private + * @param string $address The addresses to split. + * @return boolean Success or failure. + */ + function _splitAddresses($address) + { + if (!empty($this->limit) && count($this->addresses) == $this->limit) { + return ''; + } + + if ($this->_isGroup($address) && !isset($this->error)) { + $split_char = ';'; + $is_group = true; + } elseif (!isset($this->error)) { + $split_char = ','; + $is_group = false; + } elseif (isset($this->error)) { + return false; + } + + // Split the string based on the above ten or so lines. + $parts = explode($split_char, $address); + $string = $this->_splitCheck($parts, $split_char); + + // If a group... + if ($is_group) { + // If $string does not contain a colon outside of + // brackets/quotes etc then something's fubar. + + // First check there's a colon at all: + if (strpos($string, ':') === false) { + $this->error = 'Invalid address: ' . $string; + return false; + } + + // Now check it's outside of brackets/quotes: + if (!$this->_splitCheck(explode(':', $string), ':')) { + return false; + } + + // We must have a group at this point, so increase the counter: + $this->num_groups++; + } + + // $string now contains the first full address/group. + // Add to the addresses array. + $this->addresses[] = array( + 'address' => trim($string), + 'group' => $is_group + ); + + // Remove the now stored address from the initial line, the +1 + // is to account for the explode character. + $address = trim(substr($address, strlen($string) + 1)); + + // If the next char is a comma and this was a group, then + // there are more addresses, otherwise, if there are any more + // chars, then there is another address. + if ($is_group && substr($address, 0, 1) == ','){ + $address = trim(substr($address, 1)); + return $address; + + } elseif (strlen($address) > 0) { + return $address; + + } else { + return ''; + } + + // If you got here then something's off + return false; + } + + /** + * Checks for a group at the start of the string. + * + * @access private + * @param string $address The address to check. + * @return boolean Whether or not there is a group at the start of the string. + */ + function _isGroup($address) + { + // First comma not in quotes, angles or escaped: + $parts = explode(',', $address); + $string = $this->_splitCheck($parts, ','); + + // Now we have the first address, we can reliably check for a + // group by searching for a colon that's not escaped or in + // quotes or angle brackets. + if (count($parts = explode(':', $string)) > 1) { + $string2 = $this->_splitCheck($parts, ':'); + return ($string2 !== $string); + } else { + return false; + } + } + + /** + * A common function that will check an exploded string. + * + * @access private + * @param array $parts The exloded string. + * @param string $char The char that was exploded on. + * @return mixed False if the string contains unclosed quotes/brackets, or the string on success. + */ + function _splitCheck($parts, $char) + { + $string = $parts[0]; + + for ($i = 0; $i < count($parts); $i++) { + if ($this->_hasUnclosedQuotes($string) + || $this->_hasUnclosedBrackets($string, '<>') + || $this->_hasUnclosedBrackets($string, '[]') + || $this->_hasUnclosedBrackets($string, '()') + || substr($string, -1) == '\\') { + if (isset($parts[$i + 1])) { + $string = $string . $char . $parts[$i + 1]; + } else { + $this->error = 'Invalid address spec. Unclosed bracket or quotes'; + return false; + } + } else { + $this->index = $i; + break; + } + } + + return $string; + } + + /** + * Checks if a string has an unclosed quotes or not. + * + * @access private + * @param string $string The string to check. + * @return boolean True if there are unclosed quotes inside the string, false otherwise. + */ + function _hasUnclosedQuotes($string) + { + $string = explode('"', $string); + $string_cnt = count($string); + + for ($i = 0; $i < (count($string) - 1); $i++) + if (substr($string[$i], -1) == '\\') + $string_cnt--; + + return ($string_cnt % 2 === 0); + } + + /** + * Checks if a string has an unclosed brackets or not. IMPORTANT: + * This function handles both angle brackets and square brackets; + * + * @access private + * @param string $string The string to check. + * @param string $chars The characters to check for. + * @return boolean True if there are unclosed brackets inside the string, false otherwise. + */ + function _hasUnclosedBrackets($string, $chars) + { + $num_angle_start = substr_count($string, $chars[0]); + $num_angle_end = substr_count($string, $chars[1]); + + $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]); + $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]); + + if ($num_angle_start < $num_angle_end) { + $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')'; + return false; + } else { + return ($num_angle_start > $num_angle_end); + } + } + + /** + * Sub function that is used only by hasUnclosedBrackets(). + * + * @access private + * @param string $string The string to check. + * @param integer &$num The number of occurences. + * @param string $char The character to count. + * @return integer The number of occurences of $char in $string, adjusted for backslashes. + */ + function _hasUnclosedBracketsSub($string, &$num, $char) + { + $parts = explode($char, $string); + for ($i = 0; $i < count($parts); $i++){ + if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) + $num--; + if (isset($parts[$i + 1])) + $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1]; + } + + return $num; + } + + /** + * Function to begin checking the address. + * + * @access private + * @param string $address The address to validate. + * @return mixed False on failure, or a structured array of address information on success. + */ + function _validateAddress($address) + { + $is_group = false; + $addresses = array(); + + if ($address['group']) { + $is_group = true; + + // Get the group part of the name + $parts = explode(':', $address['address']); + $groupname = $this->_splitCheck($parts, ':'); + $structure = array(); + + // And validate the group part of the name. + if (!$this->_validatePhrase($groupname)){ + $this->error = 'Group name did not validate.'; + return false; + } else { + // Don't include groups if we are not nesting + // them. This avoids returning invalid addresses. + if ($this->nestGroups) { + $structure = new stdClass; + $structure->groupname = $groupname; + } + } + + $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':'))); + } + + // If a group then split on comma and put into an array. + // Otherwise, Just put the whole address in an array. + if ($is_group) { + while (strlen($address['address']) > 0) { + $parts = explode(',', $address['address']); + $addresses[] = $this->_splitCheck($parts, ','); + $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ','))); + } + } else { + $addresses[] = $address['address']; + } + + // Check that $addresses is set, if address like this: + // Groupname:; + // Then errors were appearing. + if (!count($addresses)){ + $this->error = 'Empty group.'; + return false; + } + + // Trim the whitespace from all of the address strings. + array_map('trim', $addresses); + + // Validate each mailbox. + // Format could be one of: name + // geezer@domain.com + // geezer + // ... or any other format valid by RFC 822. + for ($i = 0; $i < count($addresses); $i++) { + if (!$this->validateMailbox($addresses[$i])) { + if (empty($this->error)) { + $this->error = 'Validation failed for: ' . $addresses[$i]; + } + return false; + } + } + + // Nested format + if ($this->nestGroups) { + if ($is_group) { + $structure->addresses = $addresses; + } else { + $structure = $addresses[0]; + } + + // Flat format + } else { + if ($is_group) { + $structure = array_merge($structure, $addresses); + } else { + $structure = $addresses; + } + } + + return $structure; + } + + /** + * Function to validate a phrase. + * + * @access private + * @param string $phrase The phrase to check. + * @return boolean Success or failure. + */ + function _validatePhrase($phrase) + { + // Splits on one or more Tab or space. + $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY); + + $phrase_parts = array(); + while (count($parts) > 0){ + $phrase_parts[] = $this->_splitCheck($parts, ' '); + for ($i = 0; $i < $this->index + 1; $i++) + array_shift($parts); + } + + foreach ($phrase_parts as $part) { + // If quoted string: + if (substr($part, 0, 1) == '"') { + if (!$this->_validateQuotedString($part)) { + return false; + } + continue; + } + + // Otherwise it's an atom: + if (!$this->_validateAtom($part)) return false; + } + + return true; + } + + /** + * Function to validate an atom which from rfc822 is: + * atom = 1* + * + * If validation ($this->validate) has been turned off, then + * validateAtom() doesn't actually check anything. This is so that you + * can split a list of addresses up before encoding personal names + * (umlauts, etc.), for example. + * + * @access private + * @param string $atom The string to check. + * @return boolean Success or failure. + */ + function _validateAtom($atom) + { + if (!$this->validate) { + // Validation has been turned off; assume the atom is okay. + return true; + } + + // Check for any char from ASCII 0 - ASCII 127 + if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) { + return false; + } + + // Check for specials: + if (preg_match('/[][()<>@,;\\:". ]/', $atom)) { + return false; + } + + // Check for control characters (ASCII 0-31): + if (preg_match('/[\\x00-\\x1F]+/', $atom)) { + return false; + } + + return true; + } + + /** + * Function to validate quoted string, which is: + * quoted-string = <"> *(qtext/quoted-pair) <"> + * + * @access private + * @param string $qstring The string to check + * @return boolean Success or failure. + */ + function _validateQuotedString($qstring) + { + // Leading and trailing " + $qstring = substr($qstring, 1, -1); + + // Perform check, removing quoted characters first. + return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring)); + } + + /** + * Function to validate a mailbox, which is: + * mailbox = addr-spec ; simple address + * / phrase route-addr ; name and route-addr + * + * @access public + * @param string &$mailbox The string to check. + * @return boolean Success or failure. + */ + function validateMailbox(&$mailbox) + { + // A couple of defaults. + $phrase = ''; + $comment = ''; + $comments = array(); + + // Catch any RFC822 comments and store them separately. + $_mailbox = $mailbox; + while (strlen(trim($_mailbox)) > 0) { + $parts = explode('(', $_mailbox); + $before_comment = $this->_splitCheck($parts, '('); + if ($before_comment != $_mailbox) { + // First char should be a (. + $comment = substr(str_replace($before_comment, '', $_mailbox), 1); + $parts = explode(')', $comment); + $comment = $this->_splitCheck($parts, ')'); + $comments[] = $comment; + + // +1 is for the trailing ) + $_mailbox = substr($_mailbox, strpos($_mailbox, $comment)+strlen($comment)+1); + } else { + break; + } + } + + foreach ($comments as $comment) { + $mailbox = str_replace("($comment)", '', $mailbox); + } + + $mailbox = trim($mailbox); + + // Check for name + route-addr + if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') { + $parts = explode('<', $mailbox); + $name = $this->_splitCheck($parts, '<'); + + $phrase = trim($name); + $route_addr = trim(substr($mailbox, strlen($name.'<'), -1)); + + if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) { + return false; + } + + // Only got addr-spec + } else { + // First snip angle brackets if present. + if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') { + $addr_spec = substr($mailbox, 1, -1); + } else { + $addr_spec = $mailbox; + } + + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } + + // Construct the object that will be returned. + $mbox = new stdClass(); + + // Add the phrase (even if empty) and comments + $mbox->personal = $phrase; + $mbox->comment = isset($comments) ? $comments : array(); + + if (isset($route_addr)) { + $mbox->mailbox = $route_addr['local_part']; + $mbox->host = $route_addr['domain']; + $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : ''; + } else { + $mbox->mailbox = $addr_spec['local_part']; + $mbox->host = $addr_spec['domain']; + } + + $mailbox = $mbox; + return true; + } + + /** + * This function validates a route-addr which is: + * route-addr = "<" [route] addr-spec ">" + * + * Angle brackets have already been removed at the point of + * getting to this function. + * + * @access private + * @param string $route_addr The string to check. + * @return mixed False on failure, or an array containing validated address/route information on success. + */ + function _validateRouteAddr($route_addr) + { + // Check for colon. + if (strpos($route_addr, ':') !== false) { + $parts = explode(':', $route_addr); + $route = $this->_splitCheck($parts, ':'); + } else { + $route = $route_addr; + } + + // If $route is same as $route_addr then the colon was in + // quotes or brackets or, of course, non existent. + if ($route === $route_addr){ + unset($route); + $addr_spec = $route_addr; + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } else { + // Validate route part. + if (($route = $this->_validateRoute($route)) === false) { + return false; + } + + $addr_spec = substr($route_addr, strlen($route . ':')); + + // Validate addr-spec part. + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } + + if (isset($route)) { + $return['adl'] = $route; + } else { + $return['adl'] = ''; + } + + $return = array_merge($return, $addr_spec); + return $return; + } + + /** + * Function to validate a route, which is: + * route = 1#("@" domain) ":" + * + * @access private + * @param string $route The string to check. + * @return mixed False on failure, or the validated $route on success. + */ + function _validateRoute($route) + { + // Split on comma. + $domains = explode(',', trim($route)); + + foreach ($domains as $domain) { + $domain = str_replace('@', '', trim($domain)); + if (!$this->_validateDomain($domain)) return false; + } + + return $route; + } + + /** + * Function to validate a domain, though this is not quite what + * you expect of a strict internet domain. + * + * domain = sub-domain *("." sub-domain) + * + * @access private + * @param string $domain The string to check. + * @return mixed False on failure, or the validated domain on success. + */ + function _validateDomain($domain) + { + // Note the different use of $subdomains and $sub_domains + $subdomains = explode('.', $domain); + + while (count($subdomains) > 0) { + $sub_domains[] = $this->_splitCheck($subdomains, '.'); + for ($i = 0; $i < $this->index + 1; $i++) + array_shift($subdomains); + } + + foreach ($sub_domains as $sub_domain) { + if (!$this->_validateSubdomain(trim($sub_domain))) + return false; + } + + // Managed to get here, so return input. + return $domain; + } + + /** + * Function to validate a subdomain: + * subdomain = domain-ref / domain-literal + * + * @access private + * @param string $subdomain The string to check. + * @return boolean Success or failure. + */ + function _validateSubdomain($subdomain) + { + if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){ + if (!$this->_validateDliteral($arr[1])) return false; + } else { + if (!$this->_validateAtom($subdomain)) return false; + } + + // Got here, so return successful. + return true; + } + + /** + * Function to validate a domain literal: + * domain-literal = "[" *(dtext / quoted-pair) "]" + * + * @access private + * @param string $dliteral The string to check. + * @return boolean Success or failure. + */ + function _validateDliteral($dliteral) + { + return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\'; + } + + /** + * Function to validate an addr-spec. + * + * addr-spec = local-part "@" domain + * + * @access private + * @param string $addr_spec The string to check. + * @return mixed False on failure, or the validated addr-spec on success. + */ + function _validateAddrSpec($addr_spec) + { + $addr_spec = trim($addr_spec); + + // Split on @ sign if there is one. + if (strpos($addr_spec, '@') !== false) { + $parts = explode('@', $addr_spec); + $local_part = $this->_splitCheck($parts, '@'); + $domain = substr($addr_spec, strlen($local_part . '@')); + + // No @ sign so assume the default domain. + } else { + $local_part = $addr_spec; + $domain = $this->default_domain; + } + + if (($local_part = $this->_validateLocalPart($local_part)) === false) return false; + if (($domain = $this->_validateDomain($domain)) === false) return false; + + // Got here so return successful. + return array('local_part' => $local_part, 'domain' => $domain); + } + + /** + * Function to validate the local part of an address: + * local-part = word *("." word) + * + * @access private + * @param string $local_part + * @return mixed False on failure, or the validated local part on success. + */ + function _validateLocalPart($local_part) + { + $parts = explode('.', $local_part); + $words = array(); + + // Split the local_part into words. + while (count($parts) > 0){ + $words[] = $this->_splitCheck($parts, '.'); + for ($i = 0; $i < $this->index + 1; $i++) { + array_shift($parts); + } + } + + // Validate each word. + foreach ($words as $word) { + // If this word contains an unquoted space, it is invalid. (6.2.4) + if (strpos($word, ' ') && $word[0] !== '"') + { + return false; + } + + if ($this->_validatePhrase(trim($word)) === false) return false; + } + + // Managed to get here, so return the input. + return $local_part; + } + + /** + * Returns an approximate count of how many addresses are in the + * given string. This is APPROXIMATE as it only splits based on a + * comma which has no preceding backslash. Could be useful as + * large amounts of addresses will end up producing *large* + * structures when used with parseAddressList(). + * + * @param string $data Addresses to count + * @return int Approximate count + */ + function approximateCount($data) + { + return count(preg_split('/(?@. This can be sufficient for most + * people. Optional stricter mode can be utilised which restricts + * mailbox characters allowed to alphanumeric, full stop, hyphen + * and underscore. + * + * @param string $data Address to check + * @param boolean $strict Optional stricter mode + * @return mixed False if it fails, an indexed array + * username/domain if it matches + */ + function isValidInetAddress($data, $strict = false) + { + $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i'; + if (preg_match($regex, trim($data), $matches)) { + return array($matches[1], $matches[2]); + } else { + return false; + } + } + +} diff --git a/plugins/notification/mail/lib/Pear/Mail/mail.php b/plugins/notification/mail/lib/Pear/Mail/mail.php new file mode 100644 index 0000000..2273f93 --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/mail.php @@ -0,0 +1,142 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mail.php,v 1.18 2006/09/13 05:32:08 jon Exp $ + +/** + * internal PHP-mail() implementation of the PEAR Mail:: interface. + * @package Mail + * @version $Revision: 1.18 $ + */ +class Mail_mail extends Mail { + + /** + * Any arguments to pass to the mail() function. + * @var string + */ + var $_params = ''; + + /** + * Constructor. + * + * Instantiates a new Mail_mail:: object based on the parameters + * passed in. + * + * @param array $params Extra arguments for the mail() function. + */ + function Mail_mail($params = null) + { + /* The other mail implementations accept parameters as arrays. + * In the interest of being consistent, explode an array into + * a string of parameter arguments. */ + if (is_array($params)) { + $this->_params = join(' ', $params); + } else { + $this->_params = $params; + } + + /* Because the mail() function may pass headers as command + * line arguments, we can't guarantee the use of the standard + * "\r\n" separator. Instead, we use the system's native line + * separator. */ + if (defined('PHP_EOL')) { + $this->sep = PHP_EOL; + } else { + $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; + } + } + + /** + * Implements Mail_mail::send() function using php's built-in mail() + * command. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * + * @access public + */ + function send($recipients, $headers, $body) + { + $this->_sanitizeHeaders($headers); + + // If we're passed an array of recipients, implode it. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // Get the Subject out of the headers array so that we can + // pass it as a seperate argument to mail(). + $subject = ''; + if (isset($headers['Subject'])) { + $subject = $headers['Subject']; + unset($headers['Subject']); + } + + /* + * Also remove the To: header. The mail() function will add its own + * To: header based on the contents of $recipients. + */ + unset($headers['To']); + + // Flatten the headers out. + $headerElements = $this->prepareHeaders($headers); + if (PEAR::isError($headerElements)) { + return $headerElements; + } + list(, $text_headers) = $headerElements; + + /* + * We only use mail()'s optional fifth parameter if the additional + * parameters have been provided and we're not running in safe mode. + */ + if (empty($this->_params) || ini_get('safe_mode')) { + $result = mail($recipients, $subject, $body, $text_headers); + } else { + $result = mail($recipients, $subject, $body, $text_headers, + $this->_params); + } + + /* + * If the mail() function returned failure, we need to create a + * PEAR_Error object and return it instead of the boolean result. + */ + if ($result === false) { + $result = PEAR::raiseError('mail() returned failure'); + } + + return $result; + } + +} diff --git a/plugins/notification/mail/lib/Pear/Mail/mime.php b/plugins/notification/mail/lib/Pear/Mail/mime.php new file mode 100644 index 0000000..2286920 --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/mime.php @@ -0,0 +1,1095 @@ + + * Copyright (c) 2003-2006, PEAR + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the authors, nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * @category Mail + * @package Mail_Mime + * @author Richard Heyes + * @author Tomas V.V. Cox + * @author Cipriano Groenendal + * @author Sean Coates + * @copyright 2003-2006 PEAR + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version CVS: $Id: mime.php,v 1.81 2007/06/21 19:08:28 cipri Exp $ + * @link http://pear.php.net/package/Mail_mime + * + * This class is based on HTML Mime Mail class from + * Richard Heyes which was based also + * in the mime_mail.class by Tobias Ratschiller + * and Sascha Schumann + */ + + +/** + * require PEAR + * + * This package depends on PEAR to raise errors. + */ +require_once 'PEAR.php'; + +/** + * require Mail_mimePart + * + * Mail_mimePart contains the code required to + * create all the different parts a mail can + * consist of. + */ +require_once 'Mail/mimePart.php'; + + +/** + * The Mail_Mime class provides an OO interface to create MIME + * enabled email messages. This way you can create emails that + * contain plain-text bodies, HTML bodies, attachments, inline + * images and specific headers. + * + * @category Mail + * @package Mail_Mime + * @author Richard Heyes + * @author Tomas V.V. Cox + * @author Cipriano Groenendal + * @author Sean Coates + * @copyright 2003-2006 PEAR + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Mail_mime + */ +class Mail_mime +{ + /** + * Contains the plain text part of the email + * + * @var string + * @access private + */ + var $_txtbody; + + /** + * Contains the html part of the email + * + * @var string + * @access private + */ + var $_htmlbody; + + /** + * contains the mime encoded text + * + * @var string + * @access private + */ + var $_mime; + + /** + * contains the multipart content + * + * @var string + * @access private + */ + var $_multipart; + + /** + * list of the attached images + * + * @var array + * @access private + */ + var $_html_images = array(); + + /** + * list of the attachements + * + * @var array + * @access private + */ + var $_parts = array(); + + /** + * Build parameters + * + * @var array + * @access private + */ + var $_build_params = array(); + + /** + * Headers for the mail + * + * @var array + * @access private + */ + var $_headers = array(); + + /** + * End Of Line sequence (for serialize) + * + * @var string + * @access private + */ + var $_eol; + + + /** + * Constructor function. + * + * @param string $crlf what type of linebreak to use. + * Defaults to "\r\n" + * + * @return void + * + * @access public + */ + function Mail_mime($crlf = "\r\n") + { + $this->_setEOL($crlf); + $this->_build_params = array( + 'head_encoding' => 'quoted-printable', + 'text_encoding' => '7bit', + 'html_encoding' => 'quoted-printable', + '7bit_wrap' => 998, + 'html_charset' => 'ISO-8859-1', + 'text_charset' => 'ISO-8859-1', + 'head_charset' => 'ISO-8859-1' + ); + } + + /** + * wakeup function called by unserialize. It re-sets the EOL constant + * + * @access private + * @return void + */ + function __wakeup() + { + $this->_setEOL($this->_eol); + } + + + /** + * Accessor function to set the body text. Body text is used if + * it's not an html mail being sent or else is used to fill the + * text/plain part that emails clients who don't support + * html should show. + * + * @param string $data Either a string or + * the file name with the contents + * @param bool $isfile If true the first param should be treated + * as a file name, else as a string (default) + * @param bool $append If true the text or file is appended to + * the existing body, else the old body is + * overwritten + * + * @return mixed true on success or PEAR_Error object + * @access public + */ + function setTXTBody($data, $isfile = false, $append = false) + { + if (!$isfile) { + if (!$append) { + $this->_txtbody = $data; + } else { + $this->_txtbody .= $data; + } + } else { + $cont = $this->_file2str($data); + if (PEAR::isError($cont)) { + return $cont; + } + if (!$append) { + $this->_txtbody = $cont; + } else { + $this->_txtbody .= $cont; + } + } + return true; + } + + /** + * Adds a html part to the mail. + * + * @param string $data either a string or the file name with the + * contents + * @param bool $isfile a flag that determines whether $data is a + * filename, or a string(false, default) + * + * @return bool true on success + * @access public + */ + function setHTMLBody($data, $isfile = false) + { + if (!$isfile) { + $this->_htmlbody = $data; + } else { + $cont = $this->_file2str($data); + if (PEAR::isError($cont)) { + return $cont; + } + $this->_htmlbody = $cont; + } + + return true; + } + + /** + * Adds an image to the list of embedded images. + * + * @param string $file the image file name OR image data itself + * @param string $c_type the content type + * @param string $name the filename of the image. + * Only used if $file is the image data. + * @param bool $isfile whether $file is a filename or not. + * Defaults to true + * + * @return bool true on success + * @access public + */ + function addHTMLImage($file, $c_type='application/octet-stream', + $name = '', $isfile = true) + { + $filedata = ($isfile === true) ? $this->_file2str($file) + : $file; + if ($isfile === true) { + $filename = ($name == '' ? $file : $name); + } else { + $filename = $name; + } + if (PEAR::isError($filedata)) { + return $filedata; + } + $this->_html_images[] = array( + 'body' => $filedata, + 'name' => $filename, + 'c_type' => $c_type, + 'cid' => md5(uniqid(time())) + ); + return true; + } + + /** + * Adds a file to the list of attachments. + * + * @param string $file The file name of the file to attach + * OR the file contents itself + * @param string $c_type The content type + * @param string $name The filename of the attachment + * Only use if $file is the contents + * @param bool $isfile Whether $file is a filename or not + * Defaults to true + * @param string $encoding The type of encoding to use. + * Defaults to base64. + * Possible values: 7bit, 8bit, base64, + * or quoted-printable. + * @param string $disposition The content-disposition of this file + * Defaults to attachment. + * Possible values: attachment, inline. + * @param string $charset The character set used in the filename + * of this attachment. + * @param string $language The language of the attachment + * @param string $location The RFC 2557.4 location of the attachment + * + * @return mixed true on success or PEAR_Error object + * @access public + */ + function addAttachment($file, + $c_type = 'application/octet-stream', + $name = '', + $isfile = true, + $encoding = 'base64', + $disposition = 'attachment', + $charset = '', + $language = '', + $location = '') + { + $filedata = ($isfile === true) ? $this->_file2str($file) + : $file; + if ($isfile === true) { + // Force the name the user supplied, otherwise use $file + $filename = (strlen($name)) ? $name : $file; + } else { + $filename = $name; + } + if (!strlen($filename)) { + $msg = "The supplied filename for the attachment can't be empty"; + $err = PEAR::raiseError($msg); + return $err; + } + $filename = basename($filename); + if (PEAR::isError($filedata)) { + return $filedata; + } + + $this->_parts[] = array( + 'body' => $filedata, + 'name' => $filename, + 'c_type' => $c_type, + 'encoding' => $encoding, + 'charset' => $charset, + 'language' => $language, + 'location' => $location, + 'disposition' => $disposition + ); + return true; + } + + /** + * Get the contents of the given file name as string + * + * @param string $file_name path of file to process + * + * @return string contents of $file_name + * @access private + */ + function &_file2str($file_name) + { + if (!is_readable($file_name)) { + $err = PEAR::raiseError('File is not readable ' . $file_name); + return $err; + } + if (!$fd = fopen($file_name, 'rb')) { + $err = PEAR::raiseError('Could not open ' . $file_name); + return $err; + } + $filesize = filesize($file_name); + if ($filesize == 0) { + $cont = ""; + } else { + if ($magic_quote_setting = get_magic_quotes_runtime()) { + set_magic_quotes_runtime(0); + } + $cont = fread($fd, $filesize); + if ($magic_quote_setting) { + set_magic_quotes_runtime($magic_quote_setting); + } + } + fclose($fd); + return $cont; + } + + /** + * Adds a text subpart to the mimePart object and + * returns it during the build process. + * + * @param mixed &$obj The object to add the part to, or + * null if a new object is to be created. + * @param string $text The text to add. + * + * @return object The text mimePart object + * @access private + */ + function &_addTextPart(&$obj, $text) + { + $params['content_type'] = 'text/plain'; + $params['encoding'] = $this->_build_params['text_encoding']; + $params['charset'] = $this->_build_params['text_charset']; + if (is_object($obj)) { + $ret = $obj->addSubpart($text, $params); + return $ret; + } else { + $ret = new Mail_mimePart($text, $params); + return $ret; + } + } + + /** + * Adds a html subpart to the mimePart object and + * returns it during the build process. + * + * @param mixed &$obj The object to add the part to, or + * null if a new object is to be created. + * + * @return object The html mimePart object + * @access private + */ + function &_addHtmlPart(&$obj) + { + $params['content_type'] = 'text/html'; + $params['encoding'] = $this->_build_params['html_encoding']; + $params['charset'] = $this->_build_params['html_charset']; + if (is_object($obj)) { + $ret = $obj->addSubpart($this->_htmlbody, $params); + return $ret; + } else { + $ret = new Mail_mimePart($this->_htmlbody, $params); + return $ret; + } + } + + /** + * Creates a new mimePart object, using multipart/mixed as + * the initial content-type and returns it during the + * build process. + * + * @return object The multipart/mixed mimePart object + * @access private + */ + function &_addMixedPart() + { + $params = array(); + $params['content_type'] = 'multipart/mixed'; + + //Create empty multipart/mixed Mail_mimePart object to return + $ret = new Mail_mimePart('', $params); + return $ret; + } + + /** + * Adds a multipart/alternative part to a mimePart + * object (or creates one), and returns it during + * the build process. + * + * @param mixed &$obj The object to add the part to, or + * null if a new object is to be created. + * + * @return object The multipart/mixed mimePart object + * @access private + */ + function &_addAlternativePart(&$obj) + { + $params['content_type'] = 'multipart/alternative'; + if (is_object($obj)) { + return $obj->addSubpart('', $params); + } else { + $ret = new Mail_mimePart('', $params); + return $ret; + } + } + + /** + * Adds a multipart/related part to a mimePart + * object (or creates one), and returns it during + * the build process. + * + * @param mixed &$obj The object to add the part to, or + * null if a new object is to be created + * + * @return object The multipart/mixed mimePart object + * @access private + */ + function &_addRelatedPart(&$obj) + { + $params['content_type'] = 'multipart/related'; + if (is_object($obj)) { + return $obj->addSubpart('', $params); + } else { + $ret = new Mail_mimePart('', $params); + return $ret; + } + } + + /** + * Adds an html image subpart to a mimePart object + * and returns it during the build process. + * + * @param object &$obj The mimePart to add the image to + * @param array $value The image information + * + * @return object The image mimePart object + * @access private + */ + function &_addHtmlImagePart(&$obj, $value) + { + $params['content_type'] = $value['c_type']; + $params['encoding'] = 'base64'; + $params['disposition'] = 'inline'; + $params['dfilename'] = $value['name']; + $params['cid'] = $value['cid']; + + $ret = $obj->addSubpart($value['body'], $params); + return $ret; + + } + + /** + * Adds an attachment subpart to a mimePart object + * and returns it during the build process. + * + * @param object &$obj The mimePart to add the image to + * @param array $value The attachment information + * + * @return object The image mimePart object + * @access private + */ + function &_addAttachmentPart(&$obj, $value) + { + $params['dfilename'] = $value['name']; + $params['encoding'] = $value['encoding']; + if ($value['charset']) { + $params['charset'] = $value['charset']; + } + if ($value['language']) { + $params['language'] = $value['language']; + } + if ($value['location']) { + $params['location'] = $value['location']; + } + $params['content_type'] = $value['c_type']; + $params['disposition'] = isset($value['disposition']) ? + $value['disposition'] : 'attachment'; + $ret = $obj->addSubpart($value['body'], $params); + return $ret; + } + + /** + * Returns the complete e-mail, ready to send using an alternative + * mail delivery method. Note that only the mailpart that is made + * with Mail_Mime is created. This means that, + * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF + * using the $xtra_headers parameter! + * + * @param string $separation The separation etween these two parts. + * @param array $build_params The Build parameters passed to the + * &get() function. See &get for more info. + * @param array $xtra_headers The extra headers that should be passed + * to the &headers() function. + * See that function for more info. + * @param bool $overwrite Overwrite the existing headers with new. + * + * @return string The complete e-mail. + * @access public + */ + function getMessage( + $separation = null, + $build_params = null, + $xtra_headers = null, + $overwrite = false + ) + { + if ($separation === null) { + $separation = MAIL_MIME_CRLF; + } + $body = $this->get($build_params); + $head = $this->txtHeaders($xtra_headers, $overwrite); + $mail = $head . $separation . $body; + return $mail; + } + + + /** + * Builds the multipart message from the list ($this->_parts) and + * returns the mime content. + * + * @param array $build_params Build parameters that change the way the email + * is built. Should be associative. Can contain: + * head_encoding - What encoding to use for the headers. + * Options: quoted-printable or base64 + * Default is quoted-printable + * text_encoding - What encoding to use for plain text + * Options: 7bit, 8bit, + * base64, or quoted-printable + * Default is 7bit + * html_encoding - What encoding to use for html + * Options: 7bit, 8bit, + * base64, or quoted-printable + * Default is quoted-printable + * 7bit_wrap - Number of characters before text is + * wrapped in 7bit encoding + * Default is 998 + * html_charset - The character set to use for html. + * Default is iso-8859-1 + * text_charset - The character set to use for text. + * Default is iso-8859-1 + * head_charset - The character set to use for headers. + * Default is iso-8859-1 + * + * @return string The mime content + * @access public + */ + function &get($build_params = null) + { + if (isset($build_params)) { + while (list($key, $value) = each($build_params)) { + $this->_build_params[$key] = $value; + } + } + + if (isset($this->_headers['From'])){ + $domain = @strstr($this->_headers['From'],'@'); + //Bug #11381: Illegal characters in domain ID + $domain = str_replace(array("<", ">", "&", "(", ")", " ", "\"", "'"), "", $domain); + $domain = urlencode($domain); + foreach($this->_html_images as $i => $img){ + $this->_html_images[$i]['cid'] = $this->_html_images[$i]['cid'] . $domain; + } + } + + if (count($this->_html_images) AND isset($this->_htmlbody)) { + foreach ($this->_html_images as $key => $value) { + $regex = array(); + $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' . + preg_quote($value['name'], '#') . '\3#'; + $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' . + preg_quote($value['name'], '#') . '\1\s*\)#'; + + $rep = array(); + $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3'; + $rep[] = 'url(\1cid:' . $value['cid'] . '\2)'; + + $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody); + $this->_html_images[$key]['name'] = + basename($this->_html_images[$key]['name']); + } + } + + $null = null; + $attachments = count($this->_parts) ? true : false; + $html_images = count($this->_html_images) ? true : false; + $html = strlen($this->_htmlbody) ? true : false; + $text = (!$html AND strlen($this->_txtbody)) ? true : false; + + switch (true) { + case $text AND !$attachments: + $message =& $this->_addTextPart($null, $this->_txtbody); + break; + + case !$text AND !$html AND $attachments: + $message =& $this->_addMixedPart(); + for ($i = 0; $i < count($this->_parts); $i++) { + $this->_addAttachmentPart($message, $this->_parts[$i]); + } + break; + + case $text AND $attachments: + $message =& $this->_addMixedPart(); + $this->_addTextPart($message, $this->_txtbody); + for ($i = 0; $i < count($this->_parts); $i++) { + $this->_addAttachmentPart($message, $this->_parts[$i]); + } + break; + + case $html AND !$attachments AND !$html_images: + if (isset($this->_txtbody)) { + $message =& $this->_addAlternativePart($null); + $this->_addTextPart($message, $this->_txtbody); + $this->_addHtmlPart($message); + } else { + $message =& $this->_addHtmlPart($null); + } + break; + + case $html AND !$attachments AND $html_images: + $message =& $this->_addRelatedPart($null); + if (isset($this->_txtbody)) { + $alt =& $this->_addAlternativePart($message); + $this->_addTextPart($alt, $this->_txtbody); + $this->_addHtmlPart($alt); + } else { + $this->_addHtmlPart($message); + } + for ($i = 0; $i < count($this->_html_images); $i++) { + $this->_addHtmlImagePart($message, $this->_html_images[$i]); + } + break; + + case $html AND $attachments AND !$html_images: + $message =& $this->_addMixedPart(); + if (isset($this->_txtbody)) { + $alt =& $this->_addAlternativePart($message); + $this->_addTextPart($alt, $this->_txtbody); + $this->_addHtmlPart($alt); + } else { + $this->_addHtmlPart($message); + } + for ($i = 0; $i < count($this->_parts); $i++) { + $this->_addAttachmentPart($message, $this->_parts[$i]); + } + break; + + case $html AND $attachments AND $html_images: + $message =& $this->_addMixedPart(); + if (isset($this->_txtbody)) { + $alt =& $this->_addAlternativePart($message); + $this->_addTextPart($alt, $this->_txtbody); + $rel =& $this->_addRelatedPart($alt); + } else { + $rel =& $this->_addRelatedPart($message); + } + $this->_addHtmlPart($rel); + for ($i = 0; $i < count($this->_html_images); $i++) { + $this->_addHtmlImagePart($rel, $this->_html_images[$i]); + } + for ($i = 0; $i < count($this->_parts); $i++) { + $this->_addAttachmentPart($message, $this->_parts[$i]); + } + break; + + } + + if (isset($message)) { + $output = $message->encode(); + + $this->_headers = array_merge($this->_headers, + $output['headers']); + $body = $output['body']; + return $body; + + } else { + $ret = false; + return $ret; + } + } + + /** + * Returns an array with the headers needed to prepend to the email + * (MIME-Version and Content-Type). Format of argument is: + * $array['header-name'] = 'header-value'; + * + * @param array $xtra_headers Assoc array with any extra headers. + * Optional. + * @param bool $overwrite Overwrite already existing headers. + * + * @return array Assoc array with the mime headers + * @access public + */ + function &headers($xtra_headers = null, $overwrite = false) + { + // Content-Type header should already be present, + // So just add mime version header + $headers['MIME-Version'] = '1.0'; + if (isset($xtra_headers)) { + $headers = array_merge($headers, $xtra_headers); + } + if ($overwrite) { + $this->_headers = array_merge($this->_headers, $headers); + } else { + $this->_headers = array_merge($headers, $this->_headers); + } + + $encodedHeaders = $this->_encodeHeaders($this->_headers); + return $encodedHeaders; + } + + /** + * Get the text version of the headers + * (usefull if you want to use the PHP mail() function) + * + * @param array $xtra_headers Assoc array with any extra headers. + * Optional. + * @param bool $overwrite Overwrite the existing heaers with new. + * + * @return string Plain text headers + * @access public + */ + function txtHeaders($xtra_headers = null, $overwrite = false) + { + $headers = $this->headers($xtra_headers, $overwrite); + + $ret = ''; + foreach ($headers as $key => $val) { + $ret .= "$key: $val" . MAIL_MIME_CRLF; + } + return $ret; + } + + /** + * Sets the Subject header + * + * @param string $subject String to set the subject to. + * + * @return void + * @access public + */ + function setSubject($subject) + { + $this->_headers['Subject'] = $subject; + } + + /** + * Set an email to the From (the sender) header + * + * @param string $email The email address to use + * + * @return void + * @access public + */ + function setFrom($email) + { + $this->_headers['From'] = $email; + } + + /** + * Add an email to the Cc (carbon copy) header + * (multiple calls to this method are allowed) + * + * @param string $email The email direction to add + * + * @return void + * @access public + */ + function addCc($email) + { + if (isset($this->_headers['Cc'])) { + $this->_headers['Cc'] .= ", $email"; + } else { + $this->_headers['Cc'] = $email; + } + } + + /** + * Add an email to the Bcc (blank carbon copy) header + * (multiple calls to this method are allowed) + * + * @param string $email The email direction to add + * + * @return void + * @access public + */ + function addBcc($email) + { + if (isset($this->_headers['Bcc'])) { + $this->_headers['Bcc'] .= ", $email"; + } else { + $this->_headers['Bcc'] = $email; + } + } + + /** + * Since the PHP send function requires you to specifiy + * recipients (To: header) separately from the other + * headers, the To: header is not properly encoded. + * To fix this, you can use this public method to + * encode your recipients before sending to the send + * function + * + * @param string $recipients A comma-delimited list of recipients + * + * @return string Encoded data + * @access public + */ + function encodeRecipients($recipients) + { + $input = array("To" => $recipients); + $retval = $this->_encodeHeaders($input); + return $retval["To"] ; + } + + /** + * Encodes a header as per RFC2047 + * + * @param array $input The header data to encode + * @param array $params Extra build parameters + * + * @return array Encoded data + * @access private + */ + function _encodeHeaders($input, $params = array()) + { + + $build_params = $this->_build_params; + while (list($key, $value) = each($params)) { + $build_params[$key] = $value; + } + //$hdr_name: Name of the heaer + //$hdr_value: Full line of header value. + //$hdr_value_out: The recombined $hdr_val-atoms, or the encoded string. + + $useIconv = true; + if (isset($build_params['ignore-iconv'])) { + $useIconv = !$build_params['ignore-iconv']; + } + foreach ($input as $hdr_name => $hdr_value) { + if (preg_match('#([\x80-\xFF]){1}#', $hdr_value)) { + if (function_exists('iconv_mime_encode') && $useIconv) { + $imePrefs = array(); + if ($build_params['head_encoding'] == 'base64') { + $imePrefs['scheme'] = 'B'; + } else { + $imePrefs['scheme'] = 'Q'; + } + $imePrefs['input-charset'] = $build_params['head_charset']; + $imePrefs['output-charset'] = $build_params['head_charset']; + $imePrefs['line-length'] = 74; + $imePrefs['line-break-chars'] = "\r\n"; //Specified in RFC2047 + + $hdr_value = iconv_mime_encode($hdr_name, $hdr_value, $imePrefs); + $hdr_value = preg_replace("#^{$hdr_name}\:\ #", "", $hdr_value); + } elseif ($build_params['head_encoding'] == 'base64') { + //Base64 encoding has been selected. + //Base64 encode the entire string + $hdr_value = base64_encode($hdr_value); + + //Generate the header using the specified params and dynamicly + //determine the maximum length of such strings. + //75 is the value specified in the RFC. The first -2 is there so + //the later regexp doesn't break any of the translated chars. + //The -2 on the first line-regexp is to compensate for the ": " + //between the header-name and the header value + $prefix = '=?' . $build_params['head_charset'] . '?B?'; + $suffix = '?='; + $maxLength = 75 - strlen($prefix . $suffix) - 2; + $maxLength1stLine = $maxLength - strlen($hdr_name) - 2; + + //We can cut base4 every 4 characters, so the real max + //we can get must be rounded down. + $maxLength = $maxLength - ($maxLength % 4); + $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4); + + $cutpoint = $maxLength1stLine; + $hdr_value_out = $hdr_value; + $output = ""; + while ($hdr_value_out) { + //Split translated string at every $maxLength + $part = substr($hdr_value_out, 0, $cutpoint); + $hdr_value_out = substr($hdr_value_out, $cutpoint); + $cutpoint = $maxLength; + //RFC 2047 specifies that any split header should + //be seperated by a CRLF SPACE. + if ($output) { + $output .= "\r\n "; + } + $output .= $prefix . $part . $suffix; + } + $hdr_value = $output; + } else { + //quoted-printable encoding has been selected + + //Fix for Bug #10298, Ota Mares + //Check if there is a double quote at beginning or end of + //the string to prevent that an open or closing quote gets + //ignored because it is encapsuled by an encoding pre/suffix. + //Remove the double quote and set the specific prefix or + //suffix variable so that we can concat the encoded string and + //the double quotes back together to get the intended string. + $quotePrefix = $quoteSuffix = ''; + if ($hdr_value{0} == '"') { + $hdr_value = substr($hdr_value, 1); + $quotePrefix = '"'; + } + if ($hdr_value{strlen($hdr_value)-1} == '"') { + $hdr_value = substr($hdr_value, 0, -1); + $quoteSuffix = '"'; + } + + //Generate the header using the specified params and dynamicly + //determine the maximum length of such strings. + //75 is the value specified in the RFC. The -2 is there so + //the later regexp doesn't break any of the translated chars. + //The -2 on the first line-regexp is to compensate for the ": " + //between the header-name and the header value + $prefix = '=?' . $build_params['head_charset'] . '?Q?'; + $suffix = '?='; + $maxLength = 75 - strlen($prefix . $suffix) - 2 - 1; + $maxLength1stLine = $maxLength - strlen($hdr_name) - 2; + $maxLength = $maxLength - 1; + + //Replace all special characters used by the encoder. + $search = array('=', '_', '?', ' '); + $replace = array('=3D', '=5F', '=3F', '_'); + $hdr_value = str_replace($search, $replace, $hdr_value); + + //Replace all extended characters (\x80-xFF) with their + //ASCII values. + $hdr_value = preg_replace('#([\x80-\xFF])#e', + '"=" . strtoupper(dechex(ord("\1")))', + $hdr_value); + + //This regexp will break QP-encoded text at every $maxLength + //but will not break any encoded letters. + $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|"; + $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|"; + //Fix for Bug #10298, Ota Mares + //Concat the double quotes and encoded string together + $hdr_value = $quotePrefix . $hdr_value . $quoteSuffix; + + + $hdr_value_out = $hdr_value; + $realMax = $maxLength1stLine + strlen($prefix . $suffix); + if (strlen($hdr_value_out) >= $realMax) { + //Begin with the regexp for the first line. + $reg = $reg1st; + $output = ""; + while ($hdr_value_out) { + //Split translated string at every $maxLength + //But make sure not to break any translated chars. + $found = preg_match($reg, $hdr_value_out, $matches); + + //After this first line, we need to use a different + //regexp for the first line. + $reg = $reg2nd; + + //Save the found part and encapsulate it in the + //prefix & suffix. Then remove the part from the + //$hdr_value_out variable. + if ($found) { + $part = $matches[0]; + $len = strlen($matches[0]); + $hdr_value_out = substr($hdr_value_out, $len); + } else { + $part = $hdr_value_out; + $hdr_value_out = ""; + } + + //RFC 2047 specifies that any split header should + //be seperated by a CRLF SPACE + if ($output) { + $output .= "\r\n "; + } + $output .= $prefix . $part . $suffix; + } + $hdr_value_out = $output; + } else { + $hdr_value_out = $prefix . $hdr_value_out . $suffix; + } + $hdr_value = $hdr_value_out; + } + } + $input[$hdr_name] = $hdr_value; + } + return $input; + } + + /** + * Set the object's end-of-line and define the constant if applicable. + * + * @param string $eol End Of Line sequence + * + * @return void + * @access private + */ + function _setEOL($eol) + { + $this->_eol = $eol; + if (!defined('MAIL_MIME_CRLF')) { + define('MAIL_MIME_CRLF', $this->_eol, true); + } + } + + + +} // End of class diff --git a/plugins/notification/mail/lib/Pear/Mail/mimeDecode.php b/plugins/notification/mail/lib/Pear/Mail/mimeDecode.php new file mode 100644 index 0000000..aaa870c --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/mimeDecode.php @@ -0,0 +1,849 @@ + + * Copyright (c) 2003-2006, PEAR + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the authors, nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * @category Mail + * @package Mail_Mime + * @author Richard Heyes + * @author George Schlossnagle + * @author Cipriano Groenendal + * @author Sean Coates + * @copyright 2003-2006 PEAR + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version CVS: $Id: mimeDecode.php,v 1.48 2006/12/03 13:43:33 cipri Exp $ + * @link http://pear.php.net/package/Mail_mime + */ + + +/** + * require PEAR + * + * This package depends on PEAR to raise errors. + */ +require_once 'PEAR.php'; + + +/** + * The Mail_mimeDecode class is used to decode mail/mime messages + * + * This class will parse a raw mime email and return the structure. + * Returned structure is similar to that returned by imap_fetchstructure(). + * + * +----------------------------- IMPORTANT ------------------------------+ + * | Usage of this class compared to native php extensions such as | + * | mailparse or imap, is slow and may be feature deficient. If available| + * | you are STRONGLY recommended to use the php extensions. | + * +----------------------------------------------------------------------+ + * + * @category Mail + * @package Mail_Mime + * @author Richard Heyes + * @author George Schlossnagle + * @author Cipriano Groenendal + * @author Sean Coates + * @copyright 2003-2006 PEAR + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Mail_mime + */ +class Mail_mimeDecode extends PEAR +{ + /** + * The raw email to decode + * + * @var string + * @access private + */ + var $_input; + + /** + * The header part of the input + * + * @var string + * @access private + */ + var $_header; + + /** + * The body part of the input + * + * @var string + * @access private + */ + var $_body; + + /** + * If an error occurs, this is used to store the message + * + * @var string + * @access private + */ + var $_error; + + /** + * Flag to determine whether to include bodies in the + * returned object. + * + * @var boolean + * @access private + */ + var $_include_bodies; + + /** + * Flag to determine whether to decode bodies + * + * @var boolean + * @access private + */ + var $_decode_bodies; + + /** + * Flag to determine whether to decode headers + * + * @var boolean + * @access private + */ + var $_decode_headers; + + /** + * Constructor. + * + * Sets up the object, initialise the variables, and splits and + * stores the header and body of the input. + * + * @param string The input to decode + * @access public + */ + function Mail_mimeDecode($input) + { + list($header, $body) = $this->_splitBodyHeader($input); + + $this->_input = $input; + $this->_header = $header; + $this->_body = $body; + $this->_decode_bodies = false; + $this->_include_bodies = true; + } + + /** + * Begins the decoding process. If called statically + * it will create an object and call the decode() method + * of it. + * + * @param array An array of various parameters that determine + * various things: + * include_bodies - Whether to include the body in the returned + * object. + * decode_bodies - Whether to decode the bodies + * of the parts. (Transfer encoding) + * decode_headers - Whether to decode headers + * input - If called statically, this will be treated + * as the input + * @return object Decoded results + * @access public + */ + function decode($params = null) + { + // determine if this method has been called statically + $isStatic = !(isset($this) && get_class($this) == __CLASS__); + + // Have we been called statically? + // If so, create an object and pass details to that. + if ($isStatic AND isset($params['input'])) { + + $obj = new Mail_mimeDecode($params['input']); + $structure = $obj->decode($params); + + // Called statically but no input + } elseif ($isStatic) { + return PEAR::raiseError('Called statically and no input given'); + + // Called via an object + } else { + $this->_include_bodies = isset($params['include_bodies']) ? + $params['include_bodies'] : false; + $this->_decode_bodies = isset($params['decode_bodies']) ? + $params['decode_bodies'] : false; + $this->_decode_headers = isset($params['decode_headers']) ? + $params['decode_headers'] : false; + + $structure = $this->_decode($this->_header, $this->_body); + if ($structure === false) { + $structure = $this->raiseError($this->_error); + } + } + + return $structure; + } + + /** + * Performs the decoding. Decodes the body string passed to it + * If it finds certain content-types it will call itself in a + * recursive fashion + * + * @param string Header section + * @param string Body section + * @return object Results of decoding process + * @access private + */ + function _decode($headers, $body, $default_ctype = 'text/plain') + { + $return = new stdClass; + $return->headers = array(); + $headers = $this->_parseHeaders($headers); + + foreach ($headers as $value) { + if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) { + $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]); + $return->headers[strtolower($value['name'])][] = $value['value']; + + } elseif (isset($return->headers[strtolower($value['name'])])) { + $return->headers[strtolower($value['name'])][] = $value['value']; + + } else { + $return->headers[strtolower($value['name'])] = $value['value']; + } + } + + reset($headers); + while (list($key, $value) = each($headers)) { + $headers[$key]['name'] = strtolower($headers[$key]['name']); + switch ($headers[$key]['name']) { + + case 'content-type': + $content_type = $this->_parseHeaderValue($headers[$key]['value']); + + if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) { + $return->ctype_primary = $regs[1]; + $return->ctype_secondary = $regs[2]; + } + + if (isset($content_type['other'])) { + while (list($p_name, $p_value) = each($content_type['other'])) { + $return->ctype_parameters[$p_name] = $p_value; + } + } + break; + + case 'content-disposition': + $content_disposition = $this->_parseHeaderValue($headers[$key]['value']); + $return->disposition = $content_disposition['value']; + if (isset($content_disposition['other'])) { + while (list($p_name, $p_value) = each($content_disposition['other'])) { + $return->d_parameters[$p_name] = $p_value; + } + } + break; + + case 'content-transfer-encoding': + $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']); + break; + } + } + + if (isset($content_type)) { + switch (strtolower($content_type['value'])) { + case 'text/plain': + $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; + $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null; + break; + + case 'text/html': + $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; + $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null; + break; + + case 'multipart/parallel': + case 'multipart/appledouble': // Appledouble mail + case 'multipart/report': // RFC1892 + case 'multipart/signed': // PGP + case 'multipart/digest': + case 'multipart/alternative': + case 'multipart/related': + case 'multipart/mixed': + if(!isset($content_type['other']['boundary'])){ + $this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; + return false; + } + + $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain'; + + $parts = $this->_boundarySplit($body, $content_type['other']['boundary']); + for ($i = 0; $i < count($parts); $i++) { + list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]); + $part = $this->_decode($part_header, $part_body, $default_ctype); + if($part === false) + $part = $this->raiseError($this->_error); + $return->parts[] = $part; + } + break; + + case 'message/rfc822': + $obj = &new Mail_mimeDecode($body); + $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies, + 'decode_bodies' => $this->_decode_bodies, + 'decode_headers' => $this->_decode_headers)); + unset($obj); + break; + + default: + if(!isset($content_transfer_encoding['value'])) + $content_transfer_encoding['value'] = '7bit'; + $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null; + break; + } + + } else { + $ctype = explode('/', $default_ctype); + $return->ctype_primary = $ctype[0]; + $return->ctype_secondary = $ctype[1]; + $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null; + } + + return $return; + } + + /** + * Given the output of the above function, this will return an + * array of references to the parts, indexed by mime number. + * + * @param object $structure The structure to go through + * @param string $mime_number Internal use only. + * @return array Mime numbers + */ + function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '') + { + $return = array(); + if (!empty($structure->parts)) { + if ($mime_number != '') { + $structure->mime_id = $prepend . $mime_number; + $return[$prepend . $mime_number] = &$structure; + } + for ($i = 0; $i < count($structure->parts); $i++) { + + + if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') { + $prepend = $prepend . $mime_number . '.'; + $_mime_number = ''; + } else { + $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1)); + } + + $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend); + foreach ($arr as $key => $val) { + $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key]; + } + } + } else { + if ($mime_number == '') { + $mime_number = '1'; + } + $structure->mime_id = $prepend . $mime_number; + $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure; + } + + return $return; + } + + /** + * Given a string containing a header and body + * section, this function will split them (at the first + * blank line) and return them. + * + * @param string Input to split apart + * @return array Contains header and body section + * @access private + */ + function _splitBodyHeader($input) + { + if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) { + return array($match[1], $match[2]); + } + $this->_error = 'Could not split header and body'; + return false; + } + + /** + * Parse headers given in $input and return + * as assoc array. + * + * @param string Headers to parse + * @return array Contains parsed headers + * @access private + */ + function _parseHeaders($input) + { + + if ($input !== '') { + // Unfold the input + $input = preg_replace("/\r?\n/", "\r\n", $input); + $input = preg_replace("/\r\n(\t| )+/", ' ', $input); + $headers = explode("\r\n", trim($input)); + + foreach ($headers as $value) { + $hdr_name = substr($value, 0, $pos = strpos($value, ':')); + $hdr_value = substr($value, $pos+1); + if($hdr_value[0] == ' ') + $hdr_value = substr($hdr_value, 1); + + $return[] = array( + 'name' => $hdr_name, + 'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value + ); + } + } else { + $return = array(); + } + + return $return; + } + + /** + * Function to parse a header value, + * extract first part, and any secondary + * parts (after ;) This function is not as + * robust as it could be. Eg. header comments + * in the wrong place will probably break it. + * + * @param string Header value to parse + * @return array Contains parsed result + * @access private + */ + function _parseHeaderValue($input) + { + + if (($pos = strpos($input, ';')) !== false) { + + $return['value'] = trim(substr($input, 0, $pos)); + $input = trim(substr($input, $pos+1)); + + if (strlen($input) > 0) { + + // This splits on a semi-colon, if there's no preceeding backslash + // Now works with quoted values; had to glue the \; breaks in PHP + // the regex is already bordering on incomprehensible + $splitRegex = '/([^;\'"]*[\'"]([^\'"]*([^\'"]*)*)[\'"][^;\'"]*|([^;]+))(;|$)/'; + preg_match_all($splitRegex, $input, $matches); + $parameters = array(); + for ($i=0; $i_quotedPrintableDecode($input); + break; + + case 'base64': + return base64_decode($input); + break; + + default: + return $input; + } + } + + /** + * Given a quoted-printable string, this + * function will decode and return it. + * + * @param string Input body to decode + * @return string Decoded body + * @access private + */ + function _quotedPrintableDecode($input) + { + // Remove soft line breaks + $input = preg_replace("/=\r?\n/", '', $input); + + // Replace encoded characters + $input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input); + + return $input; + } + + /** + * Checks the input for uuencoded files and returns + * an array of them. Can be called statically, eg: + * + * $files =& Mail_mimeDecode::uudecode($some_text); + * + * It will check for the begin 666 ... end syntax + * however and won't just blindly decode whatever you + * pass it. + * + * @param string Input body to look for attahcments in + * @return array Decoded bodies, filenames and permissions + * @access public + * @author Unknown + */ + function &uudecode($input) + { + // Find all uuencoded sections + preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches); + + for ($j = 0; $j < count($matches[3]); $j++) { + + $str = $matches[3][$j]; + $filename = $matches[2][$j]; + $fileperm = $matches[1][$j]; + + $file = ''; + $str = preg_split("/\r?\n/", trim($str)); + $strlen = count($str); + + for ($i = 0; $i < $strlen; $i++) { + $pos = 1; + $d = 0; + $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077); + + while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) { + $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); + $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); + $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); + $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20); + $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); + + $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); + + $file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077)); + + $pos += 4; + $d += 3; + } + + if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) { + $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); + $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); + $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); + $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); + + $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); + + $pos += 3; + $d += 2; + } + + if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) { + $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); + $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); + $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); + + } + } + $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file); + } + + return $files; + } + + /** + * getSendArray() returns the arguments required for Mail::send() + * used to build the arguments for a mail::send() call + * + * Usage: + * $mailtext = Full email (for example generated by a template) + * $decoder = new Mail_mimeDecode($mailtext); + * $parts = $decoder->getSendArray(); + * if (!PEAR::isError($parts) { + * list($recipents,$headers,$body) = $parts; + * $mail = Mail::factory('smtp'); + * $mail->send($recipents,$headers,$body); + * } else { + * echo $parts->message; + * } + * @return mixed array of recipeint, headers,body or Pear_Error + * @access public + * @author Alan Knowles + */ + function getSendArray() + { + // prevent warning if this is not set + $this->_decode_headers = FALSE; + $headerlist =$this->_parseHeaders($this->_header); + $to = ""; + if (!$headerlist) { + return $this->raiseError("Message did not contain headers"); + } + foreach($headerlist as $item) { + $header[$item['name']] = $item['value']; + switch (strtolower($item['name'])) { + case "to": + case "cc": + case "bcc": + $to = ",".$item['value']; + default: + break; + } + } + if ($to == "") { + return $this->raiseError("Message did not contain any recipents"); + } + $to = substr($to,1); + return array($to,$header,$this->_body); + } + + /** + * Returns a xml copy of the output of + * Mail_mimeDecode::decode. Pass the output in as the + * argument. This function can be called statically. Eg: + * + * $output = $obj->decode(); + * $xml = Mail_mimeDecode::getXML($output); + * + * The DTD used for this should have been in the package. Or + * alternatively you can get it from cvs, or here: + * http://www.phpguru.org/xmail/xmail.dtd. + * + * @param object Input to convert to xml. This should be the + * output of the Mail_mimeDecode::decode function + * @return string XML version of input + * @access public + */ + function getXML($input) + { + $crlf = "\r\n"; + $output = '' . $crlf . + '' . $crlf . + '' . $crlf . + Mail_mimeDecode::_getXML($input) . + ''; + + return $output; + } + + /** + * Function that does the actual conversion to xml. Does a single + * mimepart at a time. + * + * @param object Input to convert to xml. This is a mimepart object. + * It may or may not contain subparts. + * @param integer Number of tabs to indent + * @return string XML version of input + * @access private + */ + function _getXML($input, $indent = 1) + { + $htab = "\t"; + $crlf = "\r\n"; + $output = ''; + $headers = @(array)$input->headers; + + foreach ($headers as $hdr_name => $hdr_value) { + + // Multiple headers with this name + if (is_array($headers[$hdr_name])) { + for ($i = 0; $i < count($hdr_value); $i++) { + $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent); + } + + // Only one header of this sort + } else { + $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent); + } + } + + if (!empty($input->parts)) { + for ($i = 0; $i < count($input->parts); $i++) { + $output .= $crlf . str_repeat($htab, $indent) . '' . $crlf . + Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) . + str_repeat($htab, $indent) . '' . $crlf; + } + } elseif (isset($input->body)) { + $output .= $crlf . str_repeat($htab, $indent) . 'body . ']]>' . $crlf; + } + + return $output; + } + + /** + * Helper function to _getXML(). Returns xml of a header. + * + * @param string Name of header + * @param string Value of header + * @param integer Number of tabs to indent + * @return string XML version of input + * @access private + */ + function _getXML_helper($hdr_name, $hdr_value, $indent) + { + $htab = "\t"; + $crlf = "\r\n"; + $return = ''; + + $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value); + $new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name))); + + // Sort out any parameters + if (!empty($new_hdr_value['other'])) { + foreach ($new_hdr_value['other'] as $paramname => $paramvalue) { + $params[] = str_repeat($htab, $indent) . $htab . '' . $crlf . + str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramname) . '' . $crlf . + str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramvalue) . '' . $crlf . + str_repeat($htab, $indent) . $htab . '' . $crlf; + } + + $params = implode('', $params); + } else { + $params = ''; + } + + $return = str_repeat($htab, $indent) . '
' . $crlf . + str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_name) . '' . $crlf . + str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_value['value']) . '' . $crlf . + $params . + str_repeat($htab, $indent) . '
' . $crlf; + + return $return; + } + +} // End of class diff --git a/plugins/notification/mail/lib/Pear/Mail/mimePart.php b/plugins/notification/mail/lib/Pear/Mail/mimePart.php new file mode 100644 index 0000000..7ad54e5 --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/mimePart.php @@ -0,0 +1,439 @@ + + * Copyright (c) 2003-2006, PEAR + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the authors, nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * @category Mail + * @package Mail_Mime + * @author Richard Heyes + * @author Cipriano Groenendal + * @author Sean Coates + * @copyright 2003-2006 PEAR + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version CVS: $Id: mimePart.php,v 1.25 2007/05/14 21:43:08 cipri Exp $ + * @link http://pear.php.net/package/Mail_mime + */ + + +/** + * The Mail_mimePart class is used to create MIME E-mail messages + * + * This class enables you to manipulate and build a mime email + * from the ground up. The Mail_Mime class is a userfriendly api + * to this class for people who aren't interested in the internals + * of mime mail. + * This class however allows full control over the email. + * + * @category Mail + * @package Mail_Mime + * @author Richard Heyes + * @author Cipriano Groenendal + * @author Sean Coates + * @copyright 2003-2006 PEAR + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Mail_mime + */ +class Mail_mimePart { + + /** + * The encoding type of this part + * + * @var string + * @access private + */ + var $_encoding; + + /** + * An array of subparts + * + * @var array + * @access private + */ + var $_subparts; + + /** + * The output of this part after being built + * + * @var string + * @access private + */ + var $_encoded; + + /** + * Headers for this part + * + * @var array + * @access private + */ + var $_headers; + + /** + * The body of this part (not encoded) + * + * @var string + * @access private + */ + var $_body; + + /** + * Constructor. + * + * Sets up the object. + * + * @param $body - The body of the mime part if any. + * @param $params - An associative array of parameters: + * content_type - The content type for this part eg multipart/mixed + * encoding - The encoding to use, 7bit, 8bit, base64, or quoted-printable + * cid - Content ID to apply + * disposition - Content disposition, inline or attachment + * dfilename - Optional filename parameter for content disposition + * description - Content description + * charset - Character set to use + * @access public + */ + function Mail_mimePart($body = '', $params = array()) + { + if (!defined('MAIL_MIMEPART_CRLF')) { + define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE); + } + + $contentType = array(); + $contentDisp = array(); + foreach ($params as $key => $value) { + switch ($key) { + case 'content_type': + $contentType['type'] = $value; + //$headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : ''); + break; + + case 'encoding': + $this->_encoding = $value; + $headers['Content-Transfer-Encoding'] = $value; + break; + + case 'cid': + $headers['Content-ID'] = '<' . $value . '>'; + break; + + case 'disposition': + $contentDisp['disp'] = $value; + break; + + case 'dfilename': + $contentDisp['filename'] = $value; + $contentType['name'] = $value; + break; + + case 'description': + $headers['Content-Description'] = $value; + break; + + case 'charset': + $contentType['charset'] = $value; + $contentDisp['charset'] = $value; + break; + + case 'language': + $contentType['language'] = $value; + $contentDisp['language'] = $value; + break; + + case 'location': + $headers['Content-Location'] = $value; + break; + + } + } + if (isset($contentType['type'])) { + $headers['Content-Type'] = $contentType['type']; + if (isset($contentType['name'])) { + $headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF; + $headers['Content-Type'] .= $this->_buildHeaderParam('name', $contentType['name'], + isset($contentType['charset']) ? $contentType['charset'] : 'US-ASCII', + isset($contentType['language']) ? $contentType['language'] : NULL); + } elseif (isset($contentType['charset'])) { + $headers['Content-Type'] .= "; charset=\"{$contentType['charset']}\""; + } + } + + + if (isset($contentDisp['disp'])) { + $headers['Content-Disposition'] = $contentDisp['disp']; + if (isset($contentDisp['filename'])) { + $headers['Content-Disposition'] .= ';' . MAIL_MIMEPART_CRLF; + $headers['Content-Disposition'] .= $this->_buildHeaderParam('filename', $contentDisp['filename'], + isset($contentDisp['charset']) ? $contentDisp['charset'] : 'US-ASCII', + isset($contentDisp['language']) ? $contentDisp['language'] : NULL); + } + } + + + + + // Default content-type + if (!isset($headers['Content-Type'])) { + $headers['Content-Type'] = 'text/plain'; + } + + //Default encoding + if (!isset($this->_encoding)) { + $this->_encoding = '7bit'; + } + + // Assign stuff to member variables + $this->_encoded = array(); + $this->_headers = $headers; + $this->_body = $body; + } + + /** + * encode() + * + * Encodes and returns the email. Also stores + * it in the encoded member variable + * + * @return An associative array containing two elements, + * body and headers. The headers element is itself + * an indexed array. + * @access public + */ + function encode() + { + $encoded =& $this->_encoded; + + if (count($this->_subparts)) { + srand((double)microtime()*1000000); + $boundary = '=_' . md5(rand() . microtime()); + $this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"'; + + // Add body parts to $subparts + for ($i = 0; $i < count($this->_subparts); $i++) { + $headers = array(); + $tmp = $this->_subparts[$i]->encode(); + foreach ($tmp['headers'] as $key => $value) { + $headers[] = $key . ': ' . $value; + } + $subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'] . MAIL_MIMEPART_CRLF; + } + + $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF . + rtrim(implode('--' . $boundary . MAIL_MIMEPART_CRLF , $subparts), MAIL_MIMEPART_CRLF) . MAIL_MIMEPART_CRLF . + '--' . $boundary.'--' . MAIL_MIMEPART_CRLF; + + } else { + $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding); + } + + // Add headers to $encoded + $encoded['headers'] =& $this->_headers; + + return $encoded; + } + + /** + * &addSubPart() + * + * Adds a subpart to current mime part and returns + * a reference to it + * + * @param $body The body of the subpart, if any. + * @param $params The parameters for the subpart, same + * as the $params argument for constructor. + * @return A reference to the part you just added. It is + * crucial if using multipart/* in your subparts that + * you use =& in your script when calling this function, + * otherwise you will not be able to add further subparts. + * @access public + */ + function &addSubPart($body, $params) + { + $this->_subparts[] = new Mail_mimePart($body, $params); + return $this->_subparts[count($this->_subparts) - 1]; + } + + /** + * _getEncodedData() + * + * Returns encoded data based upon encoding passed to it + * + * @param $data The data to encode. + * @param $encoding The encoding type to use, 7bit, base64, + * or quoted-printable. + * @access private + */ + function _getEncodedData($data, $encoding) + { + switch ($encoding) { + case '8bit': + case '7bit': + return $data; + break; + + case 'quoted-printable': + return $this->_quotedPrintableEncode($data); + break; + + case 'base64': + return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF)); + break; + + default: + return $data; + } + } + + /** + * quotedPrintableEncode() + * + * Encodes data to quoted-printable standard. + * + * @param $input The data to encode + * @param $line_max Optional max line length. Should + * not be more than 76 chars + * + * @access private + */ + function _quotedPrintableEncode($input , $line_max = 76) + { + $lines = preg_split("/\r?\n/", $input); + $eol = MAIL_MIMEPART_CRLF; + $escape = '='; + $output = ''; + + while (list(, $line) = each($lines)) { + + $line = preg_split('||', $line, -1, PREG_SPLIT_NO_EMPTY); + $linlen = count($line); + $newline = ''; + + for ($i = 0; $i < $linlen; $i++) { + $char = $line[$i]; + $dec = ord($char); + + if (($dec == 32) AND ($i == ($linlen - 1))) { // convert space at eol only + $char = '=20'; + + } elseif (($dec == 9) AND ($i == ($linlen - 1))) { // convert tab at eol only + $char = '=09'; + } elseif ($dec == 9) { + ; // Do nothing if a tab. + } elseif (($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) { + $char = $escape . strtoupper(sprintf('%02s', dechex($dec))); + } elseif (($dec == 46) AND ($newline == '')) { + //Bug #9722: convert full-stop at bol + //Some Windows servers need this, won't break anything (cipri) + $char = '=2E'; + } + + if ((strlen($newline) + strlen($char)) >= $line_max) { // MAIL_MIMEPART_CRLF is not counted + $output .= $newline . $escape . $eol; // soft line break; " =\r\n" is okay + $newline = ''; + } + $newline .= $char; + } // end of for + $output .= $newline . $eol; + } + $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf + return $output; + } + + /** + * _buildHeaderParam() + * + * Encodes the paramater of a header. + * + * @param $name The name of the header-parameter + * @param $value The value of the paramter + * @param $charset The characterset of $value + * @param $language The language used in $value + * @param $maxLength The maximum length of a line. Defauls to 75 + * + * @access private + */ + function _buildHeaderParam($name, $value, $charset=NULL, $language=NULL, $maxLength=75) + { + //If we find chars to encode, or if charset or language + //is not any of the defaults, we need to encode the value. + $shouldEncode = 0; + $secondAsterisk = ''; + if (preg_match('#([\x80-\xFF]){1}#', $value)) { + $shouldEncode = 1; + } elseif ($charset && (strtolower($charset) != 'us-ascii')) { + $shouldEncode = 1; + } elseif ($language && ($language != 'en' && $language != 'en-us')) { + $shouldEncode = 1; + } + if ($shouldEncode) { + $search = array('%', ' ', "\t"); + $replace = array('%25', '%20', '%09'); + $encValue = str_replace($search, $replace, $value); + $encValue = preg_replace('#([\x80-\xFF])#e', '"%" . strtoupper(dechex(ord("\1")))', $encValue); + $value = "$charset'$language'$encValue"; + $secondAsterisk = '*'; + } + $header = " {$name}{$secondAsterisk}=\"{$value}\"; "; + if (strlen($header) <= $maxLength) { + return $header; + } + + $preLength = strlen(" {$name}*0{$secondAsterisk}=\""); + $sufLength = strlen("\";"); + $maxLength = MAX(16, $maxLength - $preLength - $sufLength - 2); + $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|"; + + $headers = array(); + $headCount = 0; + while ($value) { + $matches = array(); + $found = preg_match($maxLengthReg, $value, $matches); + if ($found) { + $headers[] = " {$name}*{$headCount}{$secondAsterisk}=\"{$matches[0]}\""; + $value = substr($value, strlen($matches[0])); + } else { + $headers[] = " {$name}*{$headCount}{$secondAsterisk}=\"{$value}\""; + $value = ""; + } + $headCount++; + } + $headers = implode(MAIL_MIMEPART_CRLF, $headers) . ';'; + return $headers; + } +} // End of class diff --git a/plugins/notification/mail/lib/Pear/Mail/null.php b/plugins/notification/mail/lib/Pear/Mail/null.php new file mode 100644 index 0000000..982bfa4 --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/null.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: null.php,v 1.2 2004/04/06 05:19:03 jon Exp $ +// + +/** + * Null implementation of the PEAR Mail:: interface. + * @access public + * @package Mail + * @version $Revision: 1.2 $ + */ +class Mail_null extends Mail { + + /** + * Implements Mail_null::send() function. Silently discards all + * mail. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + */ + function send($recipients, $headers, $body) + { + return true; + } + +} diff --git a/plugins/notification/mail/lib/Pear/Mail/sendmail.php b/plugins/notification/mail/lib/Pear/Mail/sendmail.php new file mode 100644 index 0000000..8d6e385 --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/sendmail.php @@ -0,0 +1,155 @@ + | +// +----------------------------------------------------------------------+ + +/** + * Sendmail implementation of the PEAR Mail:: interface. + * @access public + * @package Mail + * @version $Revision: 1.17 $ + */ +class Mail_sendmail extends Mail { + + /** + * The location of the sendmail or sendmail wrapper binary on the + * filesystem. + * @var string + */ + var $sendmail_path = '/usr/sbin/sendmail'; + + /** + * Any extra command-line parameters to pass to the sendmail or + * sendmail wrapper binary. + * @var string + */ + var $sendmail_args = '-i'; + + /** + * Constructor. + * + * Instantiates a new Mail_sendmail:: object based on the parameters + * passed in. It looks for the following parameters: + * sendmail_path The location of the sendmail binary on the + * filesystem. Defaults to '/usr/sbin/sendmail'. + * + * sendmail_args Any extra parameters to pass to the sendmail + * or sendmail wrapper binary. + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @param array $params Hash containing any parameters different from the + * defaults. + * @access public + */ + function Mail_sendmail($params) + { + if (isset($params['sendmail_path'])) { + $this->sendmail_path = $params['sendmail_path']; + } + if (isset($params['sendmail_args'])) { + $this->sendmail_args = $params['sendmail_args']; + } + + /* + * Because we need to pass message headers to the sendmail program on + * the commandline, we can't guarantee the use of the standard "\r\n" + * separator. Instead, we use the system's native line separator. + */ + if (defined('PHP_EOL')) { + $this->sep = PHP_EOL; + } else { + $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; + } + } + + /** + * Implements Mail::send() function using the sendmail + * command-line binary. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + */ + function send($recipients, $headers, $body) + { + $recipients = $this->parseRecipients($recipients); + if (PEAR::isError($recipients)) { + return $recipients; + } + $recipients = escapeShellCmd(implode(' ', $recipients)); + + $this->_sanitizeHeaders($headers); + $headerElements = $this->prepareHeaders($headers); + if (PEAR::isError($headerElements)) { + return $headerElements; + } + list($from, $text_headers) = $headerElements; + + if (!isset($from)) { + return PEAR::raiseError('No from address given.'); + } elseif (strpos($from, ' ') !== false || + strpos($from, ';') !== false || + strpos($from, '&') !== false || + strpos($from, '`') !== false) { + return PEAR::raiseError('From address specified with dangerous characters.'); + } + + $from = escapeShellCmd($from); + $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w'); + if (!$mail) { + return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.'); + } + + // Write the headers following by two newlines: one to end the headers + // section and a second to separate the headers block from the body. + fputs($mail, $text_headers . $this->sep . $this->sep); + + fputs($mail, $body); + $result = pclose($mail); + if (version_compare(phpversion(), '4.2.3') == -1) { + // With older php versions, we need to shift the pclose + // result to get the exit code. + $result = $result >> 8 & 0xFF; + } + + if ($result != 0) { + return PEAR::raiseError('sendmail returned error code ' . $result, + $result); + } + + return true; + } + +} diff --git a/plugins/notification/mail/lib/Pear/Mail/smtp.php b/plugins/notification/mail/lib/Pear/Mail/smtp.php new file mode 100644 index 0000000..14ae3cd --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Mail/smtp.php @@ -0,0 +1,348 @@ + | +// | Jon Parise | +// +----------------------------------------------------------------------+ + +/** Error: Failed to create a Net_SMTP object */ +define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000); + +/** Error: Failed to connect to SMTP server */ +define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001); + +/** Error: SMTP authentication failure */ +define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002); + +/** Error: No From: address has been provided */ +define('PEAR_MAIL_SMTP_ERROR_FROM', 10003); + +/** Error: Failed to set sender */ +define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004); + +/** Error: Failed to add recipient */ +define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005); + +/** Error: Failed to send data */ +define('PEAR_MAIL_SMTP_ERROR_DATA', 10006); + +/** + * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class. + * @access public + * @package Mail + * @version $Revision: 1.28 $ + */ +class Mail_smtp extends Mail { + + /** + * SMTP connection object. + * + * @var object + * @access private + */ + var $_smtp = null; + + /** + * The SMTP host to connect to. + * @var string + */ + var $host = 'localhost'; + + /** + * The port the SMTP server is on. + * @var integer + */ + var $port = 25; + + /** + * Should SMTP authentication be used? + * + * This value may be set to true, false or the name of a specific + * authentication method. + * + * If the value is set to true, the Net_SMTP package will attempt to use + * the best authentication method advertised by the remote SMTP server. + * + * @var mixed + */ + var $auth = false; + + /** + * The username to use if the SMTP server requires authentication. + * @var string + */ + var $username = ''; + + /** + * The password to use if the SMTP server requires authentication. + * @var string + */ + var $password = ''; + + /** + * Hostname or domain that will be sent to the remote SMTP server in the + * HELO / EHLO message. + * + * @var string + */ + var $localhost = 'localhost'; + + /** + * SMTP connection timeout value. NULL indicates no timeout. + * + * @var integer + */ + var $timeout = null; + + /** + * Whether to use VERP or not. If not a boolean, the string value + * will be used as the VERP separators. + * + * @var mixed boolean or string + */ + var $verp = false; + + /** + * Turn on Net_SMTP debugging? + * + * @var boolean $debug + */ + var $debug = false; + + /** + * Indicates whether or not the SMTP connection should persist over + * multiple calls to the send() method. + * + * @var boolean + */ + var $persist = false; + + /** + * Constructor. + * + * Instantiates a new Mail_smtp:: object based on the parameters + * passed in. It looks for the following parameters: + * host The server to connect to. Defaults to localhost. + * port The port to connect to. Defaults to 25. + * auth SMTP authentication. Defaults to none. + * username The username to use for SMTP auth. No default. + * password The password to use for SMTP auth. No default. + * localhost The local hostname / domain. Defaults to localhost. + * timeout The SMTP connection timeout. Defaults to none. + * verp Whether to use VERP or not. Defaults to false. + * debug Activate SMTP debug mode? Defaults to false. + * persist Should the SMTP connection persist? + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @param array Hash containing any parameters different from the + * defaults. + * @access public + */ + function Mail_smtp($params) + { + if (isset($params['host'])) $this->host = $params['host']; + if (isset($params['port'])) $this->port = $params['port']; + if (isset($params['auth'])) $this->auth = $params['auth']; + if (isset($params['username'])) $this->username = $params['username']; + if (isset($params['password'])) $this->password = $params['password']; + if (isset($params['localhost'])) $this->localhost = $params['localhost']; + if (isset($params['timeout'])) $this->timeout = $params['timeout']; + if (isset($params['verp'])) $this->verp = $params['verp']; + if (isset($params['debug'])) $this->debug = (boolean)$params['debug']; + if (isset($params['persist'])) $this->persist = (boolean)$params['persist']; + + register_shutdown_function(array(&$this, '_Mail_smtp')); + } + + /** + * Destructor implementation to ensure that we disconnect from any + * potentially-alive persistent SMTP connections. + */ + function _Mail_smtp() + { + $this->disconnect(); + } + + /** + * Implements Mail::send() function using SMTP. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (e.g., 'Subject'), and the array value + * is the header value (e.g., 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + */ + function send($recipients, $headers, $body) + { + include_once 'Net/SMTP.php'; + + /* If we don't already have an SMTP object, create one. */ + if (is_object($this->_smtp) === false) { + $this->_smtp =& new Net_SMTP($this->host, $this->port, + $this->localhost); + + /* If we still don't have an SMTP object at this point, fail. */ + if (is_object($this->_smtp) === false) { + return PEAR::raiseError('Failed to create a Net_SMTP object', + PEAR_MAIL_SMTP_ERROR_CREATE); + } + + /* Configure the SMTP connection. */ + if ($this->debug) { + $this->_smtp->setDebug(true); + } + + /* Attempt to connect to the configured SMTP server. */ + if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) { + $error = $this->_error('Failed to connect to ' . + $this->host . ':' . $this->port, + $res); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT); + } + + /* Attempt to authenticate if authentication has been enabled. */ + if ($this->auth) { + $method = is_string($this->auth) ? $this->auth : ''; + + if (PEAR::isError($res = $this->_smtp->auth($this->username, + $this->password, + $method))) { + $error = $this->_error("$method authentication failure", + $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH); + } + } + } + + $this->_sanitizeHeaders($headers); + $headerElements = $this->prepareHeaders($headers); + if (PEAR::isError($headerElements)) { + $this->_smtp->rset(); + return $headerElements; + } + list($from, $textHeaders) = $headerElements; + + /* Since few MTAs are going to allow this header to be forged + * unless it's in the MAIL FROM: exchange, we'll use + * Return-Path instead of From: if it's set. */ + if (!empty($headers['Return-Path'])) { + $from = $headers['Return-Path']; + } + + if (!isset($from)) { + $this->_smtp->rset(); + return PEAR::raiseError('No From: address has been provided', + PEAR_MAIL_SMTP_ERROR_FROM); + } + + $args['verp'] = $this->verp; + if (PEAR::isError($res = $this->_smtp->mailFrom($from, $args))) { + $error = $this->_error("Failed to set sender: $from", $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER); + } + + $recipients = $this->parseRecipients($recipients); + if (PEAR::isError($recipients)) { + $this->_smtp->rset(); + return $recipients; + } + + foreach ($recipients as $recipient) { + if (PEAR::isError($res = $this->_smtp->rcptTo($recipient))) { + $error = $this->_error("Failed to add recipient: $recipient", + $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT); + } + } + + /* Send the message's headers and the body as SMTP data. */ + if (PEAR::isError($res = $this->_smtp->data($textHeaders . "\r\n\r\n" . $body))) { + $error = $this->_error('Failed to send data', $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA); + } + + /* If persistent connections are disabled, destroy our SMTP object. */ + if ($this->persist === false) { + $this->disconnect(); + } + + return true; + } + + /** + * Disconnect and destroy the current SMTP connection. + * + * @return boolean True if the SMTP connection no longer exists. + * + * @since 1.1.9 + * @access public + */ + function disconnect() + { + /* If we have an SMTP object, disconnect and destroy it. */ + if (is_object($this->_smtp) && $this->_smtp->disconnect()) { + $this->_smtp = null; + } + + /* We are disconnected if we no longer have an SMTP object. */ + return ($this->_smtp === null); + } + + /** + * Build a standardized string describing the current SMTP error. + * + * @param string $text Custom string describing the error context. + * @param object $error Reference to the current PEAR_Error object. + * + * @return string A string describing the current SMTP error. + * + * @since 1.1.7 + * @access private + */ + function _error($text, &$error) + { + /* Split the SMTP response into a code and a response string. */ + list($code, $response) = $this->_smtp->getResponse(); + + /* Build our standardized error string. */ + $msg = $text; + $msg .= ' [SMTP: ' . $error->getMessage(); + $msg .= " (code: $code, response: $response)]"; + + return $msg; + } + +} diff --git a/plugins/notification/mail/lib/Pear/Net/SMTP.php b/plugins/notification/mail/lib/Pear/Net/SMTP.php new file mode 100644 index 0000000..424e52a --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Net/SMTP.php @@ -0,0 +1,1133 @@ + | +// | Jon Parise | +// | Damian Alejandro Fernandez Sosa | +// +----------------------------------------------------------------------+ +// +// $Id: SMTP.php 284052 2009-07-14 05:34:26Z jon $ + +require_once 'PEAR.php'; +require_once 'Net/Socket.php'; + +/** + * Provides an implementation of the SMTP protocol using PEAR's + * Net_Socket:: class. + * + * @package Net_SMTP + * @author Chuck Hagenbuch + * @author Jon Parise + * @author Damian Alejandro Fernandez Sosa + * + * @example basic.php A basic implementation of the Net_SMTP package. + */ +class Net_SMTP +{ + /** + * The server to connect to. + * @var string + * @access public + */ + var $host = 'localhost'; + + /** + * The port to connect to. + * @var int + * @access public + */ + var $port = 25; + + /** + * The value to give when sending EHLO or HELO. + * @var string + * @access public + */ + var $localhost = 'localhost'; + + /** + * List of supported authentication methods, in preferential order. + * @var array + * @access public + */ + var $auth_methods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN'); + + /** + * Use SMTP command pipelining (specified in RFC 2920) if the SMTP + * server supports it. + * + * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(), + * somlFrom() and samlFrom() do not wait for a response from the + * SMTP server but return immediately. + * + * @var bool + * @access public + */ + var $pipelining = false; + + /** + * Number of pipelined commands. + * @var int + * @access private + */ + var $_pipelined_commands = 0; + + /** + * Should debugging output be enabled? + * @var boolean + * @access private + */ + var $_debug = false; + + /** + * Debug output handler. + * @var callback + * @access private + */ + var $_debug_handler = null; + + /** + * The socket resource being used to connect to the SMTP server. + * @var resource + * @access private + */ + var $_socket = null; + + /** + * The most recent server response code. + * @var int + * @access private + */ + var $_code = -1; + + /** + * The most recent server response arguments. + * @var array + * @access private + */ + var $_arguments = array(); + + /** + * Stores the SMTP server's greeting string. + * @var string + * @access private + */ + var $_greeting = null; + + /** + * Stores detected features of the SMTP server. + * @var array + * @access private + */ + var $_esmtp = array(); + + /** + * Instantiates a new Net_SMTP object, overriding any defaults + * with parameters that are passed in. + * + * If you have SSL support in PHP, you can connect to a server + * over SSL using an 'ssl://' prefix: + * + * // 465 is a common smtps port. + * $smtp = new Net_SMTP('ssl://mail.host.com', 465); + * $smtp->connect(); + * + * @param string $host The server to connect to. + * @param integer $port The port to connect to. + * @param string $localhost The value to give when sending EHLO or HELO. + * @param boolean $pipeling Use SMTP command pipelining + * + * @access public + * @since 1.0 + */ + function Net_SMTP($host = null, $port = null, $localhost = null, $pipelining = false) + { + if (isset($host)) { + $this->host = $host; + } + if (isset($port)) { + $this->port = $port; + } + if (isset($localhost)) { + $this->localhost = $localhost; + } + $this->pipelining = $pipelining; + + $this->_socket = new Net_Socket(); + + /* Include the Auth_SASL package. If the package is not + * available, we disable the authentication methods that + * depend upon it. */ + if ((@include_once 'Auth/SASL.php') === false) { + $pos = array_search('DIGEST-MD5', $this->auth_methods); + unset($this->auth_methods[$pos]); + $pos = array_search('CRAM-MD5', $this->auth_methods); + unset($this->auth_methods[$pos]); + } + } + + /** + * Set the value of the debugging flag. + * + * @param boolean $debug New value for the debugging flag. + * + * @access public + * @since 1.1.0 + */ + function setDebug($debug, $handler = null) + { + $this->_debug = $debug; + $this->_debug_handler = $handler; + } + + /** + * Write the given debug text to the current debug output handler. + * + * @param string $message Debug mesage text. + * + * @access private + * @since 1.3.3 + */ + function _debug($message) + { + if ($this->_debug) { + if ($this->_debug_handler) { + call_user_func_array($this->_debug_handler, + array(&$this, $message)); + } else { + echo "DEBUG: $message\n"; + } + } + } + + /** + * Send the given string of data to the server. + * + * @param string $data The string of data to send. + * + * @return mixed True on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.1.0 + */ + function _send($data) + { + $this->_debug("Send: $data"); + + if (PEAR::isError($error = $this->_socket->write($data))) { + return PEAR::raiseError('Failed to write to socket: ' . + $error->getMessage()); + } + + return true; + } + + /** + * Send a command to the server with an optional string of + * arguments. A carriage return / linefeed (CRLF) sequence will + * be appended to each command string before it is sent to the + * SMTP server - an error will be thrown if the command string + * already contains any newline characters. Use _send() for + * commands that must contain newlines. + * + * @param string $command The SMTP command to send to the server. + * @param string $args A string of optional arguments to append + * to the command. + * + * @return mixed The result of the _send() call. + * + * @access private + * @since 1.1.0 + */ + function _put($command, $args = '') + { + if (!empty($args)) { + $command .= ' ' . $args; + } + + if (strcspn($command, "\r\n") !== strlen($command)) { + return PEAR::raiseError('Commands cannot contain newlines'); + } + + return $this->_send($command . "\r\n"); + } + + /** + * Read a reply from the SMTP server. The reply consists of a response + * code and a response message. + * + * @param mixed $valid The set of valid response codes. These + * may be specified as an array of integer + * values or as a single integer value. + * @param bool $later Do not parse the response now, but wait + * until the last command in the pipelined + * command group + * + * @return mixed True if the server returned a valid response code or + * a PEAR_Error object is an error condition is reached. + * + * @access private + * @since 1.1.0 + * + * @see getResponse + */ + function _parseResponse($valid, $later = false) + { + $this->_code = -1; + $this->_arguments = array(); + + if ($later) { + $this->_pipelined_commands++; + return true; + } + + for ($i = 0; $i <= $this->_pipelined_commands; $i++) { + while ($line = $this->_socket->readLine()) { + $this->_debug("Recv: $line"); + + /* If we receive an empty line, the connection has been closed. */ + if (empty($line)) { + $this->disconnect(); + return PEAR::raiseError('Connection was unexpectedly closed'); + } + + /* Read the code and store the rest in the arguments array. */ + $code = substr($line, 0, 3); + $this->_arguments[] = trim(substr($line, 4)); + + /* Check the syntax of the response code. */ + if (is_numeric($code)) { + $this->_code = (int)$code; + } else { + $this->_code = -1; + break; + } + + /* If this is not a multiline response, we're done. */ + if (substr($line, 3, 1) != '-') { + break; + } + } + } + + $this->_pipelined_commands = 0; + + /* Compare the server's response code with the valid code/codes. */ + if (is_int($valid) && ($this->_code === $valid)) { + return true; + } elseif (is_array($valid) && in_array($this->_code, $valid, true)) { + return true; + } + + return PEAR::raiseError('Invalid response code received from server', + $this->_code); + } + + /** + * Return a 2-tuple containing the last response from the SMTP server. + * + * @return array A two-element array: the first element contains the + * response code as an integer and the second element + * contains the response's arguments as a string. + * + * @access public + * @since 1.1.0 + */ + function getResponse() + { + return array($this->_code, join("\n", $this->_arguments)); + } + + /** + * Return the SMTP server's greeting string. + * + * @return string A string containing the greeting string, or null if a + * greeting has not been received. + * + * @access public + * @since 1.3.3 + */ + function getGreeting() + { + return $this->_greeting; + } + + /** + * Attempt to connect to the SMTP server. + * + * @param int $timeout The timeout value (in seconds) for the + * socket connection. + * @param bool $persistent Should a persistent socket connection + * be used? + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function connect($timeout = null, $persistent = false) + { + $this->_greeting = null; + $result = $this->_socket->connect($this->host, $this->port, + $persistent, $timeout); + if (PEAR::isError($result)) { + return PEAR::raiseError('Failed to connect socket: ' . + $result->getMessage()); + } + + if (PEAR::isError($error = $this->_parseResponse(220))) { + return $error; + } + + /* Extract and store a copy of the server's greeting string. */ + list(, $this->_greeting) = $this->getResponse(); + + if (PEAR::isError($error = $this->_negotiate())) { + return $error; + } + + return true; + } + + /** + * Attempt to disconnect from the SMTP server. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function disconnect() + { + if (PEAR::isError($error = $this->_put('QUIT'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(221))) { + return $error; + } + if (PEAR::isError($error = $this->_socket->disconnect())) { + return PEAR::raiseError('Failed to disconnect socket: ' . + $error->getMessage()); + } + + return true; + } + + /** + * Attempt to send the EHLO command and obtain a list of ESMTP + * extensions available, and failing that just send HELO. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access private + * @since 1.1.0 + */ + function _negotiate() + { + if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) { + return $error; + } + + if (PEAR::isError($this->_parseResponse(250))) { + /* If we receive a 503 response, we're already authenticated. */ + if ($this->_code === 503) { + return true; + } + + /* If the EHLO failed, try the simpler HELO command. */ + if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) { + return $error; + } + if (PEAR::isError($this->_parseResponse(250))) { + return PEAR::raiseError('HELO was not accepted: ', $this->_code); + } + + return true; + } + + foreach ($this->_arguments as $argument) { + $verb = strtok($argument, ' '); + $arguments = substr($argument, strlen($verb) + 1, + strlen($argument) - strlen($verb) - 1); + $this->_esmtp[$verb] = $arguments; + } + + if (!isset($this->_esmtp['PIPELINING'])) { + $this->pipelining = false; + } + + return true; + } + + /** + * Returns the name of the best authentication method that the server + * has advertised. + * + * @return mixed Returns a string containing the name of the best + * supported authentication method or a PEAR_Error object + * if a failure condition is encountered. + * @access private + * @since 1.1.0 + */ + function _getBestAuthMethod() + { + $available_methods = explode(' ', $this->_esmtp['AUTH']); + + foreach ($this->auth_methods as $method) { + if (in_array($method, $available_methods)) { + return $method; + } + } + + return PEAR::raiseError('No supported authentication methods'); + } + + /** + * Attempt to do SMTP authentication. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * @param string The requested authentication method. If none is + * specified, the best supported method will be used. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function auth($uid, $pwd , $method = '') + { + /* We can only attempt a TLS connection if we're running PHP 5.1.0 or + * later, have access to the OpenSSL extension, are connected to an + * SMTP server which supports the STARTTLS extension, and aren't + * already connected over a secure (SSL) socket connection. */ + $tls = version_compare(PHP_VERSION, '5.1.0', '>=') && extension_loaded('openssl') && + isset($this->_esmtp['STARTTLS']) && strncasecmp($this->host, 'ssl://', 6) != 0; + + if ($tls) { + if (PEAR::isError($result = $this->_put('STARTTLS'))) { + return $result; + } + if (PEAR::isError($result = $this->_parseResponse(220))) { + return $result; + } + if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) { + return $result; + } elseif ($result !== true) { + return PEAR::raiseError('STARTTLS failed'); + } + + /* Send EHLO again to recieve the AUTH string from the + * SMTP server. */ + $this->_negotiate(); + } + + if (empty($this->_esmtp['AUTH'])) { + return PEAR::raiseError('SMTP server does not support authentication'); + } + + /* If no method has been specified, get the name of the best + * supported method advertised by the SMTP server. */ + if (empty($method)) { + if (PEAR::isError($method = $this->_getBestAuthMethod())) { + /* Return the PEAR_Error object from _getBestAuthMethod(). */ + return $method; + } + } else { + $method = strtoupper($method); + if (!in_array($method, $this->auth_methods)) { + return PEAR::raiseError("$method is not a supported authentication method"); + } + } + + switch ($method) { + case 'DIGEST-MD5': + $result = $this->_authDigest_MD5($uid, $pwd); + break; + + case 'CRAM-MD5': + $result = $this->_authCRAM_MD5($uid, $pwd); + break; + + case 'LOGIN': + $result = $this->_authLogin($uid, $pwd); + break; + + case 'PLAIN': + $result = $this->_authPlain($uid, $pwd); + break; + + default: + $result = PEAR::raiseError("$method is not a supported authentication method"); + break; + } + + /* If an error was encountered, return the PEAR_Error object. */ + if (PEAR::isError($result)) { + return $result; + } + + return true; + } + + /** + * Authenticates the user using the DIGEST-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authDigest_MD5($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + $challenge = base64_decode($this->_arguments[0]); + $digest = &Auth_SASL::factory('digestmd5'); + $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, + $this->host, "smtp")); + + if (PEAR::isError($error = $this->_put($auth_str))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + return $error; + } + + /* We don't use the protocol's third step because SMTP doesn't + * allow subsequent authentication, so we just silently ignore + * it. */ + if (PEAR::isError($error = $this->_put(''))) { + return $error; + } + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + } + + /** + * Authenticates the user using the CRAM-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authCRAM_MD5($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + $challenge = base64_decode($this->_arguments[0]); + $cram = &Auth_SASL::factory('crammd5'); + $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); + + if (PEAR::isError($error = $this->_put($auth_str))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + } + + /** + * Authenticates the user using the LOGIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authLogin($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + if (PEAR::isError($error = $this->_put(base64_encode($uid)))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + return $error; + } + + if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + + return true; + } + + /** + * Authenticates the user using the PLAIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authPlain($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + $auth_str = base64_encode(chr(0) . $uid . chr(0) . $pwd); + + if (PEAR::isError($error = $this->_put($auth_str))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + + return true; + } + + /** + * Send the HELO command. + * + * @param string The domain name to say we are. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function helo($domain) + { + if (PEAR::isError($error = $this->_put('HELO', $domain))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Return the list of SMTP service extensions advertised by the server. + * + * @return array The list of SMTP service extensions. + * @access public + * @since 1.3 + */ + function getServiceExtensions() + { + return $this->_esmtp; + } + + /** + * Send the MAIL FROM: command. + * + * @param string $sender The sender (reverse path) to set. + * @param string $params String containing additional MAIL parameters, + * such as the NOTIFY flags defined by RFC 1891 + * or the VERP protocol. + * + * If $params is an array, only the 'verp' option + * is supported. If 'verp' is true, the XVERP + * parameter is appended to the MAIL command. If + * the 'verp' value is a string, the full + * XVERP=value parameter is appended. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function mailFrom($sender, $params = null) + { + $args = "FROM:<$sender>"; + + /* Support the deprecated array form of $params. */ + if (is_array($params) && isset($params['verp'])) { + /* XVERP */ + if ($params['verp'] === true) { + $args .= ' XVERP'; + + /* XVERP=something */ + } elseif (trim($params['verp'])) { + $args .= ' XVERP=' . $params['verp']; + } + } elseif (is_string($params)) { + $args .= ' ' . $params; + } + + if (PEAR::isError($error = $this->_put('MAIL', $args))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Send the RCPT TO: command. + * + * @param string $recipient The recipient (forward path) to add. + * @param string $params String containing additional RCPT parameters, + * such as the NOTIFY flags defined by RFC 1891. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + */ + function rcptTo($recipient, $params = null) + { + $args = "TO:<$recipient>"; + if (is_string($params)) { + $args .= ' ' . $params; + } + + if (PEAR::isError($error = $this->_put('RCPT', $args))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(array(250, 251), $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Quote the data so that it meets SMTP standards. + * + * This is provided as a separate public function to facilitate + * easier overloading for the cases where it is desirable to + * customize the quoting behavior. + * + * @param string $data The message text to quote. The string must be passed + * by reference, and the text will be modified in place. + * + * @access public + * @since 1.2 + */ + function quotedata(&$data) + { + /* Change Unix (\n) and Mac (\r) linefeeds into + * Internet-standard CRLF (\r\n) linefeeds. */ + $data = preg_replace(array('/(?_esmtp['SIZE']) && ($this->_esmtp['SIZE'] > 0)) { + if (strlen($data) >= $this->_esmtp['SIZE']) { + $this->disconnect(); + return PEAR::raiseError('Message size excedes the server limit'); + } + } + + /* Quote the data based on the SMTP standards. */ + $this->quotedata($data); + + if (PEAR::isError($error = $this->_put('DATA'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(354))) { + return $error; + } + + if (PEAR::isError($result = $this->_send($data . "\r\n.\r\n"))) { + return $result; + } + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Send the SEND FROM: command. + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.2.6 + */ + function sendFrom($path) + { + if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility wrapper for sendFrom(). + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + * @deprecated 1.2.6 + */ + function send_from($path) + { + return sendFrom($path); + } + + /** + * Send the SOML FROM: command. + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.2.6 + */ + function somlFrom($path) + { + if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility wrapper for somlFrom(). + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + * @deprecated 1.2.6 + */ + function soml_from($path) + { + return somlFrom($path); + } + + /** + * Send the SAML FROM: command. + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.2.6 + */ + function samlFrom($path) + { + if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility wrapper for samlFrom(). + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + * @deprecated 1.2.6 + */ + function saml_from($path) + { + return samlFrom($path); + } + + /** + * Send the RSET command. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function rset() + { + if (PEAR::isError($error = $this->_put('RSET'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + return $error; + } + + return true; + } + + /** + * Send the VRFY command. + * + * @param string The string to verify + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function vrfy($string) + { + /* Note: 251 is also a valid response code */ + if (PEAR::isError($error = $this->_put('VRFY', $string))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(array(250, 252)))) { + return $error; + } + + return true; + } + + /** + * Send the NOOP command. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function noop() + { + if (PEAR::isError($error = $this->_put('NOOP'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility method. identifySender()'s functionality is + * now handled internally. + * + * @return boolean This method always return true. + * + * @access public + * @since 1.0 + */ + function identifySender() + { + return true; + } + +} diff --git a/plugins/notification/mail/lib/Pear/Net/Socket.php b/plugins/notification/mail/lib/Pear/Net/Socket.php new file mode 100644 index 0000000..73bb4dd --- /dev/null +++ b/plugins/notification/mail/lib/Pear/Net/Socket.php @@ -0,0 +1,592 @@ + | +// | Chuck Hagenbuch | +// +----------------------------------------------------------------------+ +// +// $Id: Socket.php,v 1.38 2008/02/15 18:24:17 chagenbu Exp $ + +require_once 'PEAR.php'; + +define('NET_SOCKET_READ', 1); +define('NET_SOCKET_WRITE', 2); +define('NET_SOCKET_ERROR', 4); + +/** + * Generalized Socket class. + * + * @version 1.1 + * @author Stig Bakken + * @author Chuck Hagenbuch + */ +class Net_Socket extends PEAR { + + /** + * Socket file pointer. + * @var resource $fp + */ + var $fp = null; + + /** + * Whether the socket is blocking. Defaults to true. + * @var boolean $blocking + */ + var $blocking = true; + + /** + * Whether the socket is persistent. Defaults to false. + * @var boolean $persistent + */ + var $persistent = false; + + /** + * The IP address to connect to. + * @var string $addr + */ + var $addr = ''; + + /** + * The port number to connect to. + * @var integer $port + */ + var $port = 0; + + /** + * Number of seconds to wait on socket connections before assuming + * there's no more data. Defaults to no timeout. + * @var integer $timeout + */ + var $timeout = false; + + /** + * Number of bytes to read at a time in readLine() and + * readAll(). Defaults to 2048. + * @var integer $lineLength + */ + var $lineLength = 2048; + + /** + * Connect to the specified port. If called when the socket is + * already connected, it disconnects and connects again. + * + * @param string $addr IP address or host name. + * @param integer $port TCP port number. + * @param boolean $persistent (optional) Whether the connection is + * persistent (kept open between requests + * by the web server). + * @param integer $timeout (optional) How long to wait for data. + * @param array $options See options for stream_context_create. + * + * @access public + * + * @return boolean | PEAR_Error True on success or a PEAR_Error on failure. + */ + function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null) + { + if (is_resource($this->fp)) { + @fclose($this->fp); + $this->fp = null; + } + + if (!$addr) { + return $this->raiseError('$addr cannot be empty'); + } elseif (strspn($addr, '.0123456789') == strlen($addr) || + strstr($addr, '/') !== false) { + $this->addr = $addr; + } else { + $this->addr = @gethostbyname($addr); + } + + $this->port = $port % 65536; + + if ($persistent !== null) { + $this->persistent = $persistent; + } + + if ($timeout !== null) { + $this->timeout = $timeout; + } + + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; + $errno = 0; + $errstr = ''; + $old_track_errors = @ini_set('track_errors', 1); + if ($options && function_exists('stream_context_create')) { + if ($this->timeout) { + $timeout = $this->timeout; + } else { + $timeout = 0; + } + $context = stream_context_create($options); + + // Since PHP 5 fsockopen doesn't allow context specification + if (function_exists('stream_socket_client')) { + $flags = $this->persistent ? STREAM_CLIENT_PERSISTENT : STREAM_CLIENT_CONNECT; + $addr = $this->addr . ':' . $this->port; + $fp = stream_socket_client($addr, $errno, $errstr, $timeout, $flags, $context); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context); + } + } else { + if ($this->timeout) { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr); + } + } + + if (!$fp) { + if ($errno == 0 && isset($php_errormsg)) { + $errstr = $php_errormsg; + } + @ini_set('track_errors', $old_track_errors); + return $this->raiseError($errstr, $errno); + } + + @ini_set('track_errors', $old_track_errors); + $this->fp = $fp; + + return $this->setBlocking($this->blocking); + } + + /** + * Disconnects from the peer, closes the socket. + * + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function disconnect() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + @fclose($this->fp); + $this->fp = null; + return true; + } + + /** + * Find out if the socket is in blocking mode. + * + * @access public + * @return boolean The current blocking mode. + */ + function isBlocking() + { + return $this->blocking; + } + + /** + * Sets whether the socket connection should be blocking or + * not. A read call to a non-blocking socket will return immediately + * if there is no data available, whereas it will block until there + * is data for blocking sockets. + * + * @param boolean $mode True for blocking sockets, false for nonblocking. + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function setBlocking($mode) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $this->blocking = $mode; + socket_set_blocking($this->fp, $this->blocking); + return true; + } + + /** + * Sets the timeout value on socket descriptor, + * expressed in the sum of seconds and microseconds + * + * @param integer $seconds Seconds. + * @param integer $microseconds Microseconds. + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function setTimeout($seconds, $microseconds) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_set_timeout($this->fp, $seconds, $microseconds); + } + + /** + * Sets the file buffering size on the stream. + * See php's stream_set_write_buffer for more information. + * + * @param integer $size Write buffer size. + * @access public + * @return mixed on success or an PEAR_Error object otherwise + */ + function setWriteBuffer($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $returned = stream_set_write_buffer($this->fp, $size); + if ($returned == 0) { + return true; + } + return $this->raiseError('Cannot set write buffer.'); + } + + /** + * Returns information about an existing socket resource. + * Currently returns four entries in the result array: + * + *

+ * timed_out (bool) - The socket timed out waiting for data
+ * blocked (bool) - The socket was blocked
+ * eof (bool) - Indicates EOF event
+ * unread_bytes (int) - Number of bytes left in the socket buffer
+ *

+ * + * @access public + * @return mixed Array containing information about existing socket resource or a PEAR_Error instance otherwise + */ + function getStatus() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_get_status($this->fp); + } + + /** + * Get a specified line of data + * + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function gets($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fgets($this->fp, $size); + } + + /** + * Read a specified amount of data. This is guaranteed to return, + * and has the added benefit of getting everything in one fread() + * chunk; if you know the size of the data you're getting + * beforehand, this is definitely the way to go. + * + * @param integer $size The number of bytes to read from the socket. + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function read($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fread($this->fp, $size); + } + + /** + * Write a specified amount of data. + * + * @param string $data Data to write. + * @param integer $blocksize Amount of data to write at once. + * NULL means all at once. + * + * @access public + * @return mixed If the socket is not connected, returns an instance of PEAR_Error + * If the write succeeds, returns the number of bytes written + * If the write fails, returns false. + */ + function write($data, $blocksize = null) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + if (is_null($blocksize) && !OS_WINDOWS) { + return @fwrite($this->fp, $data); + } else { + if (is_null($blocksize)) { + $blocksize = 1024; + } + + $pos = 0; + $size = strlen($data); + while ($pos < $size) { + $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); + if ($written === false) { + return false; + } + $pos += $written; + } + + return $pos; + } + } + + /** + * Write a line of data to the socket, followed by a trailing "\r\n". + * + * @access public + * @return mixed fputs result, or an error + */ + function writeLine($data) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return fwrite($this->fp, $data . "\r\n"); + } + + /** + * Tests for end-of-file on a socket descriptor. + * + * Also returns true if the socket is disconnected. + * + * @access public + * @return bool + */ + function eof() + { + return (!is_resource($this->fp) || feof($this->fp)); + } + + /** + * Reads a byte of data + * + * @access public + * @return 1 byte of data from the socket, or a PEAR_Error if + * not connected. + */ + function readByte() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return ord(@fread($this->fp, 1)); + } + + /** + * Reads a word of data + * + * @access public + * @return 1 word of data from the socket, or a PEAR_Error if + * not connected. + */ + function readWord() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); + } + + /** + * Reads an int of data + * + * @access public + * @return integer 1 int of data from the socket, or a PEAR_Error if + * not connected. + */ + function readInt() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + } + + /** + * Reads a zero-terminated string of data + * + * @access public + * @return string, or a PEAR_Error if + * not connected. + */ + function readString() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $string = ''; + while (($char = @fread($this->fp, 1)) != "\x00") { + $string .= $char; + } + return $string; + } + + /** + * Reads an IP Address and returns it in a dot formatted string + * + * @access public + * @return Dot formatted string, or a PEAR_Error if + * not connected. + */ + function readIPAddress() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]), + ord($buf[2]), ord($buf[3])); + } + + /** + * Read until either the end of the socket or a newline, whichever + * comes first. Strips the trailing newline from the returned data. + * + * @access public + * @return All available data up to a newline, without that + * newline, or until the end of the socket, or a PEAR_Error if + * not connected. + */ + function readLine() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $line = ''; + $timeout = time() + $this->timeout; + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { + $line .= @fgets($this->fp, $this->lineLength); + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Read until the socket closes, or until there is no more data in + * the inner PHP buffer. If the inner buffer is empty, in blocking + * mode we wait for at least 1 byte of data. Therefore, in + * blocking mode, if there is no data at all to be read, this + * function will never exit (unless the socket is closed on the + * remote end). + * + * @access public + * + * @return string All data until the socket closes, or a PEAR_Error if + * not connected. + */ + function readAll() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $data = ''; + while (!feof($this->fp)) { + $data .= @fread($this->fp, $this->lineLength); + } + return $data; + } + + /** + * Runs the equivalent of the select() system call on the socket + * with a timeout specified by tv_sec and tv_usec. + * + * @param integer $state Which of read/write/error to check for. + * @param integer $tv_sec Number of seconds for timeout. + * @param integer $tv_usec Number of microseconds for timeout. + * + * @access public + * @return False if select fails, integer describing which of read/write/error + * are ready, or PEAR_Error if not connected. + */ + function select($state, $tv_sec, $tv_usec = 0) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $read = null; + $write = null; + $except = null; + if ($state & NET_SOCKET_READ) { + $read[] = $this->fp; + } + if ($state & NET_SOCKET_WRITE) { + $write[] = $this->fp; + } + if ($state & NET_SOCKET_ERROR) { + $except[] = $this->fp; + } + if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { + return false; + } + + $result = 0; + if (count($read)) { + $result |= NET_SOCKET_READ; + } + if (count($write)) { + $result |= NET_SOCKET_WRITE; + } + if (count($except)) { + $result |= NET_SOCKET_ERROR; + } + return $result; + } + + /** + * Turns encryption on/off on a connected socket. + * + * @param bool $enabled Set this parameter to true to enable encryption + * and false to disable encryption. + * @param integer $type Type of encryption. See + * http://se.php.net/manual/en/function.stream-socket-enable-crypto.php for values. + * + * @access public + * @return false on error, true on success and 0 if there isn't enough data and the + * user should try again (non-blocking sockets only). A PEAR_Error object + * is returned if the socket is not connected + */ + function enableCrypto($enabled, $type) + { + if (version_compare(phpversion(), "5.1.0", ">=")) { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + return @stream_socket_enable_crypto($this->fp, $enabled, $type); + } else { + return $this->raiseError('Net_Socket::enableCrypto() requires php version >= 5.1.0'); + } + } + +} diff --git a/plugins/notification/sms_ftp/CHANGELOG b/plugins/notification/sms_ftp/CHANGELOG new file mode 100644 index 0000000..ba8ce8a --- /dev/null +++ b/plugins/notification/sms_ftp/CHANGELOG @@ -0,0 +1,16 @@ +1.2.3 (2007.11.19) +------------------ +Use init.inc.php + +1.2.2 (2007.10.17) +------------------ +Added the possibility to set a custom prefix for the file upload via ftp. + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro +Changed prefix for temp file in ortro_sms_ + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/notification/sms_ftp/LICENSE b/plugins/notification/sms_ftp/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/notification/sms_ftp/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/notification/sms_ftp/configure.php b/plugins/notification/sms_ftp/configure.php new file mode 100644 index 0000000..daf513d --- /dev/null +++ b/plugins/notification/sms_ftp/configure.php @@ -0,0 +1,61 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['sms_ftp'][0]['version'] = '1.2.3'; +$plugin_field['sms_ftp'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['sms_ftp'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['sms_ftp'][0]['title'] = PLUGIN_SMS_FTP_TITLE; +$plugin_field['sms_ftp'][0]['description'] = PLUGIN_SMS_FTP_DESCRIPTION; + +$plugin_field['sms_ftp'][1]['type'] = 'text'; +$plugin_field['sms_ftp'][1]['name'] = 'sms_ftp_dir'; +$plugin_field['sms_ftp'][1]['value'] = ''; +$plugin_field['sms_ftp'][1]['attributes'] = 'disabled size=50'; +$plugin_field['sms_ftp'][1]['description'] = PLUGIN_SMS_FTP_REMOTE_DIR_DESCRIPTION; +$plugin_field['sms_ftp'][1]['description_detail'] = PLUGIN_SMS_FTP_REMOTE_DIR_DESCRIPTION_DETAIL; + +$plugin_field['sms_ftp'][2]['type'] = 'text'; +$plugin_field['sms_ftp'][2]['name'] = 'sms_ftp_identity'; +$plugin_field['sms_ftp'][2]['value'] = ''; +$plugin_field['sms_ftp'][2]['attributes'] = 'disabled readonly size=50'; +$plugin_field['sms_ftp'][2]['description'] = PLUGIN_IDENTITY; +$plugin_field['sms_ftp'][2]['num_rules'] = '1'; +$plugin_field['sms_ftp'][2]['rule_msg'][0] = PLUGIN_IDENTITY_RULE; +$plugin_field['sms_ftp'][2]['rule_type'][0] = 'required'; +$plugin_field['sms_ftp'][2]['rule_attribute'][0] = ''; + +$plugin_field['sms_ftp'][3]['type'] = 'textarea'; +$plugin_field['sms_ftp'][3]['name'] = 'sms_ftp_message'; +$plugin_field['sms_ftp'][3]['value'] = ''; +$plugin_field['sms_ftp'][3]['attributes'] = 'disabled rows=10 cols=70'; +$plugin_field['sms_ftp'][3]['description'] = PLUGIN_SMS_FTP_MESSAGE_DESCRIPTION; + +$plugin_field['sms_ftp'][4]['type'] = 'checkbox'; +$plugin_field['sms_ftp'][4]['name'] = 'sms_ftp_attach_result'; +$plugin_field['sms_ftp'][4]['value'] = ''; +$plugin_field['sms_ftp'][4]['attributes'] = ''; +$plugin_field['sms_ftp'][4]['description'] = PLUGIN_ATTACH_RESULT; + +$plugin_field['sms_ftp'][5]['type'] = 'checkbox'; +$plugin_field['sms_ftp'][5]['name'] = 'sms_ftp_attach_timestamp'; +$plugin_field['sms_ftp'][5]['value'] = ''; +$plugin_field['sms_ftp'][5]['attributes'] = ''; +$plugin_field['sms_ftp'][5]['description'] = PLUGIN_ATTACH_DATE; +?> \ No newline at end of file diff --git a/plugins/notification/sms_ftp/configure_metadata.php b/plugins/notification/sms_ftp/configure_metadata.php new file mode 100644 index 0000000..a618a5a --- /dev/null +++ b/plugins/notification/sms_ftp/configure_metadata.php @@ -0,0 +1,39 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['sms_ftp']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['sms_ftp']['host']['description'] = PLUGIN_SMS_FTP_METADATA_SERVER_DESCRIPTION; +$conf_metadata['sms_ftp']['host']['type'] = 'text'; +$conf_metadata['sms_ftp']['host']['name'] = 'sms_ftp-host'; +$conf_metadata['sms_ftp']['host']['value'] = 'localhost'; +$conf_metadata['sms_ftp']['host']['attributes'] = 'size=30'; + +$conf_metadata['sms_ftp']['port']['description'] = PLUGIN_SMS_FTP_METADATA_PORT_DESCRIPTION; +$conf_metadata['sms_ftp']['port']['type'] = 'text'; +$conf_metadata['sms_ftp']['port']['name'] = 'sms_ftp-port'; +$conf_metadata['sms_ftp']['port']['value'] = ''; +$conf_metadata['sms_ftp']['port']['attributes'] = 'size=5'; + +$conf_metadata['sms_ftp']['file_prefix']['description'] = PLUGIN_SMS_FTP_METADATA_FILE_PREFIX_DESCRIPTION; +$conf_metadata['sms_ftp']['file_prefix']['type'] = 'text'; +$conf_metadata['sms_ftp']['file_prefix']['name'] = 'sms_ftp-file_prefix'; +$conf_metadata['sms_ftp']['file_prefix']['value'] = 'ortro_'; +$conf_metadata['sms_ftp']['file_prefix']['attributes'] = 'size=20'; +?> \ No newline at end of file diff --git a/plugins/notification/sms_ftp/core.php b/plugins/notification/sms_ftp/core.php new file mode 100644 index 0000000..93c42f2 --- /dev/null +++ b/plugins/notification/sms_ftp/core.php @@ -0,0 +1,114 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; + +global $conf; +require_once ORTRO_CONF_PLUGINS . 'notification_sms_ftp.php'; + +/** + * Uploads a brief text message via FTP, + * such as is used for SMS (Short Message System) + * + * @param array $elements The user form values + * @param array $attachments The files to attach + * + * @return void + */ +function sms_ftpNotify($elements,$attachments) +{ + $logger = new LogUtil('sms_ftp_notification'); + + $logger->trace('DEBUG', 'Sending sms using ftp interface'); + $ftp_server = $GLOBALS['conf']['sms_ftp']['host']; + $port = $GLOBALS['conf']['sms_ftp']['port']; + $file_prefix = $GLOBALS['conf']['sms_ftp']['file_prefix']; + + // set up basic connection + $conn_id = ftp_connect($ftp_server, $port); + + // login with username and password + $login_result = ftp_login($conn_id, + $elements['identity']['username'], + $elements['identity']['password']); + + // check connection + if ((!$conn_id) || (!$login_result)) { + $logger->trace('ERROR', "FTP connection has failed! " . + "Attempted to connect to $ftp_server for user " . + $elements['identity']['username']); + $exit_code = 1; + } else { + $logger->trace('DEBUG', "Connected to $ftp_server, for user " . + $elements['identity']['username']); + $exit_code = 0; + } + + //create the temporary sms message + $tempDir = ORTRO_NOTIFICATION_PLUGINS . 'tmp/'; + if (!is_dir($tempDir)) { + mkdir($tempDir); + } + $tempFile = $file_prefix . 'sms_' . + $elements['id_job'] . '_' . + time() . rand(); + @unlink($tempDir . $tempFile); // just in case + + $fh = fopen($tempDir . $tempFile, 'w+'); + $data_message = $elements['sms_ftp_message']; + if ($elements['sms_ftp_attach_result'] == '1' && + array_key_exists('txt', $attachments)) { + $data_message .= $attachments['txt']; + } + if ($elements['sms_ftp_attach_timestamp'] == '1') { + $data_message .= ' - Date: ' . date('Y-m-d H:i'); + } + fwrite($fh, $data_message); + fclose($fh); + chmod($tempDir . $tempFile, 0777); + + // try to change the directory to somedir if defined + if (isset($elements['sms_ftp_dir']) && $elements['sms_ftp_dir'] != '') { + if (ftp_chdir($conn_id, $elements['sms_ftp_dir'])) { + $logger->trace('DEBUG', "cd " . ftp_pwd($conn_id)); + } else { + $logger->trace('ERROR', "Couldn't change directory"); + } + } + + // upload the file + $upload = ftp_put($conn_id, $tempFile, $tempDir . $tempFile, FTP_ASCII); + + // check upload status + if (!$upload) { + $logger->trace('ERROR', 'FTP upload has failed!'); + } else { + $logger->trace('DEBUG', "Uploaded message to $ftp_server as $tempFile"); + } + // close the FTP stream + ftp_close($conn_id); + + //remove temp file + unlink($tempDir . $tempFile); + $logger->trace('DEBUG', 'Done.'); +} +?> \ No newline at end of file diff --git a/plugins/notification/tibco_rvd/CHANGELOG b/plugins/notification/tibco_rvd/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/notification/tibco_rvd/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/notification/tibco_rvd/LICENSE b/plugins/notification/tibco_rvd/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/notification/tibco_rvd/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/notification/tibco_rvd/configure.php b/plugins/notification/tibco_rvd/configure.php new file mode 100644 index 0000000..3dba28e --- /dev/null +++ b/plugins/notification/tibco_rvd/configure.php @@ -0,0 +1,66 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['tibco_rvd'][0]['version'] = '1.2.2'; +$plugin_field['tibco_rvd'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['tibco_rvd'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['tibco_rvd'][0]['title'] = PLUGIN_TIBCO_RVD_TITLE; +$plugin_field['tibco_rvd'][0]['description'] = PLUGIN_TIBCO_RVD_DESCRIPTION; + +$plugin_field['tibco_rvd'][1]['type'] = 'text'; +$plugin_field['tibco_rvd'][1]['name'] = 'tibco_rvd_service'; +$plugin_field['tibco_rvd'][1]['value'] = ''; +$plugin_field['tibco_rvd'][1]['attributes'] = 'disabled size=50'; +$plugin_field['tibco_rvd'][1]['description'] = PLUGIN_TIBCO_RVD_SERVICE_DESCRIPTION; + +$plugin_field['tibco_rvd'][2]['type'] = 'text'; +$plugin_field['tibco_rvd'][2]['name'] = 'tibco_rvd_network'; +$plugin_field['tibco_rvd'][2]['value'] = ''; +$plugin_field['tibco_rvd'][2]['attributes'] = 'disabled size=50'; +$plugin_field['tibco_rvd'][2]['description'] = PLUGIN_TIBCO_RVD_NETWORK_DESCRIPTION; + +$plugin_field['tibco_rvd'][3]['type'] = 'text'; +$plugin_field['tibco_rvd'][3]['name'] = 'tibco_rvd_daemon'; +$plugin_field['tibco_rvd'][3]['value'] = ''; +$plugin_field['tibco_rvd'][3]['attributes'] = 'disabled size=50'; +$plugin_field['tibco_rvd'][3]['description'] = PLUGIN_TIBCO_RVD_DAEMON_DESCRIPTION; + +$plugin_field['tibco_rvd'][4]['type'] = 'text'; +$plugin_field['tibco_rvd'][4]['name'] = 'tibco_rvd_subject'; +$plugin_field['tibco_rvd'][4]['value'] = ''; +$plugin_field['tibco_rvd'][4]['attributes'] = 'disabled size=50'; +$plugin_field['tibco_rvd'][4]['description'] = PLUGIN_TIBCO_RVD_SUBJECT_DESCRIPTION; +$plugin_field['tibco_rvd'][4]['num_rules'] = '1'; +$plugin_field['tibco_rvd'][4]['rule_msg'][0] = PLUGIN_TIBCO_RVD_RULE_4_0; +$plugin_field['tibco_rvd'][4]['rule_type'][0] = 'required'; +$plugin_field['tibco_rvd'][4]['rule_attribute'][0] = ''; + +$plugin_field['tibco_rvd'][5]['type'] = 'textarea'; +$plugin_field['tibco_rvd'][5]['name'] = 'tibco_rvd_message'; +$plugin_field['tibco_rvd'][5]['value'] = ''; +$plugin_field['tibco_rvd'][5]['attributes'] = 'disabled rows=10 cols=70'; +$plugin_field['tibco_rvd'][5]['description'] = PLUGIN_TIBCO_RVD_MESSAGE_DESCRIPTION; + +$plugin_field['tibco_rvd'][6]['type'] = 'checkbox'; +$plugin_field['tibco_rvd'][6]['name'] = 'tibco_rvd_attach_result'; +$plugin_field['tibco_rvd'][6]['value'] = ''; +$plugin_field['tibco_rvd'][6]['attributes'] = ''; +$plugin_field['tibco_rvd'][6]['description'] = PLUGIN_ATTACH_RESULT; +?> \ No newline at end of file diff --git a/plugins/notification/tibco_rvd/configure_metadata.php b/plugins/notification/tibco_rvd/configure_metadata.php new file mode 100644 index 0000000..d5595d8 --- /dev/null +++ b/plugins/notification/tibco_rvd/configure_metadata.php @@ -0,0 +1,27 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['tibco_rvd']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['tibco_rvd']['path']['description'] = PLUGIN_TIBCO_RVD_METADATA_TIBCO_PATH_DESCRIPTION; +$conf_metadata['tibco_rvd']['path']['type'] = 'text'; +$conf_metadata['tibco_rvd']['path']['name'] = 'tibco_rvd-path'; +$conf_metadata['tibco_rvd']['path']['value'] = '/opt/tibco/tibrv/bin/tibrvsend'; +$conf_metadata['tibco_rvd']['path']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/notification/tibco_rvd/core.php b/plugins/notification/tibco_rvd/core.php new file mode 100644 index 0000000..1c69e8c --- /dev/null +++ b/plugins/notification/tibco_rvd/core.php @@ -0,0 +1,67 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; + +global $conf; +require_once ORTRO_CONF_PLUGINS . 'notification_tibco_rvd.php'; + +/** + * Posts a Tibco Rendezvous Message. + * + * @param array $elements The user form values + * + * @return void + */ +function tibco_rvdNotify($elements) +{ + $logger = new LogUtil('tibco_rvd_notification'); + + $logger->trace('DEBUG', 'Sending Tibco rvd message'); + + $cmdLine = $GLOBALS['conf']['tibco_rvd']['path']; + + if ($elements['rvd_service'] != '') { + $cmdLine .= ' -service ' . $elements['rvd_service']; + } + if ($elements['rvd_network'] != '') { + $cmdLine .= ' -network "' . $elements['rvd_network'] . '"'; + } + if ($elements['rvd_daemon'] != '') { + $cmdLine .= ' -daemon ' . $elements['rvd_daemon']; + } + + $data_message = $elements['rvd_message']; + if ($elements['tibco_rvd_attach_result'] == '1' && + array_key_exists('txt', $attachments)) { + $data_message .= $attachments['txt']; + } + + $cmdLine .= ' "' . $elements['rvd_subject'] . '"' . + ' "' . $data_message . '"' . + ' 2>&1 &'; + + exec($cmdLine, $stdout, $exit_code); + + $logger->trace('DEBUG', 'tibrvsend output: ' . $stdout); + $logger->trace('DEBUG', 'Done.'); +} +?> \ No newline at end of file diff --git a/plugins/notification/tivoli_postemsg/CHANGELOG b/plugins/notification/tivoli_postemsg/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/notification/tivoli_postemsg/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/notification/tivoli_postemsg/LICENSE b/plugins/notification/tivoli_postemsg/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/notification/tivoli_postemsg/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/notification/tivoli_postemsg/configure.php b/plugins/notification/tivoli_postemsg/configure.php new file mode 100644 index 0000000..55f04d3 --- /dev/null +++ b/plugins/notification/tivoli_postemsg/configure.php @@ -0,0 +1,64 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['tivoli_postemsg'][0]['version'] = '1.2.2'; +$plugin_field['tivoli_postemsg'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['tivoli_postemsg'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['tivoli_postemsg'][0]['title'] = PLUGIN_TIVOLI_POSTEMSG_TITLE; +$plugin_field['tivoli_postemsg'][0]['description'] = PLUGIN_TIVOLI_POSTEMSG_DESCRIPTION; + +$plugin_field['tivoli_postemsg'][1]['type'] = 'select'; +$plugin_field['tivoli_postemsg'][1]['name'] = 'tivoli_postemsg_severity'; +$plugin_field['tivoli_postemsg'][1]['value'] = array('CRITICAL' => 'CRITICAL', + 'WARNING' => 'WARNING', + 'HARMLESS' => 'HARMLESS'); +$plugin_field['tivoli_postemsg'][1]['attributes'] = ''; +$plugin_field['tivoli_postemsg'][1]['description'] = PLUGIN_TIVOLI_POSTEMSG_SEVERITY_DESCRIPTION; + +$plugin_field['tivoli_postemsg'][2]['type'] = 'textarea'; +$plugin_field['tivoli_postemsg'][2]['name'] = 'tivoli_postemsg_message'; +$plugin_field['tivoli_postemsg'][2]['value'] = ''; +$plugin_field['tivoli_postemsg'][2]['attributes'] = 'disabled rows=10 cols=70'; +$plugin_field['tivoli_postemsg'][2]['description'] = PLUGIN_TIVOLI_POSTEMSG_MESSAGE_DESCRIPTION; + +$plugin_field['tivoli_postemsg'][3]['type'] = 'textarea'; +$plugin_field['tivoli_postemsg'][3]['name'] = 'tivoli_postemsg_attribute'; +$plugin_field['tivoli_postemsg'][3]['value'] = ''; +$plugin_field['tivoli_postemsg'][3]['attributes'] = 'disabled rows=10 cols=70'; +$plugin_field['tivoli_postemsg'][3]['description'] = PLUGIN_TIVOLI_POSTEMSG_ATTRIBUTE_DESCRIPTION; + +$plugin_field['tivoli_postemsg'][4]['type'] = 'text'; +$plugin_field['tivoli_postemsg'][4]['name'] = 'tivoli_postemsg_class'; +$plugin_field['tivoli_postemsg'][4]['value'] = ''; +$plugin_field['tivoli_postemsg'][4]['attributes'] = 'disabled size=50'; +$plugin_field['tivoli_postemsg'][4]['description'] = PLUGIN_TIVOLI_POSTEMSG_CLASS_DESCRIPTION; + +$plugin_field['tivoli_postemsg'][5]['type'] = 'text'; +$plugin_field['tivoli_postemsg'][5]['name'] = 'tivoli_postemsg_source'; +$plugin_field['tivoli_postemsg'][5]['value'] = ''; +$plugin_field['tivoli_postemsg'][5]['attributes'] = 'disabled size=50'; +$plugin_field['tivoli_postemsg'][5]['description'] = PLUGIN_TIVOLI_POSTEMSG_SOURCE_DESCRIPTION; + +$plugin_field['tivoli_postemsg'][6]['type'] = 'checkbox'; +$plugin_field['tivoli_postemsg'][6]['name'] = 'tivoli_postemsg_attach_result'; +$plugin_field['tivoli_postemsg'][6]['value'] = ''; +$plugin_field['tivoli_postemsg'][6]['attributes'] = ''; +$plugin_field['tivoli_postemsg'][6]['description'] = PLUGIN_ATTACH_RESULT; +?> \ No newline at end of file diff --git a/plugins/notification/tivoli_postemsg/configure_metadata.php b/plugins/notification/tivoli_postemsg/configure_metadata.php new file mode 100644 index 0000000..f792772 --- /dev/null +++ b/plugins/notification/tivoli_postemsg/configure_metadata.php @@ -0,0 +1,33 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$conf_metadata['tivoli_postemsg']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['tivoli_postemsg']['path']['description'] = PLUGIN_TIVOLI_POSTEMSG_METADATA_TIVOLI_PATH_DESCRIPTION; +$conf_metadata['tivoli_postemsg']['path']['type'] = 'text'; +$conf_metadata['tivoli_postemsg']['path']['name'] = 'tivoli_postemsg-path'; +$conf_metadata['tivoli_postemsg']['path']['value'] = '/opt/Tivoli/lcf/bin/postemsg'; +$conf_metadata['tivoli_postemsg']['path']['attributes'] = 'size=30'; + +$conf_metadata['tivoli_postemsg']['host']['description'] = PLUGIN_TIVOLI_POSTEMSG_METADATA_SERVER_DESCRIPTION; +$conf_metadata['tivoli_postemsg']['host']['type'] = 'text'; +$conf_metadata['tivoli_postemsg']['host']['name'] = 'tivoli_postemsg-host'; +$conf_metadata['tivoli_postemsg']['host']['value'] = 'localhost'; +$conf_metadata['tivoli_postemsg']['host']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/notification/tivoli_postemsg/core.php b/plugins/notification/tivoli_postemsg/core.php new file mode 100644 index 0000000..b281189 --- /dev/null +++ b/plugins/notification/tivoli_postemsg/core.php @@ -0,0 +1,57 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'logUtil.php'; + +global $conf; +require_once ORTRO_CONF_PLUGINS . 'notification_tivoli_postemsg.php'; + +/** + * Posts an event to the event server using non-Tivoli communication + * + * @param array $elements The user form values + * @param array $attachments The files to attach + * + * @return void + */ +function tivoli_postemsgNotify($elements,$attachments) +{ + $logger = new LogUtil('tivoli_postemsg_notification'); + + $logger->trace('DEBUG', 'Sending tivoli postemsg'); + $data_message = $elements['tivoli_postemsg_message']; + if ($elements['tivoli_postemsg_attach_result'] == '1' && + array_key_exists('txt', $attachments)) { + $data_message .= $attachments['txt']; + } + $cmdLine = $GLOBALS['conf']['tivoli_postemsg']['path'] . + ' -S ' . $GLOBALS['conf']['tivoli_postemsg']['host'] . + ' -r ' . $elements['tivoli_postemsg_severity'] . + ' -m "' . $data_message . '" ' . + $elements['tivoli_postemsg_attribute'] . + ' "' . $elements['tivoli_postemsg_class'] . '" ' . + ' "' . $elements['tivoli_postemsg_source'] . '" ' . + ' 2>&1 &'; + + exec($cmdLine, $stdout, $exit_code); + $logger->trace('DEBUG', 'postemsg output: ' . $cmdLine); + $logger->trace('DEBUG', 'Done.'); +} +?> \ No newline at end of file diff --git a/plugins/system/check_glance_status/CHANGELOG b/plugins/system/check_glance_status/CHANGELOG new file mode 100644 index 0000000..a4aee06 --- /dev/null +++ b/plugins/system/check_glance_status/CHANGELOG @@ -0,0 +1,7 @@ +1.0.1 (2009.08.06) +------------------ +Fix. Update to work with latest ssh library + +1.0.0 (2007.11.19) +------------------ +Initial release with i18n support diff --git a/plugins/system/check_glance_status/LICENSE b/plugins/system/check_glance_status/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/check_glance_status/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/check_glance_status/configure.php b/plugins/system/check_glance_status/configure.php new file mode 100644 index 0000000..0857807 --- /dev/null +++ b/plugins/system/check_glance_status/configure.php @@ -0,0 +1,114 @@ + + * @author Danilo Alfano + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['check_glance_status'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['check_glance_status'][0]['action'] = 'plugin'; +$plugin_actions['check_glance_status'][0]['file'] = 'display_archive_results'; +$plugin_actions['check_glance_status'][0]['image'] = 'archive.png'; + +$plugin_field['check_glance_status'][0]['version'] = '1.0.1'; +$plugin_field['check_glance_status'][0]['min_ortro_version'] = '1.2.0'; + +$plugin_field['check_glance_status'][0]['authors'][0] = 'Marcello Sessa '; +$plugin_field['check_glance_status'][0]['authors'][1] = 'Danilo Alfano '; +$plugin_field['check_glance_status'][0]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_DESCRIPTION; +$plugin_field['check_glance_status'][0]['title'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_TITLE; + +$plugin_field['check_glance_status'][1]['type'] = 'text'; +$plugin_field['check_glance_status'][1]['name'] = 'check_glance_status_dir_path'; +$plugin_field['check_glance_status'][1]['value'] = ''; +$plugin_field['check_glance_status'][1]['attributes'] = 'disabled size=70'; +$plugin_field['check_glance_status'][1]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_PATH_COMMAND; +$plugin_field['check_glance_status'][1]['num_rules'] = '1'; +$plugin_field['check_glance_status'][1]['rule_msg'][0] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_RULE_1_0; +$plugin_field['check_glance_status'][1]['rule_type'][0] = 'required'; +$plugin_field['check_glance_status'][1]['rule_attribute'][0] = ''; + +$plugin_field['check_glance_status'][2]['type'] = 'text'; +$plugin_field['check_glance_status'][2]['name'] = 'check_glance_status_user'; +$plugin_field['check_glance_status'][2]['value'] = ''; +$plugin_field['check_glance_status'][2]['attributes'] = 'disabled'; +$plugin_field['check_glance_status'][2]['description'] = PLUGIN_USER; +$plugin_field['check_glance_status'][2]['num_rules'] = '1'; +$plugin_field['check_glance_status'][2]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['check_glance_status'][2]['rule_type'][0] = 'required'; +$plugin_field['check_glance_status'][2]['rule_attribute'][0] = ''; + +$plugin_field['check_glance_status'][3]['type'] = 'text'; +$plugin_field['check_glance_status'][3]['name'] = 'check_glance_status_port'; +$plugin_field['check_glance_status'][3]['value'] = ''; +$plugin_field['check_glance_status'][3]['attributes'] = 'disabled'; +$plugin_field['check_glance_status'][3]['description'] = PLUGIN_PORT; + +$plugin_field['check_glance_status'][4]['type'] = 'select'; +$plugin_field['check_glance_status'][4]['name'] = 'check_glance_type'; +$plugin_field['check_glance_status'][4]['value'] = array('CPU' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_CPU, + 'IO' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_IO, + 'MEM' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_MEM, + 'NFS' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_NFS, + 'PRO' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_PRO, + 'NET' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_NET); + +$plugin_field['check_glance_status'][4]['attributes'] = ''; +$plugin_field['check_glance_status'][4]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_TYPE; +$plugin_field['check_glance_status'][4]['num_rules'] = '1'; +$plugin_field['check_glance_status'][4]['rule_msg'][0] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_RULE_4_0; +$plugin_field['check_glance_status'][4]['rule_type'][0] = 'required'; +$plugin_field['check_glance_status'][4]['rule_attribute'][0] = ''; + +$plugin_field['check_glance_status'][5]['type'] = 'text'; +$plugin_field['check_glance_status'][5]['name'] = 'check_glance_status_number'; +$plugin_field['check_glance_status'][5]['value'] = ''; +$plugin_field['check_glance_status'][5]['attributes'] = 'disabled'; +$plugin_field['check_glance_status'][5]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_NUMBER_DESCRIPTION; + +$plugin_field['check_glance_status'][6]['type'] = 'select'; +$plugin_field['check_glance_status'][6]['name'] = 'check_glance_status_operator'; +$plugin_field['check_glance_status'][6]['value'] = array('>' => '>', '<' => '<', '=' => '=', '!=' => '!='); +$plugin_field['check_glance_status'][6]['attributes'] = ''; +$plugin_field['check_glance_status'][6]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_OPERATOR_DESCRIPTION; +$plugin_field['check_glance_status'][6]['num_rules'] = '0'; + +$plugin_field['check_glance_status'][7]['type'] = 'text'; +$plugin_field['check_glance_status'][7]['name'] = 'check_glance_status_threshold'; +$plugin_field['check_glance_status'][7]['value'] = ''; +$plugin_field['check_glance_status'][7]['attributes'] = 'disabled'; +$plugin_field['check_glance_status'][7]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_THRESHOLD_DESCRIPTION; +$plugin_field['check_glance_status'][7]['num_rules'] = '1'; +$plugin_field['check_glance_status'][7]['rule_msg'][0] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_RULE_7_0; +$plugin_field['check_glance_status'][7]['rule_type'][0] = 'required'; +$plugin_field['check_glance_status'][7]['rule_attribute'][0] = ''; + +$plugin_field['check_glance_status'][8]['type'] = 'select'; +$plugin_field['check_glance_status'][8]['name'] = 'check_glance_status_is_error'; +$plugin_field['check_glance_status'][8]['value'] = array('0' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_SUCCESS, + '1' => PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_ERROR); +$plugin_field['check_glance_status'][8]['attributes'] = ''; +$plugin_field['check_glance_status'][8]['description'] = PLUGIN_SYSTEM_CHECK_GLANCE_STATUS_ERROR_DESCRIPTION; +$plugin_field['check_glance_status'][8]['num_rules'] = '0'; + +$plugin_field['check_glance_status'][9]['type'] = 'text'; +$plugin_field['check_glance_status'][9]['name'] = 'check_glance_retention'; +$plugin_field['check_glance_status'][9]['value'] = ''; +$plugin_field['check_glance_status'][9]['attributes'] = 'disabled'; +$plugin_field['check_glance_status'][9]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/system/check_glance_status/core.php b/plugins/system/check_glance_status/core.php new file mode 100644 index 0000000..7cca32b --- /dev/null +++ b/plugins/system/check_glance_status/core.php @@ -0,0 +1,114 @@ + + * @author Danilo Alfano + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['check_glance_status_user']; + $port = $parameters['check_glance_status_port']; + + // The absolute path of glance command + $dir_path = '"' . $parameters['check_glance_status_dir_path'] . '"'; + // The parameter to pass to the glance command + $type = '"' . $parameters['check_glance_type'] . '"'; + // The parameter to pass for the number of checks + $number = '"' . $parameters['check_glance_status_number'] . '"'; + + $script_parameters = array($dir_path, $type, $number); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/glance.sh'; + + $local_parameters = implode(' ', $script_parameters); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['check_glance_retention']; + var_dump($retention_data); + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); + +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/check_glance_status/glance.sh b/plugins/system/check_glance_status/glance.sh new file mode 100755 index 0000000..1b2d414 --- /dev/null +++ b/plugins/system/check_glance_status/glance.sh @@ -0,0 +1,94 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License v2 +# a copy of which has been included with this distribution in the LICENSE file. +# +# This script allows you to monitor the tail of a specified file +# +# File Authors: +# Marcello Sessa +# Danilo Alfano +# +################################################################################## + +#!/bin/sh + +# Date for other applications +GetDate=`date +"%Y%m%d"` + +LOG_NM=/fs_app_oracle/ortro/glance.$GetDate + +if [ "$2" = "" ] + then + echo " usage: ./glance.sh glance_absolute_path parameter [times]" + echo "" + echo " path : i.e. /opt/perf/bin/" + echo " parameter: " + echo " CPU for cpu usage" + echo " IO for global io peak" + echo " MEM for memory used" + echo " PRO for total processes started" + echo " NET for global packet rate" + echo " NFS for global NFS calls\n\n\n" + echo " times: calculate the average value on the specified times of checks\n\n" + +else + + case $2 in + CPU) echo "print GBL_CPU_TOTAL_UTIL" > config.cf + ;; + IO) echo "print GBL_DISK_UTIL_PEAK" > config.cf + ;; + MEM) echo "print GBL_MEM_UTIL" > config.cf + ;; + PRO) echo "print GBL_ACTIVE_PROC" > config.cf + ;; + NET) echo "print GBL_NET_PACKET_RATE" > config.cf + ;; + NFS) echo "print GBL_NFS_CALL_RATE" > config.cf + ;; + *) echo "\n call ./glance.sh without parameters for help online\n" + ;; + esac + + + if [ "$3" = "" ] + then TIMES="1" + else + TIMES=$3 + fi + + I=0 + SUM=0 + + while test "$I" -lt "$TIMES" + do + : $((I=I+1)) + + $1glance -adviser_only -syntax ./config.cf -iterations 2 -j 2 1>1shadow 2>2shadow + ERROR=`tail -1 2shadow` + if [ "$ERROR" -ne "" ] + then + rm 1shadow + rm 2shadow + rm config.cf + echo $ERROR + exit 1 + fi + + RESULT=`tail -1 1shadow` + : $((RES_C=RESULT*100)) + #echo $RES_C + : $((SUM=SUM+RES_C)) + done + + : $((AVG_RES_C=SUM/$TIMES)) + : $((AVG_RESULT=AVG_RES_C/100)) + #echo "la media "$AVG_RESULT + echo $AVG_RESULT + rm 1shadow + rm 2shadow + rm config.cf +fi diff --git a/plugins/system/cpu_idle/CHANGELOG b/plugins/system/cpu_idle/CHANGELOG new file mode 100644 index 0000000..932da92 --- /dev/null +++ b/plugins/system/cpu_idle/CHANGELOG @@ -0,0 +1,19 @@ +1.0.4 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.3 (2008.06.13) +------------------ +Fixed. #75 CPU idle plugin does not work correctly on all platforms + +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.0.0 (2007.07.24) +------------------ +Initial release with i18n support diff --git a/plugins/system/cpu_idle/LICENSE b/plugins/system/cpu_idle/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/cpu_idle/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/cpu_idle/configure.php b/plugins/system/cpu_idle/configure.php new file mode 100644 index 0000000..0d50bb9 --- /dev/null +++ b/plugins/system/cpu_idle/configure.php @@ -0,0 +1,66 @@ + + * @author Francesco Acquista + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['cpu_idle'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['cpu_idle'][0]['action'] = 'plugin'; +$plugin_actions['cpu_idle'][0]['file'] = 'display_archive_results'; +$plugin_actions['cpu_idle'][0]['image'] = 'archive.png'; + +$plugin_field['cpu_idle'][0]['version'] = '1.0.4'; +$plugin_field['cpu_idle'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['cpu_idle'][0]['authors'][0] = 'Fabrizio Cardarello '; +$plugin_field['cpu_idle'][0]['authors'][1] = 'Francesco Acquista '; +$plugin_field['cpu_idle'][0]['description'] = PLUGIN_CPU_IDLE_DESCRIPTION; +$plugin_field['cpu_idle'][0]['title'] = PLUGIN_CPU_IDLE_TITLE; + +$plugin_field['cpu_idle'][1]['type'] = 'text'; +$plugin_field['cpu_idle'][1]['name'] = 'cpu_idle_user'; +$plugin_field['cpu_idle'][1]['value'] = ''; +$plugin_field['cpu_idle'][1]['attributes'] = 'disabled'; +$plugin_field['cpu_idle'][1]['description'] = PLUGIN_USER; +$plugin_field['cpu_idle'][1]['num_rules'] = '1'; +$plugin_field['cpu_idle'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['cpu_idle'][1]['rule_type'][0] = 'required'; +$plugin_field['cpu_idle'][1]['rule_attribute'][0] = ''; + +$plugin_field['cpu_idle'][2]['type'] = 'text'; +$plugin_field['cpu_idle'][2]['name'] = 'cpu_idle_port'; +$plugin_field['cpu_idle'][2]['value'] = ''; +$plugin_field['cpu_idle'][2]['attributes'] = 'disabled'; +$plugin_field['cpu_idle'][2]['description'] = PLUGIN_PORT; + +$plugin_field['cpu_idle'][3]['type'] = 'text'; +$plugin_field['cpu_idle'][3]['name'] = 'cpu_idle_threshold'; +$plugin_field['cpu_idle'][3]['value'] = ''; +$plugin_field['cpu_idle'][3]['attributes'] = 'disabled'; +$plugin_field['cpu_idle'][3]['description'] = PLUGIN_CPU_IDLE_THRESHOLD_DESCRIPTION; +$plugin_field['cpu_idle'][3]['num_rules'] = '1'; +$plugin_field['cpu_idle'][3]['rule_msg'][0] = PLUGIN_CPU_IDLE_RULE_3_0; +$plugin_field['cpu_idle'][3]['rule_type'][0] = 'required'; +$plugin_field['cpu_idle'][3]['rule_attribute'][0] = ''; + +$plugin_field['cpu_idle'][4]['type'] = 'text'; +$plugin_field['cpu_idle'][4]['name'] = 'cpu_idle_retention'; +$plugin_field['cpu_idle'][4]['value'] = ''; +$plugin_field['cpu_idle'][4]['attributes'] = 'disabled'; +$plugin_field['cpu_idle'][4]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/system/cpu_idle/core.php b/plugins/system/cpu_idle/core.php new file mode 100644 index 0000000..ad29623 --- /dev/null +++ b/plugins/system/cpu_idle/core.php @@ -0,0 +1,99 @@ + + * @author Francesco Acquista + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + $user = $parameters['cpu_idle_user']; + $port = $parameters['cpu_idle_port']; + + // threshold + $threshold = $parameters['cpu_idle_threshold']; + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/cpu-idle.ksh'; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $threshold); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> diff --git a/plugins/system/cpu_idle/cpu-idle.ksh b/plugins/system/cpu_idle/cpu-idle.ksh new file mode 100644 index 0000000..70e9c90 --- /dev/null +++ b/plugins/system/cpu_idle/cpu-idle.ksh @@ -0,0 +1,22 @@ +#!/usr/bin/ksh +# Author: Fabrizio Cardarello +# + +RESULT_FILE=/tmp/ortroCpuIdleResult +sar -u 10 1 > $RESULT_FILE + +IDLE_COL_N=$(cat $RESULT_FILE | grep % | tr " " "\n" | grep -v [AP]M | cat -b | grep idle | awk {'print $1'}) + +THRESHOLD=${1:-90} +VAR=$(cat $RESULT_FILE | tail -1 | awk '{print $'$IDLE_COL_N'}' | tr , .) +echo $VAR + +THRESHOLD_CONV=$(echo "$THRESHOLD * 10000" | bc | awk -F. {'print $1'}) +VAR_CONV=$(echo "$VAR * 10000" | bc | awk -F. {'print $1'}) +[ $VAR_CONV -gt $THRESHOLD_CONV ] && exit 0 || exit 1 diff --git a/plugins/system/file_system_check/CHANGELOG b/plugins/system/file_system_check/CHANGELOG new file mode 100644 index 0000000..8f225e9 --- /dev/null +++ b/plugins/system/file_system_check/CHANGELOG @@ -0,0 +1,19 @@ +1.2.4 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.2.3 (2008.03.06) +------------------ +Fix. [1908650] Missed error handling on ssh connection failure. + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/system/file_system_check/LICENSE b/plugins/system/file_system_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/file_system_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/file_system_check/configure.php b/plugins/system/file_system_check/configure.php new file mode 100644 index 0000000..d2775a9 --- /dev/null +++ b/plugins/system/file_system_check/configure.php @@ -0,0 +1,48 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['file_system_check'][0]['version'] = '1.2.4'; +$plugin_field['file_system_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['file_system_check'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['file_system_check'][0]['description'] = PLUGIN_FILE_SYSTEM_CHECK_DESCRIPTION; +$plugin_field['file_system_check'][0]['title'] = PLUGIN_FILE_SYSTEM_CHECK_TITLE; + +$plugin_field['file_system_check'][1]['type'] = 'text'; +$plugin_field['file_system_check'][1]['name'] = 'file_system_check_user'; +$plugin_field['file_system_check'][1]['value'] = ''; +$plugin_field['file_system_check'][1]['attributes'] = 'disabled'; +$plugin_field['file_system_check'][1]['description'] = PLUGIN_USER; +$plugin_field['file_system_check'][1]['num_rules'] = '1'; +$plugin_field['file_system_check'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['file_system_check'][1]['rule_type'][0] = 'required'; +$plugin_field['file_system_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['file_system_check'][2]['type'] = 'text'; +$plugin_field['file_system_check'][2]['name'] = 'file_system_check_port'; +$plugin_field['file_system_check'][2]['value'] = ''; +$plugin_field['file_system_check'][2]['attributes'] = 'disabled'; +$plugin_field['file_system_check'][2]['description'] = PLUGIN_PORT; + +$plugin_field['file_system_check'][3]['type'] = 'submit'; +$plugin_field['file_system_check'][3]['name'] = 'file_system_check_get_dynamic_params'; +$plugin_field['file_system_check'][3]['value'] = 'Refresh'; +$plugin_field['file_system_check'][3]['attributes'] = 'disabled'; +$plugin_field['file_system_check'][3]['description'] = PLUGIN_FILE_SYSTEM_CHECK_REFRESH_DESCRIPTION; +?> \ No newline at end of file diff --git a/plugins/system/file_system_check/core.php b/plugins/system/file_system_check/core.php new file mode 100644 index 0000000..4a24949 --- /dev/null +++ b/plugins/system/file_system_check/core.php @@ -0,0 +1,143 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + include_once 'Pear/HTML/Table.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['file_system_check_user']; + $port = $parameters['file_system_check_port']; + $dynamic_fields = $parameters['dyn_params']; + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/script.sh'; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $attachments['txt'] = 'Filesystem'. ' ---> Capacity' . "\n"; + + $table_attributes = 'cellpadding=0 cellspacing=0 border=0 width=100%'; + + $table = new HTML_Table($table_attributes); + $table->addRow(array('Filesystem', + 'MountPoint', + 'Capacity', + 'Threshold (%)'), '', 'TH', false); + $fs_alert = array(); + if ($exit_code == '0') { + $result = '1'; + for ($index = 0; $index < sizeof($stdout); $index++) { + if (preg_match('/^\/.*%$/', $stdout[$index]) == 1) { + $fs_values = explode(' ', $stdout[$index]); + if (array_key_exists($fs_values[0], $dynamic_fields)) { + $perc = substr($fs_values[2], 0, strlen($fs_values[2])-1); + $loggerPlugin->trace('DEBUG', $perc . + '>=' . + $dynamic_fields[$fs_values[0]]); + if ($perc >= $dynamic_fields[$fs_values[0]]) { + $alert = true; + array_push($fs_alert, $fs_values[0]); + } + $table->addRow(array($fs_values[0], + $fs_values[1], + $fs_values[2], + $dynamic_fields[$fs_values[0]] . '%'), + '', 'TD', false); + $attachments['txt'] .= $fs_values[0] . " ---> " . + $fs_values[2] . "\n"; + } + } + } + + $attachments['html'] = $table->toHTML(); + + if ($alert) { + $result = '0'; + $msg = 'The following filesystem have exceeded ' . + 'the specified threshold:'; + + $attachments['txt'] = $msg . "\n" . implode(' ', $fs_alert) . + "\n\n" . $attachments['txt']; + $attachments['html'] = $msg. "
" . implode(' ', $fs_alert) . + "

" . $attachments['html']; + } + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + } else { + $attachments['txt'] = implode("\n", $stdout); + $loggerPlugin->trace('ERROR', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $attachments['html'] = implode("
", $stdout); + + $result = '0'; + } + $msg_exec = $attachments['txt']; + $loggerPlugin->trace('INFO', 'Job ' . $plugin_name . + ' with id=' . $id_job . ' done.'); + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/file_system_check/dynamic_parameters.php b/plugins/system/file_system_check/dynamic_parameters.php new file mode 100644 index 0000000..15d9ccc --- /dev/null +++ b/plugins/system/file_system_check/dynamic_parameters.php @@ -0,0 +1,103 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once 'sshUtil.php'; +/** + * Allows to display the space available on all currently + * mounted file systems of a remote server + * + * @param string $ip IP address + * @param array $plugin_info Plugin info + * @param object $form The form object + * + * @return string + */ +function get_dynamic_params($ip, $plugin_info, $form) +{ + include_once 'langUtil.php'; + i18n('system', 'file_system_check'); + + $table_attributes = 'cellpadding=0 cellspacing=0 border=0 width=100%'; + + $ssh = new SSHUtil(); + $script = realpath(dirname(__FILE__)) . '/script.sh'; + + //get static parameter + $user = $plugin_info['file_system_check_user']; + $port = $plugin_info['file_system_check_port']; + + //get the dynamic parameters and put them in an array + //(i.e. $dynamic_fields['/dev/hda1'] = 50) + $dynamic_fields = $plugin_info['dyn_params']; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true); + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + $table = new HTML_Table($table_attributes); + + $table->addRow(array(PLUGIN_FILE_SYSTEM_CHECK_FILESYSTEM, + PLUGIN_FILE_SYSTEM_CHECK_MOUNTPOINT, + PLUGIN_FILE_SYSTEM_CHECK_CAPACITY, + PLUGIN_FILE_SYSTEM_CHECK_THRESHOLD), '', 'TH', false); + + if ($exit_code == '0') { + for ($index = 0; $index < sizeof($stdout); $index++) { + if (preg_match('/^\/.*%$/', $stdout[$index]) == 1) { + $tempArray = explode(' ', $stdout[$index]); + $f_th_obj = $form->addElement('text', + 'dynamic_field_' . $tempArray[0], + '', + 'size=3'); + if (isset($dynamic_fields[$tempArray[0]]) && + $dynamic_fields[$tempArray[0]] != '') { + $f_th_obj->setValue($dynamic_fields[$tempArray[0]]); + } + $f_th = $f_th_obj->toHTML(); + $form->addRule('dynamic_field_' . $tempArray[0], + $tempArray[0] . ': ' . + PLUGIN_FILE_SYSTEM_CHECK_MSG_THRESHOLD_1, + 'numeric', + '', + 'client'); + $form->addRule('dynamic_field_' . $tempArray[0], + $tempArray[0] . ': ' . + PLUGIN_FILE_SYSTEM_CHECK_MSG_THRESHOLD_2, + 'rangeValue', + '1-100', + 'client'); + $table->addRow(array($tempArray[0], + $tempArray[1], + $tempArray[2], + $f_th), '', 'TD', false); + } + } + } else { + $error_message = 'The following error has occurred during the ssh connection:
' . + implode("
", $stdout); + $table->addRow(array($error_message), 'colspan=4', 'TD', false); + } + $html = $table->toHTML(); + return $html; +} +?> \ No newline at end of file diff --git a/plugins/system/file_system_check/script.sh b/plugins/system/file_system_check/script.sh new file mode 100644 index 0000000..8cd9f5a --- /dev/null +++ b/plugins/system/file_system_check/script.sh @@ -0,0 +1,26 @@ +################################################################################## +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License +# a copy of which has been included with this distribution in the LICENSE file. +# +# File System Check script +# Get the space available on all currently mounted file systems +# +# File Authors: +# Luca Corbo +# +################################################################################## + +# Add bdf comman support +PATH_BDF=`which bdf` +IS_PRESENT_BDF=$? +if [ "x$IS_PRESENT_BDF" = "x0" ] +then + COMMAND="bdf" +else + COMMAND="df -k" +fi + +$COMMAND | sed -e '/^[^ ][^ ]*$/{ N ; s/[ ]*\n[ ]*/ / ;}' | grep '^/' | awk '{print $1 " " $6 " " $5}' diff --git a/plugins/system/mem_free/CHANGELOG b/plugins/system/mem_free/CHANGELOG new file mode 100644 index 0000000..84d78df --- /dev/null +++ b/plugins/system/mem_free/CHANGELOG @@ -0,0 +1,7 @@ +1.0.1 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.0 (2008.06.18) +------------------ +Initial release with i18n support diff --git a/plugins/system/mem_free/LICENSE b/plugins/system/mem_free/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/mem_free/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/mem_free/configure.php b/plugins/system/mem_free/configure.php new file mode 100644 index 0000000..eaa5879 --- /dev/null +++ b/plugins/system/mem_free/configure.php @@ -0,0 +1,63 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['mem_free'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['mem_free'][0]['action'] = 'plugin'; +$plugin_actions['mem_free'][0]['file'] = 'display_archive_results'; +$plugin_actions['mem_free'][0]['image'] = 'archive.png'; + +$plugin_field['mem_free'][0]['version'] = '1.0.1'; +$plugin_field['mem_free'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['mem_free'][0]['authors'][0] = 'Francesco Acquista '; +$plugin_field['mem_free'][0]['description'] = PLUGIN_MEM_FREE_DESCRIPTION; +$plugin_field['mem_free'][0]['title'] = PLUGIN_MEM_FREE_TITLE; + +$plugin_field['mem_free'][1]['type'] = 'text'; +$plugin_field['mem_free'][1]['name'] = 'mem_free_user'; +$plugin_field['mem_free'][1]['value'] = ''; +$plugin_field['mem_free'][1]['attributes'] = 'disabled'; +$plugin_field['mem_free'][1]['description'] = PLUGIN_USER; +$plugin_field['mem_free'][1]['num_rules'] = '1'; +$plugin_field['mem_free'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['mem_free'][1]['rule_type'][0] = 'required'; +$plugin_field['mem_free'][1]['rule_attribute'][0] = ''; + +$plugin_field['mem_free'][2]['type'] = 'text'; +$plugin_field['mem_free'][2]['name'] = 'mem_free_port'; +$plugin_field['mem_free'][2]['value'] = ''; +$plugin_field['mem_free'][2]['attributes'] = 'disabled'; +$plugin_field['mem_free'][2]['description'] = PLUGIN_PORT; + +$plugin_field['mem_free'][3]['type'] = 'text'; +$plugin_field['mem_free'][3]['name'] = 'mem_free_threshold'; +$plugin_field['mem_free'][3]['value'] = ''; +$plugin_field['mem_free'][3]['attributes'] = 'disabled'; +$plugin_field['mem_free'][3]['description'] = PLUGIN_MEM_FREE_THRESHOLD_DESCRIPTION; +$plugin_field['mem_free'][3]['num_rules'] = '1'; +$plugin_field['mem_free'][3]['rule_msg'][0] = PLUGIN_MEM_FREE_RULE_3_0; +$plugin_field['mem_free'][3]['rule_type'][0] = 'required'; +$plugin_field['mem_free'][3]['rule_attribute'][0] = ''; + +$plugin_field['mem_free'][4]['type'] = 'text'; +$plugin_field['mem_free'][4]['name'] = 'mem_free_retention'; +$plugin_field['mem_free'][4]['value'] = ''; +$plugin_field['mem_free'][4]['attributes'] = 'disabled'; +$plugin_field['mem_free'][4]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/system/mem_free/core.php b/plugins/system/mem_free/core.php new file mode 100644 index 0000000..e0e520f --- /dev/null +++ b/plugins/system/mem_free/core.php @@ -0,0 +1,98 @@ + + * @author Francesco Acquista + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + $user = $parameters['mem_free_user']; + $port = $parameters['mem_free_port']; + + // threshold + $threshold = $parameters['mem_free_threshold']; + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/mem-free.ksh'; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $threshold); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> diff --git a/plugins/system/mem_free/mem-free.ksh b/plugins/system/mem_free/mem-free.ksh new file mode 100644 index 0000000..8585ae5 --- /dev/null +++ b/plugins/system/mem_free/mem-free.ksh @@ -0,0 +1,13 @@ +#!/usr/bin/ksh +# Author: Francesco Acquista +# Description: This script check the amount of the free memory (percentage) +# and compare it with you threshold value. +# Argument: $1 is a threshold + +THRESHOLD=${1:-50} +MEM_TOT=`free | grep Mem | awk {'print $2'}` +MEM_FREE=`free | grep buffers/ | awk {'print $4'}` +FREE_PERC=`echo "$MEM_FREE * 100 / $MEM_TOT" | bc` + +echo $FREE_PERC +[ $FREE_PERC -gt $THRESHOLD ] && exit 0 || exit 1 diff --git a/plugins/system/ping/CHANGELOG b/plugins/system/ping/CHANGELOG new file mode 100644 index 0000000..d68b2c0 --- /dev/null +++ b/plugins/system/ping/CHANGELOG @@ -0,0 +1,19 @@ +1.2.4 (2009.09.22) +------------------ +Changed. Updated Pear library. + +1.2.3 (2008.01.07) +------------------ +Updated Ping Pear lib (v2.4.3) + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/system/ping/COPYRIGHT b/plugins/system/ping/COPYRIGHT new file mode 100644 index 0000000..e0fb026 --- /dev/null +++ b/plugins/system/ping/COPYRIGHT @@ -0,0 +1,33 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +Pear packages: +============== + +Net/Ping +--- +Copyright: 1997-2004 The PHP Group +License: PHP license + +OS/Guess +----------- +Copyright: 1997-2005 The PHP Group +License: PHP license \ No newline at end of file diff --git a/plugins/system/ping/LICENSE b/plugins/system/ping/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/ping/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/ping/configure.php b/plugins/system/ping/configure.php new file mode 100644 index 0000000..7560e6b --- /dev/null +++ b/plugins/system/ping/configure.php @@ -0,0 +1,26 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['ping'][0]['version'] = '1.2.4'; +$plugin_field['ping'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['ping'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['ping'][0]['description'] = PLUGIN_PING_DESCRIPTION; +$plugin_field['ping'][0]['title'] = PLUGIN_PING_TITLE; +?> \ No newline at end of file diff --git a/plugins/system/ping/core.php b/plugins/system/ping/core.php new file mode 100644 index 0000000..0186489 --- /dev/null +++ b/plugins/system/ping/core.php @@ -0,0 +1,83 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +set_include_path(realpath(dirname($argv[0])) . "/lib/:" . + ini_get("include_path")); +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); + +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'Pear/Net/Ping.php'; + + $result = 0; + + //Get the params required by plugin from argv + $ip = $job_infos['ip']; + + // create object + $ping = Net_Ping::factory(); + + // ping host and display response + if (!PEAR::isError($ping)) { + $response = $ping->ping($ip); + } + + if (!PEAR::isError($response)) { + if ($response->getReceived() > 0) { + $msg_exec = 'Alive'; + $result = 1; + } else { + $msg_exec = 'Host Unreachable'; + } + } else { + $msg_exec = $response->getMessage(); + } + + $attachments['html'] = $msg_exec; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/ping/lib/Pear/Net/Ping.php b/plugins/system/ping/lib/Pear/Net/Ping.php new file mode 100644 index 0000000..570e929 --- /dev/null +++ b/plugins/system/ping/lib/Pear/Net/Ping.php @@ -0,0 +1,1226 @@ + | +// | Tomas V.V.Cox | +// | Jan Lehnardt | +// | Kai Schrder | +// | Craig Constantine | +// +----------------------------------------------------------------------+ +// +// $Id: Ping.php,v 1.50 2009/01/27 20:14:00 cconstantine Exp $ + +require_once "PEAR.php"; +require_once "OS/Guess.php"; + +define('NET_PING_FAILED_MSG', 'execution of ping failed' ); +define('NET_PING_HOST_NOT_FOUND_MSG', 'unknown host' ); +define('NET_PING_INVALID_ARGUMENTS_MSG', 'invalid argument array' ); +define('NET_PING_CANT_LOCATE_PING_BINARY_MSG', 'unable to locate the ping binary'); +define('NET_PING_RESULT_UNSUPPORTED_BACKEND_MSG', 'Backend not Supported' ); + +define('NET_PING_FAILED', 0); +define('NET_PING_HOST_NOT_FOUND', 1); +define('NET_PING_INVALID_ARGUMENTS', 2); +define('NET_PING_CANT_LOCATE_PING_BINARY', 3); +define('NET_PING_RESULT_UNSUPPORTED_BACKEND', 4); + + +/** +* Wrapper class for ping calls +* +* Usage: +* +* getMessage(); +* } else { +* $ping->setArgs(array('count' => 2)); +* var_dump($ping->ping('example.com')); +* } +* ?> +* +* @author Jan Lehnardt +* @version $Revision: 1.50 $ +* @package Net +* @access public +*/ +class Net_Ping +{ + /** + * Location where the ping program is stored + * + * @var string + * @access private + */ + var $_ping_path = ""; + + /** + * Array with the result from the ping execution + * + * @var array + * @access private + */ + var $_result = array(); + + /** + * OS_Guess instance + * + * @var object + * @access private + */ + var $_OS_Guess = ""; + + /** + * OS_Guess->getSysname result + * + * @var string + * @access private + */ + var $_sysname = ""; + + /** + * Ping command arguments + * + * @var array + * @access private + */ + var $_args = array(); + + /** + * Indicates if an empty array was given to setArgs + * + * @var boolean + * @access private + */ + var $_noArgs = true; + + /** + * Contains the argument->option relation + * + * @var array + * @access private + */ + var $_argRelation = array(); + + /** + * Constructor for the Class + * + * @access private + */ + function Net_Ping($ping_path, $sysname) + { + $this->_ping_path = $ping_path; + $this->_sysname = $sysname; + $this->_initArgRelation(); + } /* function Net_Ping() */ + + /** + * Factory for Net_Ping + * + * @access public + */ + function factory() + { + $ping_path = ''; + + $sysname = Net_Ping::_setSystemName(); + + if (($ping_path = Net_Ping::_setPingPath($sysname)) == NET_PING_CANT_LOCATE_PING_BINARY) { + return PEAR::raiseError(NET_PING_CANT_LOCATE_PING_BINARY_MSG, NET_PING_CANT_LOCATE_PING_BINARY); + } else { + return new Net_Ping($ping_path, $sysname); + } + } /* function factory() */ + + /** + * Resolve the system name + * + * @access private + */ + function _setSystemName() + { + $OS_Guess = new OS_Guess; + $sysname = $OS_Guess->getSysname(); + + // Refine the sysname for different Linux bundles/vendors. (This + // should go away if OS_Guess was ever extended to give vendor + // and vendor-version guesses.) + // + // Bear in mind that $sysname is eventually used to craft a + // method name to figure out which backend gets used to parse + // the ping output. Elsewhere, we'll set $sysname back before + // that. + if ('linux' == $sysname) { + if ( file_exists('/etc/lsb-release') + && false !== ($release=@file_get_contents('/etc/lsb-release')) + && preg_match('/gutsy/i', $release) + ) { + $sysname = 'linuxredhat9'; + } + else if ( file_exists('/etc/debian_version') ) { + $sysname = 'linuxdebian'; + }else if (file_exists('/etc/redhat-release') + && false !== ($release= @file_get_contents('/etc/redhat-release')) + ) + { + if (preg_match('/release 8/i', $release)) { + $sysname = 'linuxredhat8'; + }elseif (preg_match('/release 9/i', $release)) { + $sysname = 'linuxredhat9'; + } + } + } + + return $sysname; + + } /* function _setSystemName */ + + /** + * Set the arguments array + * + * @param array $args Hash with options + * @return mixed true or PEAR_error + * @access public + */ + function setArgs($args) + { + if (!is_array($args)) { + return PEAR::raiseError(NET_PING_INVALID_ARGUMENTS_MSG, NET_PING_INVALID_ARGUMENTS); + } + + $this->_setNoArgs($args); + + $this->_args = $args; + + return true; + } /* function setArgs() */ + + /** + * Set the noArgs flag + * + * @param array $args Hash with options + * @return void + * @access private + */ + function _setNoArgs($args) + { + if (0 == count($args)) { + $this->_noArgs = true; + } else { + $this->_noArgs = false; + } + } /* function _setNoArgs() */ + + /** + * Sets the system's path to the ping binary + * + * @access private + */ + function _setPingPath($sysname) + { + $status = ''; + $output = array(); + $ping_path = ''; + + if ("windows" == $sysname) { + return "ping"; + } else { + $ping_path = exec("which ping", $output, $status); + if (0 != $status) { + return NET_PING_CANT_LOCATE_PING_BINARY; + } else { + // be certain "which" did what we expect. (ref bug #12791) + if ( is_executable($ping_path) ) { + return $ping_path; + } + else { + return NET_PING_CANT_LOCATE_PING_BINARY; + } + } + } + } /* function _setPingPath() */ + + /** + * Creates the argument list according to platform differences + * + * @return string Argument line + * @access private + */ + function _createArgList() + { + $retval = array(); + + $timeout = ""; + $iface = ""; + $ttl = ""; + $count = ""; + $quiet = ""; + $size = ""; + $seq = ""; + $deadline = ""; + + foreach($this->_args AS $option => $value) { + if(!empty($option) && isset($this->_argRelation[$this->_sysname][$option]) && NULL != $this->_argRelation[$this->_sysname][$option]) { + ${$option} = $this->_argRelation[$this->_sysname][$option]." ".$value." "; + } + } + + switch($this->_sysname) { + + case "sunos": + if ($size || $count || $iface) { + /* $size and $count must be _both_ defined */ + $seq = " -s "; + if ($size == "") { + $size = " 56 "; + } + if ($count == "") { + $count = " 5 "; + } + } + $retval['pre'] = $iface.$seq.$ttl; + $retval['post'] = $size.$count; + break; + + case "freebsd": + $retval['pre'] = $quiet.$count.$ttl.$timeout; + $retval['post'] = ""; + break; + + case "darwin": + $retval['pre'] = $count.$timeout.$size; + $retval['post'] = ""; + break; + + case "netbsd": + $retval['pre'] = $quiet.$count.$iface.$size.$ttl.$timeout; + $retval['post'] = ""; + break; + + case "openbsd": + $retval['pre'] = $quiet.$count.$iface.$size.$ttl.$timeout; + $retval['post'] = ""; + break; + + case "linux": + $retval['pre'] = $quiet.$deadline.$count.$ttl.$size.$timeout; + $retval['post'] = ""; + break; + + case "linuxdebian": + $retval['pre'] = $quiet.$count.$ttl.$size.$timeout; + $retval['post'] = ""; + $this->_sysname = 'linux'; // undo linux vendor refinement hack + break; + + case "linuxredhat8": + $retval['pre'] = $iface.$ttl.$count.$quiet.$size.$deadline; + $retval['post'] = ""; + $this->_sysname = 'linux'; // undo linux vendor refinement hack + break; + + case "linuxredhat9": + $retval['pre'] = $timeout.$iface.$ttl.$count.$quiet.$size.$deadline; + $retval['post'] = ""; + $this->_sysname = 'linux'; // undo linux vendor refinement hack + break; + + case "windows": + $retval['pre'] = $count.$ttl.$timeout; + $retval['post'] = ""; + break; + + case "hpux": + $retval['pre'] = $ttl; + $retval['post'] = $size.$count; + break; + + case "aix": + $retval['pre'] = $count.$timeout.$ttl.$size; + $retval['post'] = ""; + break; + + default: + $retval['pre'] = ""; + $retval['post'] = ""; + break; + } + return($retval); + } /* function _createArgList() */ + + /** + * Execute ping + * + * @param string $host hostname + * @return mixed String on error or array with the result + * @access public + */ + function ping($host) + { + + if($this->_noArgs) { + $this->setArgs(array('count' => 3)); + } + + $argList = $this->_createArgList(); + $cmd = $this->_ping_path." ".$argList['pre']." ".$host." ".$argList['post']; + + // since we return a new instance of Net_Ping_Result (on + // success), users may call the ping() method repeatedly to + // perform unrelated ping tests Make sure we don't have raw data + // from a previous call laying in the _result array. + $this->_result = array(); + + exec($cmd, $this->_result); + + if (!is_array($this->_result)) { + return PEAR::raiseError(NET_PING_FAILED_MSG, NET_PING_FAILED); + } + + if (count($this->_result) == 0) { + return PEAR::raiseError(NET_PING_HOST_NOT_FOUND_MSG, NET_PING_HOST_NOT_FOUND); + } + else { + // Here we pass $this->_sysname to the factory(), but it is + // not actually used by the class. It's only maintained in + // the Net_Ping_Result class because the + // Net_Ping_Result::getSysName() method needs to be retained + // for backwards compatibility. + return Net_Ping_Result::factory($this->_result, $this->_sysname); + } + } /* function ping() */ + + /** + * Check if a host is up by pinging it + * + * @param string $host The host to test + * @param bool $severely If some of the packages did reach the host + * and severely is false the function will return true + * @return bool True on success or false otherwise + * + */ + function checkHost($host, $severely = true) + { + $matches = array(); + + $this->setArgs(array("count" => 10, + "size" => 32, + "quiet" => null, + "deadline" => 10 + ) + ); + $res = $this->ping($host); + if (PEAR::isError($res)) { + return false; + } + if ($res->_received == 0) { + return false; + } + if ($res->_received != $res->_transmitted && $severely) { + return false; + } + return true; + } /* function checkHost() */ + + /** + * Output errors with PHP trigger_error(). You can silence the errors + * with prefixing a "@" sign to the function call: @Net_Ping::ping(..); + * + * @param mixed $error a PEAR error or a string with the error message + * @return bool false + * @access private + * @author Kai Schrder + */ + function _raiseError($error) + { + if (PEAR::isError($error)) { + $error = $error->getMessage(); + } + trigger_error($error, E_USER_WARNING); + return false; + } /* function _raiseError() */ + + /** + * Creates the argument list according to platform differences + * + * @return string Argument line + * @access private + */ + function _initArgRelation() + { + $this->_argRelation["sunos"] = array( + "timeout" => NULL, + "ttl" => "-t", + "count" => " ", + "quiet" => "-q", + "size" => " ", + "iface" => "-i" + ); + + $this->_argRelation["freebsd"] = array ( + "timeout" => "-t", + "ttl" => "-m", + "count" => "-c", + "quiet" => "-q", + "size" => NULL, + "iface" => NULL + ); + + $this->_argRelation["netbsd"] = array ( + "timeout" => "-w", + "iface" => "-I", + "ttl" => "-T", + "count" => "-c", + "quiet" => "-q", + "size" => "-s" + ); + + $this->_argRelation["openbsd"] = array ( + "timeout" => "-w", + "iface" => "-I", + "ttl" => "-t", + "count" => "-c", + "quiet" => "-q", + "size" => "-s" + ); + + $this->_argRelation["darwin"] = array ( + "timeout" => "-t", + "iface" => NULL, + "ttl" => NULL, + "count" => "-c", + "quiet" => "-q", + "size" => NULL + ); + + $this->_argRelation["linux"] = array ( + "timeout" => "-W", + "iface" => NULL, + "ttl" => "-t", + "count" => "-c", + "quiet" => "-q", + "size" => "-s", + "deadline" => "-w" + ); + + $this->_argRelation["linuxdebian"] = array ( + "timeout" => "-W", + "iface" => NULL, + "ttl" => "-t", + "count" => "-c", + "quiet" => "-q", + "size" => "-s", + "deadline" => "-w", + ); + + $this->_argRelation["linuxredhat8"] = array ( + "timeout" => NULL, + "iface" => "-I", + "ttl" => "-t", + "count" => "-c", + "quiet" => "-q", + "size" => "-s", + "deadline" => "-w" + ); + + $this->_argRelation["linuxredhat9"] = array ( + "timeout" => "-W", + "iface" => "-I", + "ttl" => "-t", + "count" => "-c", + "quiet" => "-q", + "size" => "-s", + "deadline" => "-w" + ); + + $this->_argRelation["windows"] = array ( + "timeout" => "-w", + "iface" => NULL, + "ttl" => "-i", + "count" => "-n", + "quiet" => NULL, + "size" => "-l" + ); + + $this->_argRelation["hpux"] = array ( + "timeout" => NULL, + "iface" => NULL, + "ttl" => "-t", + "count" => "-n", + "quiet" => NULL, + "size" => " " + ); + + $this->_argRelation["aix"] = array ( + "timeout" => "-i", + "iface" => NULL, + "ttl" => "-T", + "count" => "-c", + "quiet" => NULL, + "size" => "-s" + ); + } /* function _initArgRelation() */ +} /* class Net_Ping */ + +/** +* Container class for Net_Ping results +* +* @author Jan Lehnardt +* @version $Revision: 1.50 $ +* @package Net +* @access private +*/ +class Net_Ping_Result +{ + /** + * ICMP sequence number and associated time in ms + * + * @var array + * @access private + */ + var $_icmp_sequence = array(); /* array($sequence_number => $time ) */ + + /** + * The target's IP Address + * + * @var string + * @access private + */ + var $_target_ip; + + /** + * Number of bytes that are sent with each ICMP request + * + * @var int + * @access private + */ + var $_bytes_per_request; + + /** + * The total number of bytes that are sent with all ICMP requests + * + * @var int + * @access private + */ + var $_bytes_total; + + /** + * The ICMP request's TTL + * + * @var int + * @access private + */ + var $_ttl; + + /** + * The raw Net_Ping::result + * + * @var array + * @access private + */ + var $_raw_data = array(); + + /** + * The Net_Ping::_sysname + * + * @var int + * @access private + */ + var $_sysname; + + /** + * Statistical information about the ping + * + * @var int + * @access private + */ + var $_round_trip = array(); /* array('min' => xxx, 'avg' => yyy, 'max' => zzz) */ + + + /** + * Constructor for the Class + * + * @access private + */ + function Net_Ping_Result($result, $sysname) + { + $this->_raw_data = $result; + + // The _sysname property is no longer used by Net_Ping_result. + // The property remains for backwards compatibility so the + // getSystemName() method continues to work. + $this->_sysname = $sysname; + + $this->_parseResult(); + } /* function Net_Ping_Result() */ + + /** + * Factory for Net_Ping_Result + * + * @access public + * @param array $result Net_Ping result + * @param string $sysname OS_Guess::sysname + */ + function factory($result, $sysname) + { + return new Net_Ping_Result($result, $sysname); + } /* function factory() */ + + /** + * Parses the raw output from the ping utility. + * + * @access private + */ + function _parseResult() + { + // MAINTAINERS: + // + // If you're in this class fixing or extending the parser + // please add another file in the 'tests/test_parser_data/' + // directory which exemplafies the problem. And of course + // you'll want to run the 'tests/test_parser.php' (which + // contains easy how-to instructions) to make sure you haven't + // broken any existing behaviour. + + // operate on a copy of the raw output since we're going to modify it + $data = $this->_raw_data; + + // remove leading and trailing blank lines from output + $this->_parseResultTrimLines($data); + + // separate the output into upper and lower portions, + // and trim those portions + $this->_parseResultSeparateParts($data, $upper, $lower); + $this->_parseResultTrimLines($upper); + $this->_parseResultTrimLines($lower); + + // extract various things from the ping output . . . + + $this->_target_ip = $this->_parseResultDetailTargetIp($upper); + $this->_bytes_per_request = $this->_parseResultDetailBytesPerRequest($upper); + $this->_ttl = $this->_parseResultDetailTtl($upper); + $this->_icmp_sequence = $this->_parseResultDetailIcmpSequence($upper); + $this->_round_trip = $this->_parseResultDetailRoundTrip($lower); + + $this->_parseResultDetailTransmitted($lower); + $this->_parseResultDetailReceived($lower); + $this->_parseResultDetailLoss($lower); + + if ( isset($this->_transmitted) ) { + $this->_bytes_total = $this->_transmitted * $this->_bytes_per_request; + } + + } /* function _parseResult() */ + + /** + * determinces the number of bytes sent by ping per ICMP ECHO + * + * @access private + */ + function _parseResultDetailBytesPerRequest($upper) + { + // The ICMP ECHO REQUEST and REPLY packets should be the same + // size. So we can also find what we want in the output for any + // succesful ICMP reply which ping printed. + for ( $i=1; $i_loss = (int)$matches[1]; + return; + } + } + } + + /** + * Locates the "packets received" in the ping output + * + * @access private + */ + function _parseResultDetailReceived($lower) + { + for ( $i=1; $i_received = (int)$matches[1]; + return; + } + } + } + + /** + * determines the mininum, maximum, average and standard deviation + * of the round trip times. + * + * @access private + */ + function _parseResultDetailRoundTrip($lower) + { + // The first pattern will match a sequence of 3 or 4 + // alaphabet-char strings separated with slashes without + // presuming the order. eg, "min/max/avg" and + // "min/max/avg/mdev". Some ping flavors don't have the standard + // deviation value, and some have different names for it when + // present. + $p1 = '[a-z]+/[a-z]+/[a-z]+/?[a-z]*'; + + // And the pattern for 3 or 4 numbers (decimal values permitted) + // separated by slashes. + $p2 = '[0-9\.]+/[0-9\.]+/[0-9\.]+/?[0-9\.]*'; + + $results = array(); + $matches = array(); + for ( $i=(count($lower)-1); $i>=0; $i-- ) { + if ( preg_match('|('.$p1.')[^0-9]+('.$p2.')|i', $lower[$i], $matches) ) { + break; + } + } + + // matches? + if ( count($matches) > 0 ) { + // we want standardized keys in the array we return. Here we + // look for the values (min, max, etc) and setup the return + // hash + $fields = explode('/', $matches[1]); + $values = explode('/', $matches[2]); + for ( $i=0; $i=0; $i-- ) { + if ( preg_match('/min.*max/i', $lower[$i]) ) { + if ( preg_match('/'.$p3.$p3.$p3.'/i', $lower[$i], $matches) ) { + $results['min'] = $matches[1]; + $results['max'] = $matches[2]; + $results['avg'] = $matches[3]; + } + break; + } + } + + // either an array of min, max and avg from just above, or still + // the empty array from initialization way above + return( $results ); + } + + /** + * determinces the target IP address actually used by ping + * + * @access private + */ + function _parseResultDetailTargetIp($upper) + { + // Grab the first IP addr we can find. Most ping flavors + // put the target IP on the first line, but some only list it + // in successful ping packet lines. + for ( $i=0; $i_transmitted = (int)$matches[1]; + return; + } + } + } + + /** + * determinces the time to live (TTL) actually used by ping + * + * @access private + */ + function _parseResultDetailTtl($upper) + { + //extract TTL from first icmp echo line + for ( $i=1; $i 0 + ) { + return( (int)$matches[1] ); + } + } + + // No idea what ttl was used. Probably because no packets + // received in reply. + return( NULL ); + } + + /** + * Modifies the array to temoves leading and trailing blank lines + * + * @access private + */ + function _parseResultTrimLines(&$data) + { +if ( !is_array($data) ) { +print_r($this); +exit; +} + // Trim empty elements from the front + while ( preg_match('/^\s*$/', $data[0]) ) { + array_splice($data, 0, 1); + } + // Trim empty elements from the back + while ( preg_match('/^\s*$/', $data[(count($data)-1)]) ) { + array_splice($data, -1, 1); + } + } + + /** + * Separates the upper portion (data about individual ICMP ECHO + * packets) and the lower portion (statistics about the ping + * execution as a whole.) + * + * @access private + */ + function _parseResultSeparateParts($data, &$upper, &$lower) + { + $upper = array(); + $lower = array(); + + // find the blank line closest to the end + $dividerIndex = count($data) - 1; + while ( !preg_match('/^\s*$/', $data[$dividerIndex]) ) { + $dividerIndex--; + if ( $dividerIndex < 0 ) { + break; + } + } + + // This is horrible; All the other methods assume we're able to + // separate the upper (preamble and per-packet output) and lower + // (statistics and summary output) sections. + if ( $dividerIndex < 0 ) { + $upper = $data; + $lower = $data; + return; + } + + for ( $i=0; $i<$dividerIndex; $i++ ) { + $upper[] = $data[$i]; + } + for ( $i=(1+$dividerIndex); $i$name)?$this->$name:''; + } /* function getValue() */ + + /** + * Accessor for $this->_target_ip; + * + * @return string IP address + * @access public + * @see Ping_Result::_target_ip + */ + function getTargetIp() + { + return $this->_target_ip; + } /* function getTargetIp() */ + + /** + * Accessor for $this->_icmp_sequence; + * + * @return array ICMP sequence + * @access private + * @see Ping_Result::_icmp_sequence + */ + function getICMPSequence() + { + return $this->_icmp_sequence; + } /* function getICMPSequencs() */ + + /** + * Accessor for $this->_bytes_per_request; + * + * @return int bytes per request + * @access private + * @see Ping_Result::_bytes_per_request + */ + function getBytesPerRequest() + { + return $this->_bytes_per_request; + } /* function getBytesPerRequest() */ + + /** + * Accessor for $this->_bytes_total; + * + * @return int total bytes + * @access private + * @see Ping_Result::_bytes_total + */ + function getBytesTotal() + { + return $this->_bytes_total; + } /* function getBytesTotal() */ + + /** + * Accessor for $this->_ttl; + * + * @return int TTL + * @access private + * @see Ping_Result::_ttl + */ + function getTTL() + { + return $this->_ttl; + } /* function getTTL() */ + + /** + * Accessor for $this->_raw_data; + * + * @return array raw data + * @access private + * @see Ping_Result::_raw_data + */ + function getRawData() + { + return $this->_raw_data; + } /* function getRawData() */ + + /** + * Accessor for $this->_sysname; + * + * @return string OS_Guess::sysname + * @access private + * @see Ping_Result::_sysname + */ + function getSystemName() + { + return $this->_sysname; + } /* function getSystemName() */ + + /** + * Accessor for $this->_round_trip; + * + * @return array statistical information + * @access private + * @see Ping_Result::_round_trip + */ + function getRoundTrip() + { + return $this->_round_trip; + } /* function getRoundTrip() */ + + /** + * Accessor for $this->_round_trip['min']; + * + * @return array statistical information + * @access private + * @see Ping_Result::_round_trip + */ + function getMin() + { + return $this->_round_trip['min']; + } /* function getMin() */ + + /** + * Accessor for $this->_round_trip['max']; + * + * @return array statistical information + * @access private + * @see Ping_Result::_round_trip + */ + function getMax() + { + return $this->_round_trip['max']; + } /* function getMax() */ + + /** + * Accessor for $this->_round_trip['stddev']; + * + * @return array statistical information + * @access private + * @see Ping_Result::_round_trip + */ + function getStddev() + { + return $this->_round_trip['stddev']; + } /* function getStddev() */ + + /** + * Accessor for $this->_round_tripp['avg']; + * + * @return array statistical information + * @access private + * @see Ping_Result::_round_trip + */ + function getAvg() + { + return $this->_round_trip['avg']; + } /* function getAvg() */ + + /** + * Accessor for $this->_transmitted; + * + * @return array statistical information + * @access private + */ + function getTransmitted() + { + return $this->_transmitted; + } /* function getTransmitted() */ + + /** + * Accessor for $this->_received; + * + * @return array statistical information + * @access private + */ + function getReceived() + { + return $this->_received; + } /* function getReceived() */ + + /** + * Accessor for $this->_loss; + * + * @return array statistical information + * @access private + */ + function getLoss() + { + return $this->_loss; + } /* function getLoss() */ + +} /* class Net_Ping_Result */ +?> diff --git a/plugins/system/service_check/CHANGELOG b/plugins/system/service_check/CHANGELOG new file mode 100644 index 0000000..bf622bd --- /dev/null +++ b/plugins/system/service_check/CHANGELOG @@ -0,0 +1,20 @@ +1.2.4 (2009.08.06) +------------------ +Bug #125: TCP Service Check tests for custom port even if no value is specified + +1.2.3 (2008.11.20) +------------------ +Added the capability to check multiple ports. +It is possible to select the most commonly used service to check directly from a default list. + +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support diff --git a/plugins/system/service_check/LICENSE b/plugins/system/service_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/service_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/service_check/configure.php b/plugins/system/service_check/configure.php new file mode 100644 index 0000000..5649125 --- /dev/null +++ b/plugins/system/service_check/configure.php @@ -0,0 +1,63 @@ + + * @author Marcello Sessa + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once 'services.php'; + +$plugin_actions['service_check'][0]['description'] = PLUGIN_METADATA_CONFIGURATION; +$plugin_actions['service_check'][0]['action'] = 'plugin'; +$plugin_actions['service_check'][0]['file'] = 'display_archive_results'; +$plugin_actions['service_check'][0]['image'] = 'archive.png'; + +$plugin_field['service_check'][0]['version'] = '1.2.4'; +$plugin_field['service_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['service_check'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['service_check'][0]['authors'][1] = 'Marcello Sessa '; +$plugin_field['service_check'][0]['description'] = PLUGIN_SERVICE_CHECK_DESCRIPTION; +$plugin_field['service_check'][0]['title'] = PLUGIN_SERVICE_CHECK_TITLE; + +$plugin_field['service_check'][1]['type'] = 'select'; +$plugin_field['service_check'][1]['name'] = 'service_check_default_ports'; +$plugin_field['service_check'][1]['value'] = $services; +$plugin_field['service_check'][1]['attributes'] = 'multiple'; +$plugin_field['service_check'][1]['description'] = PLUGIN_SERVICE_CHECK_SERVICE_PORT_LIST_DESCRIPTION; + +$plugin_field['service_check'][2]['type'] = 'text'; +$plugin_field['service_check'][2]['name'] = 'service_check_custom_ports'; +$plugin_field['service_check'][2]['value'] = ''; +$plugin_field['service_check'][2]['attributes'] = 'disabled'; +$plugin_field['service_check'][2]['description'] = PLUGIN_SERVICE_CHECK_SERVICE_PORT_DESCRIPTION; + +$plugin_field['service_check'][3]['type'] = 'text'; +$plugin_field['service_check'][3]['name'] = 'service_check_timeout'; +$plugin_field['service_check'][3]['value'] = ''; +$plugin_field['service_check'][3]['attributes'] = 'disabled'; +$plugin_field['service_check'][3]['description'] = PLUGIN_SERVICE_TIMEOUT_DESCRIPTION; +$plugin_field['service_check'][3]['num_rules'] = '1'; +$plugin_field['service_check'][3]['rule_msg'][0] = PLUGIN_SERVICE_CHECK_RULE_3_0; +$plugin_field['service_check'][3]['rule_type'][0] = 'numeric'; +$plugin_field['service_check'][3]['rule_attribute'][0] = ''; + +$plugin_field['service_check'][4]['type'] = 'text'; +$plugin_field['service_check'][4]['name'] = 'service_check_retention'; +$plugin_field['service_check'][4]['value'] = ''; +$plugin_field['service_check'][4]['attributes'] = 'disabled'; +$plugin_field['service_check'][4]['description'] = PLUGIN_RETENTION; +?> diff --git a/plugins/system/service_check/core.php b/plugins/system/service_check/core.php new file mode 100644 index 0000000..3527939 --- /dev/null +++ b/plugins/system/service_check/core.php @@ -0,0 +1,113 @@ + + * @author Marcello Sessa + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; +require_once 'services.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + //Get the params required by plugin from argv + $default_ports = $parameters['service_check_default_ports']; + $custom_ports = explode(',', $parameters['service_check_custom_ports']); + + $timeout = $parameters['service_check_timeout']; + $ip = $job_infos['ip']; + $result = 1; + + if (!is_int($timeout)) { + $timeout = 20; + } + + $to_check_ports = array_merge($default_ports, $custom_ports); + + if (count($to_check_ports) == 0) { + $msg_exec = 'No port to check was specified. Nothing to check'; + $msg_exec_html = $msg_exec; + $result = 0; + } else { + foreach ($to_check_ports as $key => $value) { + //remove eventual space from custom port values. + $port = trim($value); + //create message prefix. + if (array_key_exists($port, $services)) { + $msg_prefix = $services[$port] . ' -> '; + } else { + //custom port + $msg_prefix = 'Custom:' . $port . ' -> '; + } + try { + if (isset($port) && $port != '') { + $fs = fsockopen($ip, intval($port), $errno, $errstr, $timeout); + $msg_exec .= $msg_prefix . 'Service Alive' . "\n"; + $msg_exec_html .= $msg_prefix . 'Service Alive
'; + } + } catch (Exception $e) { + $result = 0; + $msg_exec .= $msg_prefix . 'Service Unreachable' . "\n"; + $msg_exec_html .= $msg_prefix . 'Service Unreachable
'; + } + } + } + + $attachments['txt'] = $msg_exec; + $attachments['html'] = $msg_exec_html; + + $msg_exec = $msg_exec_html; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['service_check_retention']; + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec_html = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + + $msg_exec = $msg_exec_html; +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> diff --git a/plugins/system/service_check/services.php b/plugins/system/service_check/services.php new file mode 100644 index 0000000..fd9c91f --- /dev/null +++ b/plugins/system/service_check/services.php @@ -0,0 +1,37 @@ + + * @author Marcello Sessa + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$services = array(21 => 'ftp:21', + 22 => 'ssh:22', + 23 => 'telnet:23', + 25 => 'smtp:25', + 80 => 'www-http:80', + 110 => 'pop3:110', + 143 => 'imap:143', + 389 => 'ldap:389', + 443 => 'www-https:443', + 993 => 's-imap:993', + 995 => 's-pop:995', + 1521 => 'oracle:1521', + 3306 => 'mysql:3306' + ); +?> diff --git a/plugins/system/solaris_metadevice_check/CHANGELOG b/plugins/system/solaris_metadevice_check/CHANGELOG new file mode 100644 index 0000000..7371b40 --- /dev/null +++ b/plugins/system/solaris_metadevice_check/CHANGELOG @@ -0,0 +1,11 @@ +1.2.4 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.1 (2007.11.19) +------------------ +Use init.inc.php + +1.0.0 (2007.08.02) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/system/solaris_metadevice_check/LICENSE b/plugins/system/solaris_metadevice_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/solaris_metadevice_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/solaris_metadevice_check/configure.php b/plugins/system/solaris_metadevice_check/configure.php new file mode 100644 index 0000000..2730893 --- /dev/null +++ b/plugins/system/solaris_metadevice_check/configure.php @@ -0,0 +1,48 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['solaris_metadevice_check'][0]['version'] = '1.0.2'; +$plugin_field['solaris_metadevice_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['solaris_metadevice_check'][0]['authors'][0] = 'Fabrizio Cardarello '; +$plugin_field['solaris_metadevice_check'][0]['description'] = PLUGIN_SOLARIS_METADEVICE_CHECK_DESCRIPTION; +$plugin_field['solaris_metadevice_check'][0]['title'] = PLUGIN_SOLARIS_METADEVICE_CHECK_TITLE; + +$plugin_field['solaris_metadevice_check'][1]['type'] = 'text'; +$plugin_field['solaris_metadevice_check'][1]['name'] = 'solaris_metadevice_check_user'; +$plugin_field['solaris_metadevice_check'][1]['value'] = ''; +$plugin_field['solaris_metadevice_check'][1]['attributes'] = 'disabled'; +$plugin_field['solaris_metadevice_check'][1]['description'] = PLUGIN_USER; +$plugin_field['solaris_metadevice_check'][1]['num_rules'] = '1'; +$plugin_field['solaris_metadevice_check'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['solaris_metadevice_check'][1]['rule_type'][0] = 'required'; +$plugin_field['solaris_metadevice_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['solaris_metadevice_check'][2]['type'] = 'text'; +$plugin_field['solaris_metadevice_check'][2]['name'] = 'solaris_metadevice_check_port'; +$plugin_field['solaris_metadevice_check'][2]['value'] = ''; +$plugin_field['solaris_metadevice_check'][2]['attributes'] = 'disabled'; +$plugin_field['solaris_metadevice_check'][2]['description'] = PLUGIN_PORT; + +$plugin_field['solaris_metadevice_check'][3]['type'] = 'text'; +$plugin_field['solaris_metadevice_check'][3]['name'] = 'solaris_metadevice_check_metadevice'; +$plugin_field['solaris_metadevice_check'][3]['value'] = ''; +$plugin_field['solaris_metadevice_check'][3]['attributes'] = 'disabled'; +$plugin_field['solaris_metadevice_check'][3]['description'] = PLUGIN_SOLARIS_METADEVICE_CHECK_METADEVICE_DESCRIPTION; +?> \ No newline at end of file diff --git a/plugins/system/solaris_metadevice_check/core.php b/plugins/system/solaris_metadevice_check/core.php new file mode 100644 index 0000000..ba24ff3 --- /dev/null +++ b/plugins/system/solaris_metadevice_check/core.php @@ -0,0 +1,95 @@ + + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + $user = $parameters['solaris_metadevice_check_user']; + $port = $parameters['solaris_metadevice_check_port']; + $metadevice = $parameters['solaris_metadevice_check_metadevice']; + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/metadevice-check.ksh'; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $metadevice); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/solaris_metadevice_check/metadevice-check.ksh b/plugins/system/solaris_metadevice_check/metadevice-check.ksh new file mode 100644 index 0000000..a483919 --- /dev/null +++ b/plugins/system/solaris_metadevice_check/metadevice-check.ksh @@ -0,0 +1,10 @@ +#!/usr/bin/ksh +# Author: Fabrizio Cardarello +# email: hunternet@users.sourceforge.net +# Description: +# Script for checking the state of metadevice +# Argument: $1 metadevice +# if $1 is missing the default value is d0 (root mirror) + +METADEVICE=${1:-d0} +[ -z "$(metastat $1 | grep State | grep Okay)" ] && exit 1 || exit 0 \ No newline at end of file diff --git a/plugins/system/solaris_svc_check/CHANGELOG b/plugins/system/solaris_svc_check/CHANGELOG new file mode 100644 index 0000000..8fc6e5b --- /dev/null +++ b/plugins/system/solaris_svc_check/CHANGELOG @@ -0,0 +1,15 @@ +1.0.3 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.0.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/system/solaris_svc_check/LICENSE b/plugins/system/solaris_svc_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/solaris_svc_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/solaris_svc_check/configure.php b/plugins/system/solaris_svc_check/configure.php new file mode 100644 index 0000000..879e705 --- /dev/null +++ b/plugins/system/solaris_svc_check/configure.php @@ -0,0 +1,42 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['solaris_svc_check'][0]['version'] = '1.0.3'; +$plugin_field['solaris_svc_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['solaris_svc_check'][0]['authors'][0] = 'Fabrizio Cardarello '; +$plugin_field['solaris_svc_check'][0]['description'] = PLUGIN_SOLARIS_SVC_CHECK_DESCRIPTION; +$plugin_field['solaris_svc_check'][0]['title'] = PLUGIN_SOLARIS_SVC_CHECK_TITLE; + +$plugin_field['solaris_svc_check'][1]['type'] = 'text'; +$plugin_field['solaris_svc_check'][1]['name'] = 'solaris_svc_check_user'; +$plugin_field['solaris_svc_check'][1]['value'] = ''; +$plugin_field['solaris_svc_check'][1]['attributes'] = 'disabled'; +$plugin_field['solaris_svc_check'][1]['description'] = PLUGIN_USER; +$plugin_field['solaris_svc_check'][1]['num_rules'] = '1'; +$plugin_field['solaris_svc_check'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['solaris_svc_check'][1]['rule_type'][0] = 'required'; +$plugin_field['solaris_svc_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['solaris_svc_check'][2]['type'] = 'text'; +$plugin_field['solaris_svc_check'][2]['name'] = 'solaris_svc_check_port'; +$plugin_field['solaris_svc_check'][2]['value'] = ''; +$plugin_field['solaris_svc_check'][2]['attributes'] = 'disabled'; +$plugin_field['solaris_svc_check'][2]['description'] = PLUGIN_PORT; +?> \ No newline at end of file diff --git a/plugins/system/solaris_svc_check/core.php b/plugins/system/solaris_svc_check/core.php new file mode 100644 index 0000000..f231538 --- /dev/null +++ b/plugins/system/solaris_svc_check/core.php @@ -0,0 +1,93 @@ + + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + $user = $parameters['solaris_svc_check_user']; + $port = $parameters['solaris_svc_check_port']; + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/svc-check.ksh'; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/solaris_svc_check/svc-check.ksh b/plugins/system/solaris_svc_check/svc-check.ksh new file mode 100644 index 0000000..1613318 --- /dev/null +++ b/plugins/system/solaris_svc_check/svc-check.ksh @@ -0,0 +1,9 @@ +#!/usr/bin/ksh +# Author: Fabrizio Cardarello +# Description: this script check by SMF command if a service is online +# Argument: the first argument rappresent the service's FMRI +# example: svc-check.ksh svc:/network/nfs/server + +FMRI=${1:-not_set} +echo $FMRI +[ $( svcs $FMRI | tail -1 | awk '{print $1}' ) != 'online' ] && exit 1 || exit 0 diff --git a/plugins/system/solaris_zfs_scrub_check/CHANGELOG b/plugins/system/solaris_zfs_scrub_check/CHANGELOG new file mode 100644 index 0000000..8e35297 --- /dev/null +++ b/plugins/system/solaris_zfs_scrub_check/CHANGELOG @@ -0,0 +1,16 @@ +1.0.3 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro +Fixed a typo in italian translation + +1.0.0 (2007.07.24) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/system/solaris_zfs_scrub_check/LICENSE b/plugins/system/solaris_zfs_scrub_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/solaris_zfs_scrub_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/solaris_zfs_scrub_check/configure.php b/plugins/system/solaris_zfs_scrub_check/configure.php new file mode 100644 index 0000000..be91b56 --- /dev/null +++ b/plugins/system/solaris_zfs_scrub_check/configure.php @@ -0,0 +1,42 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['solaris_zfs_scrub_check'][0]['version'] = '1.0.3'; +$plugin_field['solaris_zfs_scrub_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['solaris_zfs_scrub_check'][0]['authors'][0] = 'Fabrizio Cardarello '; +$plugin_field['solaris_zfs_scrub_check'][0]['description'] = PLUGIN_SOLARIS_ZFS_SCRUB_CHECK_DESCRIPTION; +$plugin_field['solaris_zfs_scrub_check'][0]['title'] = PLUGIN_SOLARIS_ZFS_SCRUB_CHECK_TITLE; + +$plugin_field['solaris_zfs_scrub_check'][1]['type'] = 'text'; +$plugin_field['solaris_zfs_scrub_check'][1]['name'] = 'solaris_zfs_scrub_check_user'; +$plugin_field['solaris_zfs_scrub_check'][1]['value'] = ''; +$plugin_field['solaris_zfs_scrub_check'][1]['attributes'] = 'disabled'; +$plugin_field['solaris_zfs_scrub_check'][1]['description'] = PLUGIN_USER; +$plugin_field['solaris_zfs_scrub_check'][1]['num_rules'] = '1'; +$plugin_field['solaris_zfs_scrub_check'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['solaris_zfs_scrub_check'][1]['rule_type'][0] = 'required'; +$plugin_field['solaris_zfs_scrub_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['solaris_zfs_scrub_check'][2]['type'] = 'text'; +$plugin_field['solaris_zfs_scrub_check'][2]['name'] = 'solaris_zfs_scrub_check_port'; +$plugin_field['solaris_zfs_scrub_check'][2]['value'] = ''; +$plugin_field['solaris_zfs_scrub_check'][2]['attributes'] = 'disabled'; +$plugin_field['solaris_zfs_scrub_check'][2]['description'] = PLUGIN_PORT; +?> \ No newline at end of file diff --git a/plugins/system/solaris_zfs_scrub_check/core.php b/plugins/system/solaris_zfs_scrub_check/core.php new file mode 100644 index 0000000..d394535 --- /dev/null +++ b/plugins/system/solaris_zfs_scrub_check/core.php @@ -0,0 +1,93 @@ + + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + $user = $parameters['solaris_zfs_scrub_check_user']; + $port = $parameters['solaris_zfs_scrub_check_port']; + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/zfs-scrub-check.ksh'; + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/solaris_zfs_scrub_check/zfs-scrub-check.ksh b/plugins/system/solaris_zfs_scrub_check/zfs-scrub-check.ksh new file mode 100644 index 0000000..4168da0 --- /dev/null +++ b/plugins/system/solaris_zfs_scrub_check/zfs-scrub-check.ksh @@ -0,0 +1,7 @@ +#!/usr/bin/ksh +# Author: Fabrizio Cardarello +# email: +# Description: +# this script check if all the zpool need a scrubbing. + +[ `zpool status | grep scrub | grep -v none | wc -l` -ne 0 ] && exit 1 diff --git a/plugins/system/solaris_zpool_check/CHANGELOG b/plugins/system/solaris_zpool_check/CHANGELOG new file mode 100644 index 0000000..8fc6e5b --- /dev/null +++ b/plugins/system/solaris_zpool_check/CHANGELOG @@ -0,0 +1,15 @@ +1.0.3 (2009.08.06) +------------------ +Bug #123 Update plugin to work with latest ssh library + +1.0.2 (2007.11.19) +------------------ +Use init.inc.php + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.0.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/system/solaris_zpool_check/LICENSE b/plugins/system/solaris_zpool_check/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/system/solaris_zpool_check/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/system/solaris_zpool_check/configure.php b/plugins/system/solaris_zpool_check/configure.php new file mode 100644 index 0000000..1ab303f --- /dev/null +++ b/plugins/system/solaris_zpool_check/configure.php @@ -0,0 +1,62 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['solaris_zpool_check'][0]['version'] = '1.0.3'; +$plugin_field['solaris_zpool_check'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['solaris_zpool_check'][0]['authors'][0] = 'Fabrizio Cardarello '; +$plugin_field['solaris_zpool_check'][0]['description'] = PLUGIN_SOLARIS_ZPOOL_CHECK_DESCRIPTION; +$plugin_field['solaris_zpool_check'][0]['title'] = PLUGIN_SOLARIS_ZPOOL_CHECK_TITLE; + +$plugin_field['solaris_zpool_check'][1]['type'] = 'text'; +$plugin_field['solaris_zpool_check'][1]['name'] = 'solaris_zpool_check_user'; +$plugin_field['solaris_zpool_check'][1]['value'] = ''; +$plugin_field['solaris_zpool_check'][1]['attributes'] = 'disabled'; +$plugin_field['solaris_zpool_check'][1]['description'] = PLUGIN_USER; +$plugin_field['solaris_zpool_check'][1]['num_rules'] = '1'; +$plugin_field['solaris_zpool_check'][1]['rule_msg'][0] = PLUGIN_USER_RULE; +$plugin_field['solaris_zpool_check'][1]['rule_type'][0] = 'required'; +$plugin_field['solaris_zpool_check'][1]['rule_attribute'][0] = ''; + +$plugin_field['solaris_zpool_check'][2]['type'] = 'text'; +$plugin_field['solaris_zpool_check'][2]['name'] = 'solaris_zpool_check_port'; +$plugin_field['solaris_zpool_check'][2]['value'] = ''; +$plugin_field['solaris_zpool_check'][2]['attributes'] = 'disabled'; +$plugin_field['solaris_zpool_check'][2]['description'] = PLUGIN_PORT; + +$plugin_field['solaris_zpool_check'][3]['type'] = 'text'; +$plugin_field['solaris_zpool_check'][3]['name'] = 'solaris_zpool_check_zpool_name'; +$plugin_field['solaris_zpool_check'][3]['value'] = ''; +$plugin_field['solaris_zpool_check'][3]['attributes'] = 'disabled'; +$plugin_field['solaris_zpool_check'][3]['description'] = PLUGIN_SOLARIS_ZPOOL_CHECK_ZPOOL_NAME_DESCRIPTION; +$plugin_field['solaris_zpool_check'][3]['num_rules'] = '1'; +$plugin_field['solaris_zpool_check'][3]['rule_msg'][0] = PLUGIN_SOLARIS_ZPOOL_CHECK_RULE_3_0; +$plugin_field['solaris_zpool_check'][3]['rule_type'][0] = 'required'; +$plugin_field['solaris_zpool_check'][3]['rule_attribute'][0] = ''; + +$plugin_field['solaris_zpool_check'][4]['type'] = 'text'; +$plugin_field['solaris_zpool_check'][4]['name'] = 'solaris_zpool_check_threshold'; +$plugin_field['solaris_zpool_check'][4]['value'] = ''; +$plugin_field['solaris_zpool_check'][4]['attributes'] = 'disabled'; +$plugin_field['solaris_zpool_check'][4]['description'] = PLUGIN_SOLARIS_ZPOOL_CHECK_THRESHOLD_DESCRIPTION; +$plugin_field['solaris_zpool_check'][4]['num_rules'] = '1'; +$plugin_field['solaris_zpool_check'][4]['rule_msg'][0] = PLUGIN_SOLARIS_ZPOOL_CHECK_RULE_4_0; +$plugin_field['solaris_zpool_check'][4]['rule_type'][0] = 'required'; +$plugin_field['solaris_zpool_check'][4]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/system/solaris_zpool_check/core.php b/plugins/system/solaris_zpool_check/core.php new file mode 100644 index 0000000..73bd05f --- /dev/null +++ b/plugins/system/solaris_zpool_check/core.php @@ -0,0 +1,102 @@ + + * @author Luca Corbo + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +require_once realpath(dirname($argv[0])) . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + + //---- Start plugin code ----- + + include_once 'sshUtil.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + $result = 0; + + //Get the params required by plugin from argv + + $user = $parameters['solaris_zpool_check_user']; + $port = $parameters['solaris_zpool_check_port']; + + // zpool name + $zpool_name = $parameters['solaris_zpool_check_zpool_name']; + // threshold + $threshold = $parameters['solaris_zpool_check_threshold']; + + $script_parameters = array($zpool_name, $threshold); + + $ip = $job_infos['ip']; + + $ssh = new SSHUtil(); + $path = dirname($argv[0]); + $script = $path . '/zpool-check.ksh'; + $local_parameters = implode(' ', $script_parameters); + + $sshCommandResult = $ssh->sshConn($user, $ip, $port, $script, true, $local_parameters); + + $stdout = $sshCommandResult['stdout']; + $exit_code = $sshCommandResult['exit_code']; + + if ($exit_code == '0') { + $result = '1'; + } else { + $result = '0'; + } + + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + + $loggerPlugin->trace('DEBUG', 'id_job=' . $id_job . "\n" . + 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + + $msg_exec = $attachments['txt']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/system/solaris_zpool_check/zpool-check.ksh b/plugins/system/solaris_zpool_check/zpool-check.ksh new file mode 100644 index 0000000..8ee8c81 --- /dev/null +++ b/plugins/system/solaris_zpool_check/zpool-check.ksh @@ -0,0 +1,20 @@ +#!/usr/bin/ksh +# Author: Fabrizio Cardarello +# email: +# Description: +# This script check the capacity of the zpool, with an +# absolute value that you've chosen and passed as second argumet. +# Argument: +# $1 zpool name +# $2 threshold + +if [ -n $1 ] && [ -n $2 ] +then + ZPOOL=$1 + MAX=$2 + CAP=`zpool list | grep $ZPOOL | awk '{print $5}' | sed 's/%//'` + if [ $CAP -gt $MAX ] + then + exit 1 + fi +fi diff --git a/plugins/www/check_uri_response_code/CHANGELOG b/plugins/www/check_uri_response_code/CHANGELOG new file mode 100644 index 0000000..71f9fb8 --- /dev/null +++ b/plugins/www/check_uri_response_code/CHANGELOG @@ -0,0 +1,19 @@ +1.0.4 (2009.09.22) +------------------ +Changed. Updated Pear library. + +1.0.3 (2007.11.19) +------------------ +Use init.inc.php + +1.0.2 (2007.11.11) +------------------ +Fixed [1829077] www/https check plugin hangs + +1.0.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.0.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/www/check_uri_response_code/COPYRIGHT b/plugins/www/check_uri_response_code/COPYRIGHT new file mode 100644 index 0000000..e087645 --- /dev/null +++ b/plugins/www/check_uri_response_code/COPYRIGHT @@ -0,0 +1,30 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +Simpletest +========== +Copyright: http://simpletest.sourceforge.net/projects/simpletest/ +License: GPL + +TestGen4Web +=========== +Copyright: 2004-2006 SpikeSource, Inc. +License: Open Software License v2.1 (see: http://www.spikesource.com/license.html) \ No newline at end of file diff --git a/plugins/www/check_uri_response_code/LICENSE b/plugins/www/check_uri_response_code/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/www/check_uri_response_code/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/www/check_uri_response_code/configure.php b/plugins/www/check_uri_response_code/configure.php new file mode 100644 index 0000000..6cf3e0b --- /dev/null +++ b/plugins/www/check_uri_response_code/configure.php @@ -0,0 +1,47 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['check_uri_response_code'][0]['version'] = '1.0.4'; +$plugin_field['check_uri_response_code'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['check_uri_response_code'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['check_uri_response_code'][0]['description'] = PLUGIN_CHECK_URI_RESPONSE_CODE_DESCRIPTION; +$plugin_field['check_uri_response_code'][0]['title'] = PLUGIN_CHECK_URI_RESPONSE_CODE_TITLE; + +$plugin_field['check_uri_response_code'][1]['type'] = 'select'; +$plugin_field['check_uri_response_code'][1]['name'] = 'check_uri_response_code_protocol'; +$plugin_field['check_uri_response_code'][1]['value'] = array('http' => 'http', 'https' => 'https'); +$plugin_field['check_uri_response_code'][1]['attributes'] = ''; +$plugin_field['check_uri_response_code'][1]['description'] = PLUGIN_HTTP_PROTOCOL; +$plugin_field['check_uri_response_code'][1]['num_rules'] = '0'; + +$plugin_field['check_uri_response_code'][2]['type'] = 'text'; +$plugin_field['check_uri_response_code'][2]['name'] = 'check_uri_response_code_port'; +$plugin_field['check_uri_response_code'][2]['value'] = ''; +$plugin_field['check_uri_response_code'][2]['attributes'] = 'disabled'; +$plugin_field['check_uri_response_code'][2]['description'] = PLUGIN_HTTP_PORT; +$plugin_field['check_uri_response_code'][2]['num_rules'] = '0'; + +$plugin_field['check_uri_response_code'][3]['type'] = 'text'; +$plugin_field['check_uri_response_code'][3]['name'] = 'check_uri_response_code_url'; +$plugin_field['check_uri_response_code'][3]['value'] = ''; +$plugin_field['check_uri_response_code'][3]['attributes'] = 'disabled'; +$plugin_field['check_uri_response_code'][3]['description'] = PLUGIN_CHECK_URI_RESPONSE_CODE_URL_DESCRIPTION; +$plugin_field['check_uri_response_code'][3]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/www/check_uri_response_code/core.php b/plugins/www/check_uri_response_code/core.php new file mode 100644 index 0000000..085b8af --- /dev/null +++ b/plugins/www/check_uri_response_code/core.php @@ -0,0 +1,137 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +set_include_path(realpath(dirname($argv[0])) . "/lib/Pear/:" . + ini_get("include_path")); +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +try { + //---- Start plugin code ----- + + include_once 'HTTP/Request.php'; + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + //Get the params required by plugin from argv + $ip = $job_infos['ip']; + + $protocol = $parameters['check_uri_response_code_protocol']; + $port = $parameters['check_uri_response_code_port']; + $url = $parameters['check_uri_response_code_url']; + + //Generate the uri + $uri = $protocol . '://' . $ip . ':' . $port . '/' . $url; + + //Perform the request + $req =& new HTTP_Request(""); + $req->setURL($uri); + $req->sendRequest(); + + //Get the response code + $code = $req->getResponseCode(); + + //Status Code Definitions see RFC 2616 for details + $status_code_details = array( + '100'=>'Continue', + '101'=>'Switching Protocols', + '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', + '303'=>'See Other', + '304'=>'Not Modified', + '305'=>'Use Proxy', + '306'=>'(Unused)', + '307'=>'Temporary Redirect', + '400'=>'Bad Request', + '401'=>'Unauthorized', + '402'=>'Payment Required', + '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'); + + $attachments['txt'] = $code . ' -> ' . $status_code_details[$code]; + + if ($code == '200') { + $result = '1'; + $loggerPlugin->trace('INFO', 'result for id_job=' . + $id_job . ' -> ' . $attachments['txt']); + } else { + $result = '0'; + $loggerPlugin->trace('ERROR', 'result for id_job=' . + $id_job . ' -> ' . $attachments['txt']); + } + + $msg_exec = $attachments['txt']; + +} catch (Exception $e) { + $result = 0; + $msg_exec = $e->getMessage(); + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); +} +//---- End plugin code ----- + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/www/check_uri_response_code/lib/Pear/HTTP/Request.php b/plugins/www/check_uri_response_code/lib/Pear/HTTP/Request.php new file mode 100644 index 0000000..d167cf1 --- /dev/null +++ b/plugins/www/check_uri_response_code/lib/Pear/HTTP/Request.php @@ -0,0 +1,1484 @@ + + * @author Alexey Borzov + * @copyright 2002-2007 Richard Heyes + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Request.php,v 1.58 2007/10/26 13:45:56 avb Exp $ + * @link http://pear.php.net/package/HTTP_Request/ + */ + +/** + * PEAR and PEAR_Error classes (for error handling) + */ +require_once 'PEAR.php'; +/** + * Socket class + */ +require_once 'Net/Socket.php'; +/** + * URL handling class + */ +require_once 'Net/URL.php'; + +/**#@+ + * Constants for HTTP request methods + */ +define('HTTP_REQUEST_METHOD_GET', 'GET', true); +define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true); +define('HTTP_REQUEST_METHOD_POST', 'POST', true); +define('HTTP_REQUEST_METHOD_PUT', 'PUT', true); +define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true); +define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true); +define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true); +/**#@-*/ + +/**#@+ + * Constants for HTTP request error codes + */ +define('HTTP_REQUEST_ERROR_FILE', 1); +define('HTTP_REQUEST_ERROR_URL', 2); +define('HTTP_REQUEST_ERROR_PROXY', 4); +define('HTTP_REQUEST_ERROR_REDIRECTS', 8); +define('HTTP_REQUEST_ERROR_RESPONSE', 16); +define('HTTP_REQUEST_ERROR_GZIP_METHOD', 32); +define('HTTP_REQUEST_ERROR_GZIP_READ', 64); +define('HTTP_REQUEST_ERROR_GZIP_DATA', 128); +define('HTTP_REQUEST_ERROR_GZIP_CRC', 256); +/**#@-*/ + +/**#@+ + * Constants for HTTP protocol versions + */ +define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true); +define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true); +/**#@-*/ + +if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + /** + * Whether string functions are overloaded by their mbstring equivalents + */ + define('HTTP_REQUEST_MBSTRING', true); +} else { + /** + * @ignore + */ + define('HTTP_REQUEST_MBSTRING', false); +} + +/** + * Class for performing HTTP requests + * + * Simple example (fetches yahoo.com and displays it): + * + * $a = &new HTTP_Request('http://www.yahoo.com/'); + * $a->sendRequest(); + * echo $a->getResponseBody(); + * + * + * @category HTTP + * @package HTTP_Request + * @author Richard Heyes + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Request +{ + /**#@+ + * @access private + */ + /** + * Instance of Net_URL + * @var Net_URL + */ + var $_url; + + /** + * Type of request + * @var string + */ + var $_method; + + /** + * HTTP Version + * @var string + */ + var $_http; + + /** + * Request headers + * @var array + */ + var $_requestHeaders; + + /** + * Basic Auth Username + * @var string + */ + var $_user; + + /** + * Basic Auth Password + * @var string + */ + var $_pass; + + /** + * Socket object + * @var Net_Socket + */ + var $_sock; + + /** + * Proxy server + * @var string + */ + var $_proxy_host; + + /** + * Proxy port + * @var integer + */ + var $_proxy_port; + + /** + * Proxy username + * @var string + */ + var $_proxy_user; + + /** + * Proxy password + * @var string + */ + var $_proxy_pass; + + /** + * Post data + * @var array + */ + var $_postData; + + /** + * Request body + * @var string + */ + var $_body; + + /** + * A list of methods that MUST NOT have a request body, per RFC 2616 + * @var array + */ + var $_bodyDisallowed = array('TRACE'); + + /** + * Files to post + * @var array + */ + var $_postFiles = array(); + + /** + * Connection timeout. + * @var float + */ + var $_timeout; + + /** + * HTTP_Response object + * @var HTTP_Response + */ + var $_response; + + /** + * Whether to allow redirects + * @var boolean + */ + var $_allowRedirects; + + /** + * Maximum redirects allowed + * @var integer + */ + var $_maxRedirects; + + /** + * Current number of redirects + * @var integer + */ + var $_redirects; + + /** + * Whether to append brackets [] to array variables + * @var bool + */ + var $_useBrackets = true; + + /** + * Attached listeners + * @var array + */ + var $_listeners = array(); + + /** + * Whether to save response body in response object property + * @var bool + */ + var $_saveBody = true; + + /** + * Timeout for reading from socket (array(seconds, microseconds)) + * @var array + */ + var $_readTimeout = null; + + /** + * Options to pass to Net_Socket::connect. See stream_context_create + * @var array + */ + var $_socketOptions = null; + /**#@-*/ + + /** + * Constructor + * + * Sets up the object + * @param string The url to fetch/access + * @param array Associative array of parameters which can have the following keys: + *
    + *
  • method - Method to use, GET, POST etc (string)
  • + *
  • http - HTTP Version to use, 1.0 or 1.1 (string)
  • + *
  • user - Basic Auth username (string)
  • + *
  • pass - Basic Auth password (string)
  • + *
  • proxy_host - Proxy server host (string)
  • + *
  • proxy_port - Proxy server port (integer)
  • + *
  • proxy_user - Proxy auth username (string)
  • + *
  • proxy_pass - Proxy auth password (string)
  • + *
  • timeout - Connection timeout in seconds (float)
  • + *
  • allowRedirects - Whether to follow redirects or not (bool)
  • + *
  • maxRedirects - Max number of redirects to follow (integer)
  • + *
  • useBrackets - Whether to append [] to array variable names (bool)
  • + *
  • saveBody - Whether to save response body in response object property (bool)
  • + *
  • readTimeout - Timeout for reading / writing data over the socket (array (seconds, microseconds))
  • + *
  • socketOptions - Options to pass to Net_Socket object (array)
  • + *
+ * @access public + */ + function HTTP_Request($url = '', $params = array()) + { + $this->_method = HTTP_REQUEST_METHOD_GET; + $this->_http = HTTP_REQUEST_HTTP_VER_1_1; + $this->_requestHeaders = array(); + $this->_postData = array(); + $this->_body = null; + + $this->_user = null; + $this->_pass = null; + + $this->_proxy_host = null; + $this->_proxy_port = null; + $this->_proxy_user = null; + $this->_proxy_pass = null; + + $this->_allowRedirects = false; + $this->_maxRedirects = 3; + $this->_redirects = 0; + + $this->_timeout = null; + $this->_response = null; + + foreach ($params as $key => $value) { + $this->{'_' . $key} = $value; + } + + if (!empty($url)) { + $this->setURL($url); + } + + // Default useragent + $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )'); + + // We don't do keep-alives by default + $this->addHeader('Connection', 'close'); + + // Basic authentication + if (!empty($this->_user)) { + $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass)); + } + + // Proxy authentication (see bug #5913) + if (!empty($this->_proxy_user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass)); + } + + // Use gzip encoding if possible + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) { + $this->addHeader('Accept-Encoding', 'gzip'); + } + } + + /** + * Generates a Host header for HTTP/1.1 requests + * + * @access private + * @return string + */ + function _generateHostHeader() + { + if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) { + $host = $this->_url->host . ':' . $this->_url->port; + + } else { + $host = $this->_url->host; + } + + return $host; + } + + /** + * Resets the object to its initial state (DEPRECATED). + * Takes the same parameters as the constructor. + * + * @param string $url The url to be requested + * @param array $params Associative array of parameters + * (see constructor for details) + * @access public + * @deprecated deprecated since 1.2, call the constructor if this is necessary + */ + function reset($url, $params = array()) + { + $this->HTTP_Request($url, $params); + } + + /** + * Sets the URL to be requested + * + * @param string The url to be requested + * @access public + */ + function setURL($url) + { + $this->_url = &new Net_URL($url, $this->_useBrackets); + + if (!empty($this->_url->user) || !empty($this->_url->pass)) { + $this->setBasicAuth($this->_url->user, $this->_url->pass); + } + + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) { + $this->addHeader('Host', $this->_generateHostHeader()); + } + + // set '/' instead of empty path rather than check later (see bug #8662) + if (empty($this->_url->path)) { + $this->_url->path = '/'; + } + } + + /** + * Returns the current request URL + * + * @return string Current request URL + * @access public + */ + function getUrl() + { + return empty($this->_url)? '': $this->_url->getUrl(); + } + + /** + * Sets a proxy to be used + * + * @param string Proxy host + * @param int Proxy port + * @param string Proxy username + * @param string Proxy password + * @access public + */ + function setProxy($host, $port = 8080, $user = null, $pass = null) + { + $this->_proxy_host = $host; + $this->_proxy_port = $port; + $this->_proxy_user = $user; + $this->_proxy_pass = $pass; + + if (!empty($user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + } + + /** + * Sets basic authentication parameters + * + * @param string Username + * @param string Password + */ + function setBasicAuth($user, $pass) + { + $this->_user = $user; + $this->_pass = $pass; + + $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + + /** + * Sets the method to be used, GET, POST etc. + * + * @param string Method to use. Use the defined constants for this + * @access public + */ + function setMethod($method) + { + $this->_method = $method; + } + + /** + * Sets the HTTP version to use, 1.0 or 1.1 + * + * @param string Version to use. Use the defined constants for this + * @access public + */ + function setHttpVer($http) + { + $this->_http = $http; + } + + /** + * Adds a request header + * + * @param string Header name + * @param string Header value + * @access public + */ + function addHeader($name, $value) + { + $this->_requestHeaders[strtolower($name)] = $value; + } + + /** + * Removes a request header + * + * @param string Header name to remove + * @access public + */ + function removeHeader($name) + { + if (isset($this->_requestHeaders[strtolower($name)])) { + unset($this->_requestHeaders[strtolower($name)]); + } + } + + /** + * Adds a querystring parameter + * + * @param string Querystring parameter name + * @param string Querystring parameter value + * @param bool Whether the value is already urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + $this->_url->addQueryString($name, $value, $preencoded); + } + + /** + * Sets the querystring to literally what you supply + * + * @param string The querystring data. Should be of the format foo=bar&x=y etc + * @param bool Whether data is already urlencoded or not, default = already encoded + * @access public + */ + function addRawQueryString($querystring, $preencoded = true) + { + $this->_url->addRawQueryString($querystring, $preencoded); + } + + /** + * Adds postdata items + * + * @param string Post data name + * @param string Post data value + * @param bool Whether data is already urlencoded or not, default = not + * @access public + */ + function addPostData($name, $value, $preencoded = false) + { + if ($preencoded) { + $this->_postData[$name] = $value; + } else { + $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value); + } + } + + /** + * Recursively applies the callback function to the value + * + * @param mixed Callback function + * @param mixed Value to process + * @access private + * @return mixed Processed value + */ + function _arrayMapRecursive($callback, $value) + { + if (!is_array($value)) { + return call_user_func($callback, $value); + } else { + $map = array(); + foreach ($value as $k => $v) { + $map[$k] = $this->_arrayMapRecursive($callback, $v); + } + return $map; + } + } + + /** + * Adds a file to upload + * + * This also changes content-type to 'multipart/form-data' for proper upload + * + * @access public + * @param string name of file-upload field + * @param mixed file name(s) + * @param mixed content-type(s) of file(s) being uploaded + * @return bool true on success + * @throws PEAR_Error + */ + function addFile($inputName, $fileName, $contentType = 'application/octet-stream') + { + if (!is_array($fileName) && !is_readable($fileName)) { + return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE); + } elseif (is_array($fileName)) { + foreach ($fileName as $name) { + if (!is_readable($name)) { + return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE); + } + } + } + $this->addHeader('Content-Type', 'multipart/form-data'); + $this->_postFiles[$inputName] = array( + 'name' => $fileName, + 'type' => $contentType + ); + return true; + } + + /** + * Adds raw postdata (DEPRECATED) + * + * @param string The data + * @param bool Whether data is preencoded or not, default = already encoded + * @access public + * @deprecated deprecated since 1.3.0, method setBody() should be used instead + */ + function addRawPostData($postdata, $preencoded = true) + { + $this->_body = $preencoded ? $postdata : urlencode($postdata); + } + + /** + * Sets the request body (for POST, PUT and similar requests) + * + * @param string Request body + * @access public + */ + function setBody($body) + { + $this->_body = $body; + } + + /** + * Clears any postdata that has been added (DEPRECATED). + * + * Useful for multiple request scenarios. + * + * @access public + * @deprecated deprecated since 1.2 + */ + function clearPostData() + { + $this->_postData = null; + } + + /** + * Appends a cookie to "Cookie:" header + * + * @param string $name cookie name + * @param string $value cookie value + * @access public + */ + function addCookie($name, $value) + { + $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : ''; + $this->addHeader('Cookie', $cookies . $name . '=' . $value); + } + + /** + * Clears any cookies that have been added (DEPRECATED). + * + * Useful for multiple request scenarios + * + * @access public + * @deprecated deprecated since 1.2 + */ + function clearCookies() + { + $this->removeHeader('Cookie'); + } + + /** + * Sends the request + * + * @access public + * @param bool Whether to store response body in Response object property, + * set this to false if downloading a LARGE file and using a Listener + * @return mixed PEAR error on error, true otherwise + */ + function sendRequest($saveBody = true) + { + if (!is_a($this->_url, 'Net_URL')) { + return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL); + } + + $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host; + $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port; + + // 4.3.0 supports SSL connections using OpenSSL. The function test determines + // we running on at least 4.3.0 + if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) { + if (isset($this->_proxy_host)) { + return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY); + } + $host = 'ssl://' . $host; + } + + // magic quotes may fuck up file uploads and chunked response processing + $magicQuotes = ini_get('magic_quotes_runtime'); + ini_set('magic_quotes_runtime', false); + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) && + 'Keep-Alive' == $this->_requestHeaders['connection']) + { + $this->removeHeader('connection'); + } + + $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) || + (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']); + $sockets = &PEAR::getStaticProperty('HTTP_Request', 'sockets'); + $sockKey = $host . ':' . $port; + unset($this->_sock); + + // There is a connected socket in the "static" property? + if ($keepAlive && !empty($sockets[$sockKey]) && + !empty($sockets[$sockKey]->fp)) + { + $this->_sock =& $sockets[$sockKey]; + $err = null; + } else { + $this->_notify('connect'); + $this->_sock =& new Net_Socket(); + $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions); + } + PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest()); + + if (!PEAR::isError($err)) { + if (!empty($this->_readTimeout)) { + $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]); + } + + $this->_notify('sentRequest'); + + // Read the response + $this->_response = &new HTTP_Response($this->_sock, $this->_listeners); + $err = $this->_response->process( + $this->_saveBody && $saveBody, + HTTP_REQUEST_METHOD_HEAD != $this->_method + ); + + if ($keepAlive) { + $keepAlive = (isset($this->_response->_headers['content-length']) + || (isset($this->_response->_headers['transfer-encoding']) + && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked')); + if ($keepAlive) { + if (isset($this->_response->_headers['connection'])) { + $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive'; + } else { + $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol; + } + } + } + } + + ini_set('magic_quotes_runtime', $magicQuotes); + + if (PEAR::isError($err)) { + return $err; + } + + if (!$keepAlive) { + $this->disconnect(); + // Store the connected socket in "static" property + } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) { + $sockets[$sockKey] =& $this->_sock; + } + + // Check for redirection + if ( $this->_allowRedirects + AND $this->_redirects <= $this->_maxRedirects + AND $this->getResponseCode() > 300 + AND $this->getResponseCode() < 399 + AND !empty($this->_response->_headers['location'])) { + + + $redirect = $this->_response->_headers['location']; + + // Absolute URL + if (preg_match('/^https?:\/\//i', $redirect)) { + $this->_url = &new Net_URL($redirect); + $this->addHeader('Host', $this->_generateHostHeader()); + // Absolute path + } elseif ($redirect{0} == '/') { + $this->_url->path = $redirect; + + // Relative path + } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $redirect = Net_URL::resolvePath($redirect); + $this->_url->path = $redirect; + + // Filename, no path + } else { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $this->_url->path = $redirect; + } + + $this->_redirects++; + return $this->sendRequest($saveBody); + + // Too many redirects + } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) { + return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS); + } + + return true; + } + + /** + * Disconnect the socket, if connected. Only useful if using Keep-Alive. + * + * @access public + */ + function disconnect() + { + if (!empty($this->_sock) && !empty($this->_sock->fp)) { + $this->_notify('disconnect'); + $this->_sock->disconnect(); + } + } + + /** + * Returns the response code + * + * @access public + * @return mixed Response code, false if not set + */ + function getResponseCode() + { + return isset($this->_response->_code) ? $this->_response->_code : false; + } + + /** + * Returns either the named header or all if no name given + * + * @access public + * @param string The header name to return, do not set to get all headers + * @return mixed either the value of $headername (false if header is not present) + * or an array of all headers + */ + function getResponseHeader($headername = null) + { + if (!isset($headername)) { + return isset($this->_response->_headers)? $this->_response->_headers: array(); + } else { + $headername = strtolower($headername); + return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false; + } + } + + /** + * Returns the body of the response + * + * @access public + * @return mixed response body, false if not set + */ + function getResponseBody() + { + return isset($this->_response->_body) ? $this->_response->_body : false; + } + + /** + * Returns cookies set in response + * + * @access public + * @return mixed array of response cookies, false if none are present + */ + function getResponseCookies() + { + return isset($this->_response->_cookies) ? $this->_response->_cookies : false; + } + + /** + * Builds the request string + * + * @access private + * @return string The request string + */ + function _buildRequest() + { + $separator = ini_get('arg_separator.output'); + ini_set('arg_separator.output', '&'); + $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : ''; + ini_set('arg_separator.output', $separator); + + $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : ''; + $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : ''; + $path = $this->_url->path . $querystring; + $url = $host . $port . $path; + + if (!strlen($url)) { + $url = '/'; + } + + $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n"; + + if (in_array($this->_method, $this->_bodyDisallowed) || + (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method || + (empty($this->_postData) && empty($this->_postFiles))))) + { + $this->removeHeader('Content-Type'); + } else { + if (empty($this->_requestHeaders['content-type'])) { + // Add default content-type + $this->addHeader('Content-Type', 'application/x-www-form-urlencoded'); + } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) { + $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime()); + $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary); + } + } + + // Request Headers + if (!empty($this->_requestHeaders)) { + foreach ($this->_requestHeaders as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $request .= $canonicalName . ': ' . $value . "\r\n"; + } + } + + // No post data or wrong method, so simply add a final CRLF + if (in_array($this->_method, $this->_bodyDisallowed) || + (HTTP_REQUEST_METHOD_POST != $this->_method && 0 == strlen($this->_body))) { + + $request .= "\r\n"; + + // Post data if it's an array + } elseif (HTTP_REQUEST_METHOD_POST == $this->_method && + (!empty($this->_postData) || !empty($this->_postFiles))) { + + // "normal" POST request + if (!isset($boundary)) { + $postdata = implode('&', array_map( + create_function('$a', 'return $a[0] . \'=\' . $a[1];'), + $this->_flattenArray('', $this->_postData) + )); + + // multipart request, probably with file uploads + } else { + $postdata = ''; + if (!empty($this->_postData)) { + $flatData = $this->_flattenArray('', $this->_postData); + foreach ($flatData as $item) { + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"'; + $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n"; + } + } + foreach ($this->_postFiles as $name => $value) { + if (is_array($value['name'])) { + $varname = $name . ($this->_useBrackets? '[]': ''); + } else { + $varname = $name; + $value['name'] = array($value['name']); + } + foreach ($value['name'] as $key => $filename) { + $fp = fopen($filename, 'r'); + $data = fread($fp, filesize($filename)); + fclose($fp); + $basename = basename($filename); + $type = is_array($value['type'])? @$value['type'][$key]: $value['type']; + + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"'; + $postdata .= "\r\nContent-Type: " . $type; + $postdata .= "\r\n\r\n" . $data . "\r\n"; + } + } + $postdata .= '--' . $boundary . "--\r\n"; + } + $request .= 'Content-Length: ' . + (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) . + "\r\n\r\n"; + $request .= $postdata; + + // Explicitly set request body + } elseif (0 < strlen($this->_body)) { + + $request .= 'Content-Length: ' . + (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) . + "\r\n\r\n"; + $request .= $this->_body; + + // Terminate headers with CRLF on POST request with no body, too + } else { + + $request .= "\r\n"; + } + + return $request; + } + + /** + * Helper function to change the (probably multidimensional) associative array + * into the simple one. + * + * @param string name for item + * @param mixed item's values + * @return array array with the following items: array('item name', 'item value'); + * @access private + */ + function _flattenArray($name, $values) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($this->_useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, $this->_flattenArray($newName, $v)); + } + return $ret; + } + } + + + /** + * Adds a Listener to the list of listeners that are notified of + * the object's events + * + * Events sent by HTTP_Request object + * - 'connect': on connection to server + * - 'sentRequest': after the request was sent + * - 'disconnect': on disconnection from server + * + * Events sent by HTTP_Response object + * - 'gotHeaders': after receiving response headers (headers are passed in $data) + * - 'tick': on receiving a part of response body (the part is passed in $data) + * - 'gzTick': on receiving a gzip-encoded part of response body (ditto) + * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped) + * + * @param HTTP_Request_Listener listener to attach + * @return boolean whether the listener was successfully attached + * @access public + */ + function attach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener')) { + return false; + } + $this->_listeners[$listener->getId()] =& $listener; + return true; + } + + + /** + * Removes a Listener from the list of listeners + * + * @param HTTP_Request_Listener listener to detach + * @return boolean whether the listener was successfully detached + * @access public + */ + function detach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener') || + !isset($this->_listeners[$listener->getId()])) { + return false; + } + unset($this->_listeners[$listener->getId()]); + return true; + } + + + /** + * Notifies all registered listeners of an event. + * + * @param string Event name + * @param mixed Additional data + * @access private + * @see HTTP_Request::attach() + */ + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } +} + + +/** + * Response class to complement the Request class + * + * @category HTTP + * @package HTTP_Request + * @author Richard Heyes + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Response +{ + /** + * Socket object + * @var Net_Socket + */ + var $_sock; + + /** + * Protocol + * @var string + */ + var $_protocol; + + /** + * Return code + * @var string + */ + var $_code; + + /** + * Response headers + * @var array + */ + var $_headers; + + /** + * Cookies set in response + * @var array + */ + var $_cookies; + + /** + * Response body + * @var string + */ + var $_body = ''; + + /** + * Used by _readChunked(): remaining length of the current chunk + * @var string + */ + var $_chunkLength = 0; + + /** + * Attached listeners + * @var array + */ + var $_listeners = array(); + + /** + * Bytes left to read from message-body + * @var null|int + */ + var $_toRead; + + /** + * Constructor + * + * @param Net_Socket socket to read the response from + * @param array listeners attached to request + */ + function HTTP_Response(&$sock, &$listeners) + { + $this->_sock =& $sock; + $this->_listeners =& $listeners; + } + + + /** + * Processes a HTTP response + * + * This extracts response code, headers, cookies and decodes body if it + * was encoded in some way + * + * @access public + * @param bool Whether to store response body in object property, set + * this to false if downloading a LARGE file and using a Listener. + * This is assumed to be true if body is gzip-encoded. + * @param bool Whether the response can actually have a message-body. + * Will be set to false for HEAD requests. + * @throws PEAR_Error + * @return mixed true on success, PEAR_Error in case of malformed response + */ + function process($saveBody = true, $canHaveBody = true) + { + do { + $line = $this->_sock->readLine(); + if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) { + return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE); + } else { + $this->_protocol = 'HTTP/' . $http_version; + $this->_code = intval($returncode); + } + while ('' !== ($header = $this->_sock->readLine())) { + $this->_processHeader($header); + } + } while (100 == $this->_code); + + $this->_notify('gotHeaders', $this->_headers); + + // RFC 2616, section 4.4: + // 1. Any response message which "MUST NOT" include a message-body ... + // is always terminated by the first empty line after the header fields + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $canHaveBody = $canHaveBody && $this->_code >= 200 && + $this->_code != 204 && $this->_code != 304; + + // If response body is present, read it and decode + $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']); + $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']); + $hasBody = false; + if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) || + 0 != $this->_headers['content-length'])) + { + if ($chunked || !isset($this->_headers['content-length'])) { + $this->_toRead = null; + } else { + $this->_toRead = $this->_headers['content-length']; + } + while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) { + if ($chunked) { + $data = $this->_readChunked(); + } elseif (is_null($this->_toRead)) { + $data = $this->_sock->read(4096); + } else { + $data = $this->_sock->read(min(4096, $this->_toRead)); + $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data); + } + if ('' == $data) { + break; + } else { + $hasBody = true; + if ($saveBody || $gzipped) { + $this->_body .= $data; + } + $this->_notify($gzipped? 'gzTick': 'tick', $data); + } + } + } + + if ($hasBody) { + // Uncompress the body if needed + if ($gzipped) { + $body = $this->_decodeGzip($this->_body); + if (PEAR::isError($body)) { + return $body; + } + $this->_body = $body; + $this->_notify('gotBody', $this->_body); + } else { + $this->_notify('gotBody'); + } + } + return true; + } + + + /** + * Processes the response header + * + * @access private + * @param string HTTP header + */ + function _processHeader($header) + { + if (false === strpos($header, ':')) { + return; + } + list($headername, $headervalue) = explode(':', $header, 2); + $headername = strtolower($headername); + $headervalue = ltrim($headervalue); + + if ('set-cookie' != $headername) { + if (isset($this->_headers[$headername])) { + $this->_headers[$headername] .= ',' . $headervalue; + } else { + $this->_headers[$headername] = $headervalue; + } + } else { + $this->_parseCookie($headervalue); + } + } + + + /** + * Parse a Set-Cookie header to fill $_cookies array + * + * @access private + * @param string value of Set-Cookie header + */ + function _parseCookie($headervalue) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + // Only a name=value pair + if (!strpos($headervalue, ';')) { + $pos = strpos($headervalue, '='); + $cookie['name'] = trim(substr($headervalue, 0, $pos)); + $cookie['value'] = trim(substr($headervalue, $pos + 1)); + + // Some optional parameters are supplied + } else { + $elements = explode(';', $headervalue); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->_cookies[] = $cookie; + } + + + /** + * Read a part of response body encoded with chunked Transfer-Encoding + * + * @access private + * @return string + */ + function _readChunked() + { + // at start of the next chunk? + if (0 == $this->_chunkLength) { + $line = $this->_sock->readLine(); + if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + $this->_chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); // make this an eof() + return ''; + } + } else { + return ''; + } + } + $data = $this->_sock->read($this->_chunkLength); + $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data); + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); // Trailing CRLF + } + return $data; + } + + + /** + * Notifies all registered listeners of an event. + * + * @param string Event name + * @param mixed Additional data + * @access private + * @see HTTP_Request::_notify() + */ + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } + + + /** + * Decodes the message-body encoded by gzip + * + * The real decoding work is done by gzinflate() built-in function, this + * method only parses the header and checks data for compliance with + * RFC 1952 + * + * @access private + * @param string gzip-encoded data + * @return string decoded data + */ + function _decodeGzip($data) + { + if (HTTP_REQUEST_MBSTRING) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD); + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA); + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 1) { + if ($length - $headerLength - 2 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC); + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + $unpacked = @gzinflate(substr($data, $headerLength, -8), $dataSize); + if (false === $unpacked) { + return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ); + } elseif ($dataSize != strlen($unpacked)) { + return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ); + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { + return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC); + } + if (HTTP_REQUEST_MBSTRING) { + mb_internal_encoding($oldEncoding); + } + return $unpacked; + } +} // End class HTTP_Response +?> diff --git a/plugins/www/check_uri_response_code/lib/Pear/HTTP/Request/Listener.php b/plugins/www/check_uri_response_code/lib/Pear/HTTP/Request/Listener.php new file mode 100644 index 0000000..cc71b59 --- /dev/null +++ b/plugins/www/check_uri_response_code/lib/Pear/HTTP/Request/Listener.php @@ -0,0 +1,106 @@ + + * @copyright 2002-2007 Richard Heyes + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Listener.php,v 1.3 2007/05/18 10:33:31 avb Exp $ + * @link http://pear.php.net/package/HTTP_Request/ + */ + +/** + * Listener for HTTP_Request and HTTP_Response objects + * + * This class implements the Observer part of a Subject-Observer + * design pattern. + * + * @category HTTP + * @package HTTP_Request + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Request_Listener +{ + /** + * A listener's identifier + * @var string + */ + var $_id; + + /** + * Constructor, sets the object's identifier + * + * @access public + */ + function HTTP_Request_Listener() + { + $this->_id = md5(uniqid('http_request_', 1)); + } + + + /** + * Returns the listener's identifier + * + * @access public + * @return string + */ + function getId() + { + return $this->_id; + } + + + /** + * This method is called when Listener is notified of an event + * + * @access public + * @param object an object the listener is attached to + * @param string Event name + * @param mixed Additional data + * @abstract + */ + function update(&$subject, $event, $data = null) + { + echo "Notified of event: '$event'\n"; + if (null !== $data) { + echo "Additional data: "; + var_dump($data); + } + } +} +?> diff --git a/plugins/www/check_uri_response_code/lib/Pear/Net/Socket.php b/plugins/www/check_uri_response_code/lib/Pear/Net/Socket.php new file mode 100644 index 0000000..73bb4dd --- /dev/null +++ b/plugins/www/check_uri_response_code/lib/Pear/Net/Socket.php @@ -0,0 +1,592 @@ + | +// | Chuck Hagenbuch | +// +----------------------------------------------------------------------+ +// +// $Id: Socket.php,v 1.38 2008/02/15 18:24:17 chagenbu Exp $ + +require_once 'PEAR.php'; + +define('NET_SOCKET_READ', 1); +define('NET_SOCKET_WRITE', 2); +define('NET_SOCKET_ERROR', 4); + +/** + * Generalized Socket class. + * + * @version 1.1 + * @author Stig Bakken + * @author Chuck Hagenbuch + */ +class Net_Socket extends PEAR { + + /** + * Socket file pointer. + * @var resource $fp + */ + var $fp = null; + + /** + * Whether the socket is blocking. Defaults to true. + * @var boolean $blocking + */ + var $blocking = true; + + /** + * Whether the socket is persistent. Defaults to false. + * @var boolean $persistent + */ + var $persistent = false; + + /** + * The IP address to connect to. + * @var string $addr + */ + var $addr = ''; + + /** + * The port number to connect to. + * @var integer $port + */ + var $port = 0; + + /** + * Number of seconds to wait on socket connections before assuming + * there's no more data. Defaults to no timeout. + * @var integer $timeout + */ + var $timeout = false; + + /** + * Number of bytes to read at a time in readLine() and + * readAll(). Defaults to 2048. + * @var integer $lineLength + */ + var $lineLength = 2048; + + /** + * Connect to the specified port. If called when the socket is + * already connected, it disconnects and connects again. + * + * @param string $addr IP address or host name. + * @param integer $port TCP port number. + * @param boolean $persistent (optional) Whether the connection is + * persistent (kept open between requests + * by the web server). + * @param integer $timeout (optional) How long to wait for data. + * @param array $options See options for stream_context_create. + * + * @access public + * + * @return boolean | PEAR_Error True on success or a PEAR_Error on failure. + */ + function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null) + { + if (is_resource($this->fp)) { + @fclose($this->fp); + $this->fp = null; + } + + if (!$addr) { + return $this->raiseError('$addr cannot be empty'); + } elseif (strspn($addr, '.0123456789') == strlen($addr) || + strstr($addr, '/') !== false) { + $this->addr = $addr; + } else { + $this->addr = @gethostbyname($addr); + } + + $this->port = $port % 65536; + + if ($persistent !== null) { + $this->persistent = $persistent; + } + + if ($timeout !== null) { + $this->timeout = $timeout; + } + + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; + $errno = 0; + $errstr = ''; + $old_track_errors = @ini_set('track_errors', 1); + if ($options && function_exists('stream_context_create')) { + if ($this->timeout) { + $timeout = $this->timeout; + } else { + $timeout = 0; + } + $context = stream_context_create($options); + + // Since PHP 5 fsockopen doesn't allow context specification + if (function_exists('stream_socket_client')) { + $flags = $this->persistent ? STREAM_CLIENT_PERSISTENT : STREAM_CLIENT_CONNECT; + $addr = $this->addr . ':' . $this->port; + $fp = stream_socket_client($addr, $errno, $errstr, $timeout, $flags, $context); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context); + } + } else { + if ($this->timeout) { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr); + } + } + + if (!$fp) { + if ($errno == 0 && isset($php_errormsg)) { + $errstr = $php_errormsg; + } + @ini_set('track_errors', $old_track_errors); + return $this->raiseError($errstr, $errno); + } + + @ini_set('track_errors', $old_track_errors); + $this->fp = $fp; + + return $this->setBlocking($this->blocking); + } + + /** + * Disconnects from the peer, closes the socket. + * + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function disconnect() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + @fclose($this->fp); + $this->fp = null; + return true; + } + + /** + * Find out if the socket is in blocking mode. + * + * @access public + * @return boolean The current blocking mode. + */ + function isBlocking() + { + return $this->blocking; + } + + /** + * Sets whether the socket connection should be blocking or + * not. A read call to a non-blocking socket will return immediately + * if there is no data available, whereas it will block until there + * is data for blocking sockets. + * + * @param boolean $mode True for blocking sockets, false for nonblocking. + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function setBlocking($mode) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $this->blocking = $mode; + socket_set_blocking($this->fp, $this->blocking); + return true; + } + + /** + * Sets the timeout value on socket descriptor, + * expressed in the sum of seconds and microseconds + * + * @param integer $seconds Seconds. + * @param integer $microseconds Microseconds. + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function setTimeout($seconds, $microseconds) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_set_timeout($this->fp, $seconds, $microseconds); + } + + /** + * Sets the file buffering size on the stream. + * See php's stream_set_write_buffer for more information. + * + * @param integer $size Write buffer size. + * @access public + * @return mixed on success or an PEAR_Error object otherwise + */ + function setWriteBuffer($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $returned = stream_set_write_buffer($this->fp, $size); + if ($returned == 0) { + return true; + } + return $this->raiseError('Cannot set write buffer.'); + } + + /** + * Returns information about an existing socket resource. + * Currently returns four entries in the result array: + * + *

+ * timed_out (bool) - The socket timed out waiting for data
+ * blocked (bool) - The socket was blocked
+ * eof (bool) - Indicates EOF event
+ * unread_bytes (int) - Number of bytes left in the socket buffer
+ *

+ * + * @access public + * @return mixed Array containing information about existing socket resource or a PEAR_Error instance otherwise + */ + function getStatus() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_get_status($this->fp); + } + + /** + * Get a specified line of data + * + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function gets($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fgets($this->fp, $size); + } + + /** + * Read a specified amount of data. This is guaranteed to return, + * and has the added benefit of getting everything in one fread() + * chunk; if you know the size of the data you're getting + * beforehand, this is definitely the way to go. + * + * @param integer $size The number of bytes to read from the socket. + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function read($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fread($this->fp, $size); + } + + /** + * Write a specified amount of data. + * + * @param string $data Data to write. + * @param integer $blocksize Amount of data to write at once. + * NULL means all at once. + * + * @access public + * @return mixed If the socket is not connected, returns an instance of PEAR_Error + * If the write succeeds, returns the number of bytes written + * If the write fails, returns false. + */ + function write($data, $blocksize = null) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + if (is_null($blocksize) && !OS_WINDOWS) { + return @fwrite($this->fp, $data); + } else { + if (is_null($blocksize)) { + $blocksize = 1024; + } + + $pos = 0; + $size = strlen($data); + while ($pos < $size) { + $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); + if ($written === false) { + return false; + } + $pos += $written; + } + + return $pos; + } + } + + /** + * Write a line of data to the socket, followed by a trailing "\r\n". + * + * @access public + * @return mixed fputs result, or an error + */ + function writeLine($data) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return fwrite($this->fp, $data . "\r\n"); + } + + /** + * Tests for end-of-file on a socket descriptor. + * + * Also returns true if the socket is disconnected. + * + * @access public + * @return bool + */ + function eof() + { + return (!is_resource($this->fp) || feof($this->fp)); + } + + /** + * Reads a byte of data + * + * @access public + * @return 1 byte of data from the socket, or a PEAR_Error if + * not connected. + */ + function readByte() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return ord(@fread($this->fp, 1)); + } + + /** + * Reads a word of data + * + * @access public + * @return 1 word of data from the socket, or a PEAR_Error if + * not connected. + */ + function readWord() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); + } + + /** + * Reads an int of data + * + * @access public + * @return integer 1 int of data from the socket, or a PEAR_Error if + * not connected. + */ + function readInt() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + } + + /** + * Reads a zero-terminated string of data + * + * @access public + * @return string, or a PEAR_Error if + * not connected. + */ + function readString() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $string = ''; + while (($char = @fread($this->fp, 1)) != "\x00") { + $string .= $char; + } + return $string; + } + + /** + * Reads an IP Address and returns it in a dot formatted string + * + * @access public + * @return Dot formatted string, or a PEAR_Error if + * not connected. + */ + function readIPAddress() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]), + ord($buf[2]), ord($buf[3])); + } + + /** + * Read until either the end of the socket or a newline, whichever + * comes first. Strips the trailing newline from the returned data. + * + * @access public + * @return All available data up to a newline, without that + * newline, or until the end of the socket, or a PEAR_Error if + * not connected. + */ + function readLine() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $line = ''; + $timeout = time() + $this->timeout; + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { + $line .= @fgets($this->fp, $this->lineLength); + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Read until the socket closes, or until there is no more data in + * the inner PHP buffer. If the inner buffer is empty, in blocking + * mode we wait for at least 1 byte of data. Therefore, in + * blocking mode, if there is no data at all to be read, this + * function will never exit (unless the socket is closed on the + * remote end). + * + * @access public + * + * @return string All data until the socket closes, or a PEAR_Error if + * not connected. + */ + function readAll() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $data = ''; + while (!feof($this->fp)) { + $data .= @fread($this->fp, $this->lineLength); + } + return $data; + } + + /** + * Runs the equivalent of the select() system call on the socket + * with a timeout specified by tv_sec and tv_usec. + * + * @param integer $state Which of read/write/error to check for. + * @param integer $tv_sec Number of seconds for timeout. + * @param integer $tv_usec Number of microseconds for timeout. + * + * @access public + * @return False if select fails, integer describing which of read/write/error + * are ready, or PEAR_Error if not connected. + */ + function select($state, $tv_sec, $tv_usec = 0) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $read = null; + $write = null; + $except = null; + if ($state & NET_SOCKET_READ) { + $read[] = $this->fp; + } + if ($state & NET_SOCKET_WRITE) { + $write[] = $this->fp; + } + if ($state & NET_SOCKET_ERROR) { + $except[] = $this->fp; + } + if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { + return false; + } + + $result = 0; + if (count($read)) { + $result |= NET_SOCKET_READ; + } + if (count($write)) { + $result |= NET_SOCKET_WRITE; + } + if (count($except)) { + $result |= NET_SOCKET_ERROR; + } + return $result; + } + + /** + * Turns encryption on/off on a connected socket. + * + * @param bool $enabled Set this parameter to true to enable encryption + * and false to disable encryption. + * @param integer $type Type of encryption. See + * http://se.php.net/manual/en/function.stream-socket-enable-crypto.php for values. + * + * @access public + * @return false on error, true on success and 0 if there isn't enough data and the + * user should try again (non-blocking sockets only). A PEAR_Error object + * is returned if the socket is not connected + */ + function enableCrypto($enabled, $type) + { + if (version_compare(phpversion(), "5.1.0", ">=")) { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + return @stream_socket_enable_crypto($this->fp, $enabled, $type); + } else { + return $this->raiseError('Net_Socket::enableCrypto() requires php version >= 5.1.0'); + } + } + +} diff --git a/plugins/www/check_uri_response_code/lib/Pear/Net/URL.php b/plugins/www/check_uri_response_code/lib/Pear/Net/URL.php new file mode 100644 index 0000000..3dcfef6 --- /dev/null +++ b/plugins/www/check_uri_response_code/lib/Pear/Net/URL.php @@ -0,0 +1,485 @@ + | +// +-----------------------------------------------------------------------+ +// +// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $ +// +// Net_URL Class + + +class Net_URL +{ + var $options = array('encode_query_keys' => false); + /** + * Full url + * @var string + */ + var $url; + + /** + * Protocol + * @var string + */ + var $protocol; + + /** + * Username + * @var string + */ + var $username; + + /** + * Password + * @var string + */ + var $password; + + /** + * Host + * @var string + */ + var $host; + + /** + * Port + * @var integer + */ + var $port; + + /** + * Path + * @var string + */ + var $path; + + /** + * Query string + * @var array + */ + var $querystring; + + /** + * Anchor + * @var string + */ + var $anchor; + + /** + * Whether to use [] + * @var bool + */ + var $useBrackets; + + /** + * PHP4 Constructor + * + * @see __construct() + */ + function Net_URL($url = null, $useBrackets = true) + { + $this->__construct($url, $useBrackets); + } + + /** + * PHP5 Constructor + * + * Parses the given url and stores the various parts + * Defaults are used in certain cases + * + * @param string $url Optional URL + * @param bool $useBrackets Whether to use square brackets when + * multiple querystrings with the same name + * exist + */ + function __construct($url = null, $useBrackets = true) + { + $this->url = $url; + $this->useBrackets = $useBrackets; + + $this->initialize(); + } + + function initialize() + { + $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + + $this->user = ''; + $this->pass = ''; + $this->host = ''; + $this->port = 80; + $this->path = ''; + $this->querystring = array(); + $this->anchor = ''; + + // Only use defaults if not an absolute URL given + if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) { + $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http'); + + /** + * Figure out host/port + */ + if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) && + preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) + { + $host = $matches[1]; + if (!empty($matches[3])) { + $port = $matches[3]; + } else { + $port = $this->getStandardPort($this->protocol); + } + } + + $this->user = ''; + $this->pass = ''; + $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost'); + $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol)); + $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/'; + $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null; + $this->anchor = ''; + } + + // Parse the url and store the various parts + if (!empty($this->url)) { + $urlinfo = parse_url($this->url); + + // Default querystring + $this->querystring = array(); + + foreach ($urlinfo as $key => $value) { + switch ($key) { + case 'scheme': + $this->protocol = $value; + $this->port = $this->getStandardPort($value); + break; + + case 'user': + case 'pass': + case 'host': + case 'port': + $this->$key = $value; + break; + + case 'path': + if ($value{0} == '/') { + $this->path = $value; + } else { + $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path); + $this->path = sprintf('%s/%s', $path, $value); + } + break; + + case 'query': + $this->querystring = $this->_parseRawQueryString($value); + break; + + case 'fragment': + $this->anchor = $value; + break; + } + } + } + } + /** + * Returns full url + * + * @return string Full url + * @access public + */ + function getURL() + { + $querystring = $this->getQueryString(); + + $this->url = $this->protocol . '://' + . $this->user . (!empty($this->pass) ? ':' : '') + . $this->pass . (!empty($this->user) ? '@' : '') + . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) + . $this->path + . (!empty($querystring) ? '?' . $querystring : '') + . (!empty($this->anchor) ? '#' . $this->anchor : ''); + + return $this->url; + } + + /** + * Adds or updates a querystring item (URL parameter). + * Automatically encodes parameters with rawurlencode() if $preencoded + * is false. + * You can pass an array to $value, it gets mapped via [] in the URL if + * $this->useBrackets is activated. + * + * @param string $name Name of item + * @param string $value Value of item + * @param bool $preencoded Whether value is urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + if ($this->getOption('encode_query_keys')) { + $name = rawurlencode($name); + } + + if ($preencoded) { + $this->querystring[$name] = $value; + } else { + $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value); + } + } + + /** + * Removes a querystring item + * + * @param string $name Name of item + * @access public + */ + function removeQueryString($name) + { + if ($this->getOption('encode_query_keys')) { + $name = rawurlencode($name); + } + + if (isset($this->querystring[$name])) { + unset($this->querystring[$name]); + } + } + + /** + * Sets the querystring to literally what you supply + * + * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc + * @access public + */ + function addRawQueryString($querystring) + { + $this->querystring = $this->_parseRawQueryString($querystring); + } + + /** + * Returns flat querystring + * + * @return string Querystring + * @access public + */ + function getQueryString() + { + if (!empty($this->querystring)) { + foreach ($this->querystring as $name => $value) { + // Encode var name + $name = rawurlencode($name); + + if (is_array($value)) { + foreach ($value as $k => $v) { + $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v); + } + } elseif (!is_null($value)) { + $querystring[] = $name . '=' . $value; + } else { + $querystring[] = $name; + } + } + $querystring = implode(ini_get('arg_separator.output'), $querystring); + } else { + $querystring = ''; + } + + return $querystring; + } + + /** + * Parses raw querystring and returns an array of it + * + * @param string $querystring The querystring to parse + * @return array An array of the querystring data + * @access private + */ + function _parseRawQuerystring($querystring) + { + $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY); + $return = array(); + + foreach ($parts as $part) { + if (strpos($part, '=') !== false) { + $value = substr($part, strpos($part, '=') + 1); + $key = substr($part, 0, strpos($part, '=')); + } else { + $value = null; + $key = $part; + } + + if (!$this->getOption('encode_query_keys')) { + $key = rawurldecode($key); + } + + if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) { + $key = $matches[1]; + $idx = $matches[2]; + + // Ensure is an array + if (empty($return[$key]) || !is_array($return[$key])) { + $return[$key] = array(); + } + + // Add data + if ($idx === '') { + $return[$key][] = $value; + } else { + $return[$key][$idx] = $value; + } + } elseif (!$this->useBrackets AND !empty($return[$key])) { + $return[$key] = (array)$return[$key]; + $return[$key][] = $value; + } else { + $return[$key] = $value; + } + } + + return $return; + } + + /** + * Resolves //, ../ and ./ from a path and returns + * the result. Eg: + * + * /foo/bar/../boo.php => /foo/boo.php + * /foo/bar/../../boo.php => /boo.php + * /foo/bar/.././/boo.php => /foo/boo.php + * + * This method can also be called statically. + * + * @param string $path URL path to resolve + * @return string The result + */ + function resolvePath($path) + { + $path = explode('/', str_replace('//', '/', $path)); + + for ($i=0; $i 1 OR ($i == 1 AND $path[0] != '') ) ) { + unset($path[$i]); + unset($path[$i-1]); + $path = array_values($path); + $i -= 2; + + } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') { + unset($path[$i]); + $path = array_values($path); + $i--; + + } else { + continue; + } + } + + return implode('/', $path); + } + + /** + * Returns the standard port number for a protocol + * + * @param string $scheme The protocol to lookup + * @return integer Port number or NULL if no scheme matches + * + * @author Philippe Jausions + */ + function getStandardPort($scheme) + { + switch (strtolower($scheme)) { + case 'http': return 80; + case 'https': return 443; + case 'ftp': return 21; + case 'imap': return 143; + case 'imaps': return 993; + case 'pop3': return 110; + case 'pop3s': return 995; + default: return null; + } + } + + /** + * Forces the URL to a particular protocol + * + * @param string $protocol Protocol to force the URL to + * @param integer $port Optional port (standard port is used by default) + */ + function setProtocol($protocol, $port = null) + { + $this->protocol = $protocol; + $this->port = is_null($port) ? $this->getStandardPort($protocol) : $port; + } + + /** + * Set an option + * + * This function set an option + * to be used thorough the script. + * + * @access public + * @param string $optionName The optionname to set + * @param string $value The value of this option. + */ + function setOption($optionName, $value) + { + if (!array_key_exists($optionName, $this->options)) { + return false; + } + + $this->options[$optionName] = $value; + $this->initialize(); + } + + /** + * Get an option + * + * This function gets an option + * from the $this->options array + * and return it's value. + * + * @access public + * @param string $opionName The name of the option to retrieve + * @see $this->options + */ + function getOption($optionName) + { + if (!isset($this->options[$optionName])) { + return false; + } + + return $this->options[$optionName]; + } + +} +?> diff --git a/plugins/www/http_download_file/CHANGELOG b/plugins/www/http_download_file/CHANGELOG new file mode 100644 index 0000000..1027d7d --- /dev/null +++ b/plugins/www/http_download_file/CHANGELOG @@ -0,0 +1,11 @@ +1.0.2 (2009.09.22) +------------------ +Changed. Updated Pear library. + +1.0.1 (2007.11.19) +------------------ +Use init.inc.php + +1.0.0 (2007.10.22) +------------------ +Initial release \ No newline at end of file diff --git a/plugins/www/http_download_file/COPYRIGHT b/plugins/www/http_download_file/COPYRIGHT new file mode 100644 index 0000000..e087645 --- /dev/null +++ b/plugins/www/http_download_file/COPYRIGHT @@ -0,0 +1,30 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +Simpletest +========== +Copyright: http://simpletest.sourceforge.net/projects/simpletest/ +License: GPL + +TestGen4Web +=========== +Copyright: 2004-2006 SpikeSource, Inc. +License: Open Software License v2.1 (see: http://www.spikesource.com/license.html) \ No newline at end of file diff --git a/plugins/www/http_download_file/LICENSE b/plugins/www/http_download_file/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/www/http_download_file/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/www/http_download_file/configure.php b/plugins/www/http_download_file/configure.php new file mode 100644 index 0000000..dadc023 --- /dev/null +++ b/plugins/www/http_download_file/configure.php @@ -0,0 +1,61 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['http_download_file'][0]['version'] = '1.0.2'; +$plugin_field['http_download_file'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['http_download_file'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['http_download_file'][0]['description'] = PLUGIN_HTTP_DOWNLOAD_FILE_DESCRIPTION; +$plugin_field['http_download_file'][0]['title'] = PLUGIN_HTTP_DOWNLOAD_FILE_TITLE; + +$plugin_field['http_download_file'][1]['type'] = 'text'; +$plugin_field['http_download_file'][1]['name'] = 'http_download_file_identity'; +$plugin_field['http_download_file'][1]['value'] = ''; +$plugin_field['http_download_file'][1]['attributes'] = 'disabled readonly size=30'; +$plugin_field['http_download_file'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['http_download_file'][1]['num_rules'] = '0'; + +$plugin_field['http_download_file'][2]['type'] = 'select'; +$plugin_field['http_download_file'][2]['name'] = 'http_download_file_protocol'; +$plugin_field['http_download_file'][2]['value'] = array('http' => 'http', 'https' => 'https'); +$plugin_field['http_download_file'][2]['attributes'] = ''; +$plugin_field['http_download_file'][2]['description'] = PLUGIN_HTTP_PROTOCOL; +$plugin_field['http_download_file'][2]['num_rules'] = '0'; + +$plugin_field['http_download_file'][3]['type'] = 'text'; +$plugin_field['http_download_file'][3]['name'] = 'http_download_file_port'; +$plugin_field['http_download_file'][3]['value'] = ''; +$plugin_field['http_download_file'][3]['attributes'] = 'disabled size=10'; +$plugin_field['http_download_file'][3]['description'] = PLUGIN_HTTP_PORT; +$plugin_field['http_download_file'][3]['num_rules'] = '0'; + +$plugin_field['http_download_file'][4]['type'] = 'text'; +$plugin_field['http_download_file'][4]['name'] = 'http_download_file_url'; +$plugin_field['http_download_file'][4]['value'] = ''; +$plugin_field['http_download_file'][4]['attributes'] = 'disabled size=50'; +$plugin_field['http_download_file'][4]['description'] = PLUGIN_HTTP_DOWNLOAD_FILE_URL_DESCRIPTION; +$plugin_field['http_download_file'][4]['num_rules'] = '0'; + +$plugin_field['http_download_file'][5]['type'] = 'text'; +$plugin_field['http_download_file'][5]['name'] = 'http_download_file_save_as'; +$plugin_field['http_download_file'][5]['value'] = ''; +$plugin_field['http_download_file'][5]['attributes'] = 'disabled size=50'; +$plugin_field['http_download_file'][5]['description'] = PLUGIN_HTTP_DOWNLOAD_FILE_SAVE_AS_DESCRIPTION; +$plugin_field['http_download_file'][5]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/www/http_download_file/core.php b/plugins/www/http_download_file/core.php new file mode 100644 index 0000000..3acaf72 --- /dev/null +++ b/plugins/www/http_download_file/core.php @@ -0,0 +1,105 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +set_include_path(realpath(dirname($argv[0])) . "/lib/Pear/:" . + ini_get("include_path")); +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +//---- Start plugin code ----- + +require_once 'HTTP/Request.php'; + +$loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); +$log_prefix = '[job: ' . $id_job . '] '; +$loggerPlugin->trace('INFO', $log_prefix . 'Executing job'); + +$result = 0; + +//Get the params required by plugin from argv +$user = $job_infos['identity']['username']; +$password = $job_infos['identity']['password']; +$id_system = $job_infos['id_system']; +$ip = $job_infos['ip']; + +$protocol = $parameters['http_download_file_protocol']; +$port = $parameters['http_download_file_port']; +$url = $parameters['http_download_file_url']; +$save_as = trim($parameters['http_download_file_save_as']); + +if ($save_as == '') { + $save_as = basename($url); +} + +$path_save = ORTRO_INCOMING . $id_system . DS; +//check for existing folder system otherwise create it +if (!is_dir($path_save)) { + @mkdir($path_save, 0700, true); +} + +//Generate the uri +$uri = $protocol . '://' . $ip . ':' . $port . '/' . $url; + +//Perform the request +$req =& new HTTP_Request(""); +$req->setURL($uri); +if (isset($user) && $user != '') { + $req->setBasicAuth($user, $password); +} + +$response = $req->sendRequest(); + +if (PEAR::isError($response)) { + $result = '0'; + $msg_exec = $response->getMessage(); + $loggerPlugin->trace('ERROR', $log_prefix . $msg_exec); +} else { + $fh = fopen($path_save . $save_as, 'w+'); + fwrite($fh, $req->getResponseBody()); + fclose($fh); + $output = $path_save . $save_as; + $result = '1'; + $msg_exec = ''; +} + +//---- End plugin code ----- + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, + $msg_exec, $attachments, $output); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/www/http_download_file/lib/Pear/HTTP/Request.php b/plugins/www/http_download_file/lib/Pear/HTTP/Request.php new file mode 100644 index 0000000..d167cf1 --- /dev/null +++ b/plugins/www/http_download_file/lib/Pear/HTTP/Request.php @@ -0,0 +1,1484 @@ + + * @author Alexey Borzov + * @copyright 2002-2007 Richard Heyes + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Request.php,v 1.58 2007/10/26 13:45:56 avb Exp $ + * @link http://pear.php.net/package/HTTP_Request/ + */ + +/** + * PEAR and PEAR_Error classes (for error handling) + */ +require_once 'PEAR.php'; +/** + * Socket class + */ +require_once 'Net/Socket.php'; +/** + * URL handling class + */ +require_once 'Net/URL.php'; + +/**#@+ + * Constants for HTTP request methods + */ +define('HTTP_REQUEST_METHOD_GET', 'GET', true); +define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true); +define('HTTP_REQUEST_METHOD_POST', 'POST', true); +define('HTTP_REQUEST_METHOD_PUT', 'PUT', true); +define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true); +define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true); +define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true); +/**#@-*/ + +/**#@+ + * Constants for HTTP request error codes + */ +define('HTTP_REQUEST_ERROR_FILE', 1); +define('HTTP_REQUEST_ERROR_URL', 2); +define('HTTP_REQUEST_ERROR_PROXY', 4); +define('HTTP_REQUEST_ERROR_REDIRECTS', 8); +define('HTTP_REQUEST_ERROR_RESPONSE', 16); +define('HTTP_REQUEST_ERROR_GZIP_METHOD', 32); +define('HTTP_REQUEST_ERROR_GZIP_READ', 64); +define('HTTP_REQUEST_ERROR_GZIP_DATA', 128); +define('HTTP_REQUEST_ERROR_GZIP_CRC', 256); +/**#@-*/ + +/**#@+ + * Constants for HTTP protocol versions + */ +define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true); +define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true); +/**#@-*/ + +if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + /** + * Whether string functions are overloaded by their mbstring equivalents + */ + define('HTTP_REQUEST_MBSTRING', true); +} else { + /** + * @ignore + */ + define('HTTP_REQUEST_MBSTRING', false); +} + +/** + * Class for performing HTTP requests + * + * Simple example (fetches yahoo.com and displays it): + * + * $a = &new HTTP_Request('http://www.yahoo.com/'); + * $a->sendRequest(); + * echo $a->getResponseBody(); + * + * + * @category HTTP + * @package HTTP_Request + * @author Richard Heyes + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Request +{ + /**#@+ + * @access private + */ + /** + * Instance of Net_URL + * @var Net_URL + */ + var $_url; + + /** + * Type of request + * @var string + */ + var $_method; + + /** + * HTTP Version + * @var string + */ + var $_http; + + /** + * Request headers + * @var array + */ + var $_requestHeaders; + + /** + * Basic Auth Username + * @var string + */ + var $_user; + + /** + * Basic Auth Password + * @var string + */ + var $_pass; + + /** + * Socket object + * @var Net_Socket + */ + var $_sock; + + /** + * Proxy server + * @var string + */ + var $_proxy_host; + + /** + * Proxy port + * @var integer + */ + var $_proxy_port; + + /** + * Proxy username + * @var string + */ + var $_proxy_user; + + /** + * Proxy password + * @var string + */ + var $_proxy_pass; + + /** + * Post data + * @var array + */ + var $_postData; + + /** + * Request body + * @var string + */ + var $_body; + + /** + * A list of methods that MUST NOT have a request body, per RFC 2616 + * @var array + */ + var $_bodyDisallowed = array('TRACE'); + + /** + * Files to post + * @var array + */ + var $_postFiles = array(); + + /** + * Connection timeout. + * @var float + */ + var $_timeout; + + /** + * HTTP_Response object + * @var HTTP_Response + */ + var $_response; + + /** + * Whether to allow redirects + * @var boolean + */ + var $_allowRedirects; + + /** + * Maximum redirects allowed + * @var integer + */ + var $_maxRedirects; + + /** + * Current number of redirects + * @var integer + */ + var $_redirects; + + /** + * Whether to append brackets [] to array variables + * @var bool + */ + var $_useBrackets = true; + + /** + * Attached listeners + * @var array + */ + var $_listeners = array(); + + /** + * Whether to save response body in response object property + * @var bool + */ + var $_saveBody = true; + + /** + * Timeout for reading from socket (array(seconds, microseconds)) + * @var array + */ + var $_readTimeout = null; + + /** + * Options to pass to Net_Socket::connect. See stream_context_create + * @var array + */ + var $_socketOptions = null; + /**#@-*/ + + /** + * Constructor + * + * Sets up the object + * @param string The url to fetch/access + * @param array Associative array of parameters which can have the following keys: + *
    + *
  • method - Method to use, GET, POST etc (string)
  • + *
  • http - HTTP Version to use, 1.0 or 1.1 (string)
  • + *
  • user - Basic Auth username (string)
  • + *
  • pass - Basic Auth password (string)
  • + *
  • proxy_host - Proxy server host (string)
  • + *
  • proxy_port - Proxy server port (integer)
  • + *
  • proxy_user - Proxy auth username (string)
  • + *
  • proxy_pass - Proxy auth password (string)
  • + *
  • timeout - Connection timeout in seconds (float)
  • + *
  • allowRedirects - Whether to follow redirects or not (bool)
  • + *
  • maxRedirects - Max number of redirects to follow (integer)
  • + *
  • useBrackets - Whether to append [] to array variable names (bool)
  • + *
  • saveBody - Whether to save response body in response object property (bool)
  • + *
  • readTimeout - Timeout for reading / writing data over the socket (array (seconds, microseconds))
  • + *
  • socketOptions - Options to pass to Net_Socket object (array)
  • + *
+ * @access public + */ + function HTTP_Request($url = '', $params = array()) + { + $this->_method = HTTP_REQUEST_METHOD_GET; + $this->_http = HTTP_REQUEST_HTTP_VER_1_1; + $this->_requestHeaders = array(); + $this->_postData = array(); + $this->_body = null; + + $this->_user = null; + $this->_pass = null; + + $this->_proxy_host = null; + $this->_proxy_port = null; + $this->_proxy_user = null; + $this->_proxy_pass = null; + + $this->_allowRedirects = false; + $this->_maxRedirects = 3; + $this->_redirects = 0; + + $this->_timeout = null; + $this->_response = null; + + foreach ($params as $key => $value) { + $this->{'_' . $key} = $value; + } + + if (!empty($url)) { + $this->setURL($url); + } + + // Default useragent + $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )'); + + // We don't do keep-alives by default + $this->addHeader('Connection', 'close'); + + // Basic authentication + if (!empty($this->_user)) { + $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass)); + } + + // Proxy authentication (see bug #5913) + if (!empty($this->_proxy_user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass)); + } + + // Use gzip encoding if possible + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) { + $this->addHeader('Accept-Encoding', 'gzip'); + } + } + + /** + * Generates a Host header for HTTP/1.1 requests + * + * @access private + * @return string + */ + function _generateHostHeader() + { + if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) { + $host = $this->_url->host . ':' . $this->_url->port; + + } else { + $host = $this->_url->host; + } + + return $host; + } + + /** + * Resets the object to its initial state (DEPRECATED). + * Takes the same parameters as the constructor. + * + * @param string $url The url to be requested + * @param array $params Associative array of parameters + * (see constructor for details) + * @access public + * @deprecated deprecated since 1.2, call the constructor if this is necessary + */ + function reset($url, $params = array()) + { + $this->HTTP_Request($url, $params); + } + + /** + * Sets the URL to be requested + * + * @param string The url to be requested + * @access public + */ + function setURL($url) + { + $this->_url = &new Net_URL($url, $this->_useBrackets); + + if (!empty($this->_url->user) || !empty($this->_url->pass)) { + $this->setBasicAuth($this->_url->user, $this->_url->pass); + } + + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) { + $this->addHeader('Host', $this->_generateHostHeader()); + } + + // set '/' instead of empty path rather than check later (see bug #8662) + if (empty($this->_url->path)) { + $this->_url->path = '/'; + } + } + + /** + * Returns the current request URL + * + * @return string Current request URL + * @access public + */ + function getUrl() + { + return empty($this->_url)? '': $this->_url->getUrl(); + } + + /** + * Sets a proxy to be used + * + * @param string Proxy host + * @param int Proxy port + * @param string Proxy username + * @param string Proxy password + * @access public + */ + function setProxy($host, $port = 8080, $user = null, $pass = null) + { + $this->_proxy_host = $host; + $this->_proxy_port = $port; + $this->_proxy_user = $user; + $this->_proxy_pass = $pass; + + if (!empty($user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + } + + /** + * Sets basic authentication parameters + * + * @param string Username + * @param string Password + */ + function setBasicAuth($user, $pass) + { + $this->_user = $user; + $this->_pass = $pass; + + $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + + /** + * Sets the method to be used, GET, POST etc. + * + * @param string Method to use. Use the defined constants for this + * @access public + */ + function setMethod($method) + { + $this->_method = $method; + } + + /** + * Sets the HTTP version to use, 1.0 or 1.1 + * + * @param string Version to use. Use the defined constants for this + * @access public + */ + function setHttpVer($http) + { + $this->_http = $http; + } + + /** + * Adds a request header + * + * @param string Header name + * @param string Header value + * @access public + */ + function addHeader($name, $value) + { + $this->_requestHeaders[strtolower($name)] = $value; + } + + /** + * Removes a request header + * + * @param string Header name to remove + * @access public + */ + function removeHeader($name) + { + if (isset($this->_requestHeaders[strtolower($name)])) { + unset($this->_requestHeaders[strtolower($name)]); + } + } + + /** + * Adds a querystring parameter + * + * @param string Querystring parameter name + * @param string Querystring parameter value + * @param bool Whether the value is already urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + $this->_url->addQueryString($name, $value, $preencoded); + } + + /** + * Sets the querystring to literally what you supply + * + * @param string The querystring data. Should be of the format foo=bar&x=y etc + * @param bool Whether data is already urlencoded or not, default = already encoded + * @access public + */ + function addRawQueryString($querystring, $preencoded = true) + { + $this->_url->addRawQueryString($querystring, $preencoded); + } + + /** + * Adds postdata items + * + * @param string Post data name + * @param string Post data value + * @param bool Whether data is already urlencoded or not, default = not + * @access public + */ + function addPostData($name, $value, $preencoded = false) + { + if ($preencoded) { + $this->_postData[$name] = $value; + } else { + $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value); + } + } + + /** + * Recursively applies the callback function to the value + * + * @param mixed Callback function + * @param mixed Value to process + * @access private + * @return mixed Processed value + */ + function _arrayMapRecursive($callback, $value) + { + if (!is_array($value)) { + return call_user_func($callback, $value); + } else { + $map = array(); + foreach ($value as $k => $v) { + $map[$k] = $this->_arrayMapRecursive($callback, $v); + } + return $map; + } + } + + /** + * Adds a file to upload + * + * This also changes content-type to 'multipart/form-data' for proper upload + * + * @access public + * @param string name of file-upload field + * @param mixed file name(s) + * @param mixed content-type(s) of file(s) being uploaded + * @return bool true on success + * @throws PEAR_Error + */ + function addFile($inputName, $fileName, $contentType = 'application/octet-stream') + { + if (!is_array($fileName) && !is_readable($fileName)) { + return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE); + } elseif (is_array($fileName)) { + foreach ($fileName as $name) { + if (!is_readable($name)) { + return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE); + } + } + } + $this->addHeader('Content-Type', 'multipart/form-data'); + $this->_postFiles[$inputName] = array( + 'name' => $fileName, + 'type' => $contentType + ); + return true; + } + + /** + * Adds raw postdata (DEPRECATED) + * + * @param string The data + * @param bool Whether data is preencoded or not, default = already encoded + * @access public + * @deprecated deprecated since 1.3.0, method setBody() should be used instead + */ + function addRawPostData($postdata, $preencoded = true) + { + $this->_body = $preencoded ? $postdata : urlencode($postdata); + } + + /** + * Sets the request body (for POST, PUT and similar requests) + * + * @param string Request body + * @access public + */ + function setBody($body) + { + $this->_body = $body; + } + + /** + * Clears any postdata that has been added (DEPRECATED). + * + * Useful for multiple request scenarios. + * + * @access public + * @deprecated deprecated since 1.2 + */ + function clearPostData() + { + $this->_postData = null; + } + + /** + * Appends a cookie to "Cookie:" header + * + * @param string $name cookie name + * @param string $value cookie value + * @access public + */ + function addCookie($name, $value) + { + $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : ''; + $this->addHeader('Cookie', $cookies . $name . '=' . $value); + } + + /** + * Clears any cookies that have been added (DEPRECATED). + * + * Useful for multiple request scenarios + * + * @access public + * @deprecated deprecated since 1.2 + */ + function clearCookies() + { + $this->removeHeader('Cookie'); + } + + /** + * Sends the request + * + * @access public + * @param bool Whether to store response body in Response object property, + * set this to false if downloading a LARGE file and using a Listener + * @return mixed PEAR error on error, true otherwise + */ + function sendRequest($saveBody = true) + { + if (!is_a($this->_url, 'Net_URL')) { + return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL); + } + + $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host; + $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port; + + // 4.3.0 supports SSL connections using OpenSSL. The function test determines + // we running on at least 4.3.0 + if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) { + if (isset($this->_proxy_host)) { + return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY); + } + $host = 'ssl://' . $host; + } + + // magic quotes may fuck up file uploads and chunked response processing + $magicQuotes = ini_get('magic_quotes_runtime'); + ini_set('magic_quotes_runtime', false); + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) && + 'Keep-Alive' == $this->_requestHeaders['connection']) + { + $this->removeHeader('connection'); + } + + $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) || + (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']); + $sockets = &PEAR::getStaticProperty('HTTP_Request', 'sockets'); + $sockKey = $host . ':' . $port; + unset($this->_sock); + + // There is a connected socket in the "static" property? + if ($keepAlive && !empty($sockets[$sockKey]) && + !empty($sockets[$sockKey]->fp)) + { + $this->_sock =& $sockets[$sockKey]; + $err = null; + } else { + $this->_notify('connect'); + $this->_sock =& new Net_Socket(); + $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions); + } + PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest()); + + if (!PEAR::isError($err)) { + if (!empty($this->_readTimeout)) { + $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]); + } + + $this->_notify('sentRequest'); + + // Read the response + $this->_response = &new HTTP_Response($this->_sock, $this->_listeners); + $err = $this->_response->process( + $this->_saveBody && $saveBody, + HTTP_REQUEST_METHOD_HEAD != $this->_method + ); + + if ($keepAlive) { + $keepAlive = (isset($this->_response->_headers['content-length']) + || (isset($this->_response->_headers['transfer-encoding']) + && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked')); + if ($keepAlive) { + if (isset($this->_response->_headers['connection'])) { + $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive'; + } else { + $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol; + } + } + } + } + + ini_set('magic_quotes_runtime', $magicQuotes); + + if (PEAR::isError($err)) { + return $err; + } + + if (!$keepAlive) { + $this->disconnect(); + // Store the connected socket in "static" property + } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) { + $sockets[$sockKey] =& $this->_sock; + } + + // Check for redirection + if ( $this->_allowRedirects + AND $this->_redirects <= $this->_maxRedirects + AND $this->getResponseCode() > 300 + AND $this->getResponseCode() < 399 + AND !empty($this->_response->_headers['location'])) { + + + $redirect = $this->_response->_headers['location']; + + // Absolute URL + if (preg_match('/^https?:\/\//i', $redirect)) { + $this->_url = &new Net_URL($redirect); + $this->addHeader('Host', $this->_generateHostHeader()); + // Absolute path + } elseif ($redirect{0} == '/') { + $this->_url->path = $redirect; + + // Relative path + } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $redirect = Net_URL::resolvePath($redirect); + $this->_url->path = $redirect; + + // Filename, no path + } else { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $this->_url->path = $redirect; + } + + $this->_redirects++; + return $this->sendRequest($saveBody); + + // Too many redirects + } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) { + return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS); + } + + return true; + } + + /** + * Disconnect the socket, if connected. Only useful if using Keep-Alive. + * + * @access public + */ + function disconnect() + { + if (!empty($this->_sock) && !empty($this->_sock->fp)) { + $this->_notify('disconnect'); + $this->_sock->disconnect(); + } + } + + /** + * Returns the response code + * + * @access public + * @return mixed Response code, false if not set + */ + function getResponseCode() + { + return isset($this->_response->_code) ? $this->_response->_code : false; + } + + /** + * Returns either the named header or all if no name given + * + * @access public + * @param string The header name to return, do not set to get all headers + * @return mixed either the value of $headername (false if header is not present) + * or an array of all headers + */ + function getResponseHeader($headername = null) + { + if (!isset($headername)) { + return isset($this->_response->_headers)? $this->_response->_headers: array(); + } else { + $headername = strtolower($headername); + return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false; + } + } + + /** + * Returns the body of the response + * + * @access public + * @return mixed response body, false if not set + */ + function getResponseBody() + { + return isset($this->_response->_body) ? $this->_response->_body : false; + } + + /** + * Returns cookies set in response + * + * @access public + * @return mixed array of response cookies, false if none are present + */ + function getResponseCookies() + { + return isset($this->_response->_cookies) ? $this->_response->_cookies : false; + } + + /** + * Builds the request string + * + * @access private + * @return string The request string + */ + function _buildRequest() + { + $separator = ini_get('arg_separator.output'); + ini_set('arg_separator.output', '&'); + $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : ''; + ini_set('arg_separator.output', $separator); + + $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : ''; + $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : ''; + $path = $this->_url->path . $querystring; + $url = $host . $port . $path; + + if (!strlen($url)) { + $url = '/'; + } + + $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n"; + + if (in_array($this->_method, $this->_bodyDisallowed) || + (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method || + (empty($this->_postData) && empty($this->_postFiles))))) + { + $this->removeHeader('Content-Type'); + } else { + if (empty($this->_requestHeaders['content-type'])) { + // Add default content-type + $this->addHeader('Content-Type', 'application/x-www-form-urlencoded'); + } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) { + $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime()); + $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary); + } + } + + // Request Headers + if (!empty($this->_requestHeaders)) { + foreach ($this->_requestHeaders as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $request .= $canonicalName . ': ' . $value . "\r\n"; + } + } + + // No post data or wrong method, so simply add a final CRLF + if (in_array($this->_method, $this->_bodyDisallowed) || + (HTTP_REQUEST_METHOD_POST != $this->_method && 0 == strlen($this->_body))) { + + $request .= "\r\n"; + + // Post data if it's an array + } elseif (HTTP_REQUEST_METHOD_POST == $this->_method && + (!empty($this->_postData) || !empty($this->_postFiles))) { + + // "normal" POST request + if (!isset($boundary)) { + $postdata = implode('&', array_map( + create_function('$a', 'return $a[0] . \'=\' . $a[1];'), + $this->_flattenArray('', $this->_postData) + )); + + // multipart request, probably with file uploads + } else { + $postdata = ''; + if (!empty($this->_postData)) { + $flatData = $this->_flattenArray('', $this->_postData); + foreach ($flatData as $item) { + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"'; + $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n"; + } + } + foreach ($this->_postFiles as $name => $value) { + if (is_array($value['name'])) { + $varname = $name . ($this->_useBrackets? '[]': ''); + } else { + $varname = $name; + $value['name'] = array($value['name']); + } + foreach ($value['name'] as $key => $filename) { + $fp = fopen($filename, 'r'); + $data = fread($fp, filesize($filename)); + fclose($fp); + $basename = basename($filename); + $type = is_array($value['type'])? @$value['type'][$key]: $value['type']; + + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"'; + $postdata .= "\r\nContent-Type: " . $type; + $postdata .= "\r\n\r\n" . $data . "\r\n"; + } + } + $postdata .= '--' . $boundary . "--\r\n"; + } + $request .= 'Content-Length: ' . + (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) . + "\r\n\r\n"; + $request .= $postdata; + + // Explicitly set request body + } elseif (0 < strlen($this->_body)) { + + $request .= 'Content-Length: ' . + (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) . + "\r\n\r\n"; + $request .= $this->_body; + + // Terminate headers with CRLF on POST request with no body, too + } else { + + $request .= "\r\n"; + } + + return $request; + } + + /** + * Helper function to change the (probably multidimensional) associative array + * into the simple one. + * + * @param string name for item + * @param mixed item's values + * @return array array with the following items: array('item name', 'item value'); + * @access private + */ + function _flattenArray($name, $values) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($this->_useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, $this->_flattenArray($newName, $v)); + } + return $ret; + } + } + + + /** + * Adds a Listener to the list of listeners that are notified of + * the object's events + * + * Events sent by HTTP_Request object + * - 'connect': on connection to server + * - 'sentRequest': after the request was sent + * - 'disconnect': on disconnection from server + * + * Events sent by HTTP_Response object + * - 'gotHeaders': after receiving response headers (headers are passed in $data) + * - 'tick': on receiving a part of response body (the part is passed in $data) + * - 'gzTick': on receiving a gzip-encoded part of response body (ditto) + * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped) + * + * @param HTTP_Request_Listener listener to attach + * @return boolean whether the listener was successfully attached + * @access public + */ + function attach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener')) { + return false; + } + $this->_listeners[$listener->getId()] =& $listener; + return true; + } + + + /** + * Removes a Listener from the list of listeners + * + * @param HTTP_Request_Listener listener to detach + * @return boolean whether the listener was successfully detached + * @access public + */ + function detach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener') || + !isset($this->_listeners[$listener->getId()])) { + return false; + } + unset($this->_listeners[$listener->getId()]); + return true; + } + + + /** + * Notifies all registered listeners of an event. + * + * @param string Event name + * @param mixed Additional data + * @access private + * @see HTTP_Request::attach() + */ + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } +} + + +/** + * Response class to complement the Request class + * + * @category HTTP + * @package HTTP_Request + * @author Richard Heyes + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Response +{ + /** + * Socket object + * @var Net_Socket + */ + var $_sock; + + /** + * Protocol + * @var string + */ + var $_protocol; + + /** + * Return code + * @var string + */ + var $_code; + + /** + * Response headers + * @var array + */ + var $_headers; + + /** + * Cookies set in response + * @var array + */ + var $_cookies; + + /** + * Response body + * @var string + */ + var $_body = ''; + + /** + * Used by _readChunked(): remaining length of the current chunk + * @var string + */ + var $_chunkLength = 0; + + /** + * Attached listeners + * @var array + */ + var $_listeners = array(); + + /** + * Bytes left to read from message-body + * @var null|int + */ + var $_toRead; + + /** + * Constructor + * + * @param Net_Socket socket to read the response from + * @param array listeners attached to request + */ + function HTTP_Response(&$sock, &$listeners) + { + $this->_sock =& $sock; + $this->_listeners =& $listeners; + } + + + /** + * Processes a HTTP response + * + * This extracts response code, headers, cookies and decodes body if it + * was encoded in some way + * + * @access public + * @param bool Whether to store response body in object property, set + * this to false if downloading a LARGE file and using a Listener. + * This is assumed to be true if body is gzip-encoded. + * @param bool Whether the response can actually have a message-body. + * Will be set to false for HEAD requests. + * @throws PEAR_Error + * @return mixed true on success, PEAR_Error in case of malformed response + */ + function process($saveBody = true, $canHaveBody = true) + { + do { + $line = $this->_sock->readLine(); + if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) { + return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE); + } else { + $this->_protocol = 'HTTP/' . $http_version; + $this->_code = intval($returncode); + } + while ('' !== ($header = $this->_sock->readLine())) { + $this->_processHeader($header); + } + } while (100 == $this->_code); + + $this->_notify('gotHeaders', $this->_headers); + + // RFC 2616, section 4.4: + // 1. Any response message which "MUST NOT" include a message-body ... + // is always terminated by the first empty line after the header fields + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $canHaveBody = $canHaveBody && $this->_code >= 200 && + $this->_code != 204 && $this->_code != 304; + + // If response body is present, read it and decode + $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']); + $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']); + $hasBody = false; + if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) || + 0 != $this->_headers['content-length'])) + { + if ($chunked || !isset($this->_headers['content-length'])) { + $this->_toRead = null; + } else { + $this->_toRead = $this->_headers['content-length']; + } + while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) { + if ($chunked) { + $data = $this->_readChunked(); + } elseif (is_null($this->_toRead)) { + $data = $this->_sock->read(4096); + } else { + $data = $this->_sock->read(min(4096, $this->_toRead)); + $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data); + } + if ('' == $data) { + break; + } else { + $hasBody = true; + if ($saveBody || $gzipped) { + $this->_body .= $data; + } + $this->_notify($gzipped? 'gzTick': 'tick', $data); + } + } + } + + if ($hasBody) { + // Uncompress the body if needed + if ($gzipped) { + $body = $this->_decodeGzip($this->_body); + if (PEAR::isError($body)) { + return $body; + } + $this->_body = $body; + $this->_notify('gotBody', $this->_body); + } else { + $this->_notify('gotBody'); + } + } + return true; + } + + + /** + * Processes the response header + * + * @access private + * @param string HTTP header + */ + function _processHeader($header) + { + if (false === strpos($header, ':')) { + return; + } + list($headername, $headervalue) = explode(':', $header, 2); + $headername = strtolower($headername); + $headervalue = ltrim($headervalue); + + if ('set-cookie' != $headername) { + if (isset($this->_headers[$headername])) { + $this->_headers[$headername] .= ',' . $headervalue; + } else { + $this->_headers[$headername] = $headervalue; + } + } else { + $this->_parseCookie($headervalue); + } + } + + + /** + * Parse a Set-Cookie header to fill $_cookies array + * + * @access private + * @param string value of Set-Cookie header + */ + function _parseCookie($headervalue) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + // Only a name=value pair + if (!strpos($headervalue, ';')) { + $pos = strpos($headervalue, '='); + $cookie['name'] = trim(substr($headervalue, 0, $pos)); + $cookie['value'] = trim(substr($headervalue, $pos + 1)); + + // Some optional parameters are supplied + } else { + $elements = explode(';', $headervalue); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->_cookies[] = $cookie; + } + + + /** + * Read a part of response body encoded with chunked Transfer-Encoding + * + * @access private + * @return string + */ + function _readChunked() + { + // at start of the next chunk? + if (0 == $this->_chunkLength) { + $line = $this->_sock->readLine(); + if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + $this->_chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); // make this an eof() + return ''; + } + } else { + return ''; + } + } + $data = $this->_sock->read($this->_chunkLength); + $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data); + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); // Trailing CRLF + } + return $data; + } + + + /** + * Notifies all registered listeners of an event. + * + * @param string Event name + * @param mixed Additional data + * @access private + * @see HTTP_Request::_notify() + */ + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } + + + /** + * Decodes the message-body encoded by gzip + * + * The real decoding work is done by gzinflate() built-in function, this + * method only parses the header and checks data for compliance with + * RFC 1952 + * + * @access private + * @param string gzip-encoded data + * @return string decoded data + */ + function _decodeGzip($data) + { + if (HTTP_REQUEST_MBSTRING) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD); + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA); + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 1) { + if ($length - $headerLength - 2 < 8) { + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA); + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC); + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + $unpacked = @gzinflate(substr($data, $headerLength, -8), $dataSize); + if (false === $unpacked) { + return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ); + } elseif ($dataSize != strlen($unpacked)) { + return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ); + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { + return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC); + } + if (HTTP_REQUEST_MBSTRING) { + mb_internal_encoding($oldEncoding); + } + return $unpacked; + } +} // End class HTTP_Response +?> diff --git a/plugins/www/http_download_file/lib/Pear/HTTP/Request/Listener.php b/plugins/www/http_download_file/lib/Pear/HTTP/Request/Listener.php new file mode 100644 index 0000000..cc71b59 --- /dev/null +++ b/plugins/www/http_download_file/lib/Pear/HTTP/Request/Listener.php @@ -0,0 +1,106 @@ + + * @copyright 2002-2007 Richard Heyes + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Listener.php,v 1.3 2007/05/18 10:33:31 avb Exp $ + * @link http://pear.php.net/package/HTTP_Request/ + */ + +/** + * Listener for HTTP_Request and HTTP_Response objects + * + * This class implements the Observer part of a Subject-Observer + * design pattern. + * + * @category HTTP + * @package HTTP_Request + * @author Alexey Borzov + * @version Release: 1.4.2 + */ +class HTTP_Request_Listener +{ + /** + * A listener's identifier + * @var string + */ + var $_id; + + /** + * Constructor, sets the object's identifier + * + * @access public + */ + function HTTP_Request_Listener() + { + $this->_id = md5(uniqid('http_request_', 1)); + } + + + /** + * Returns the listener's identifier + * + * @access public + * @return string + */ + function getId() + { + return $this->_id; + } + + + /** + * This method is called when Listener is notified of an event + * + * @access public + * @param object an object the listener is attached to + * @param string Event name + * @param mixed Additional data + * @abstract + */ + function update(&$subject, $event, $data = null) + { + echo "Notified of event: '$event'\n"; + if (null !== $data) { + echo "Additional data: "; + var_dump($data); + } + } +} +?> diff --git a/plugins/www/http_download_file/lib/Pear/Net/Socket.php b/plugins/www/http_download_file/lib/Pear/Net/Socket.php new file mode 100644 index 0000000..73bb4dd --- /dev/null +++ b/plugins/www/http_download_file/lib/Pear/Net/Socket.php @@ -0,0 +1,592 @@ + | +// | Chuck Hagenbuch | +// +----------------------------------------------------------------------+ +// +// $Id: Socket.php,v 1.38 2008/02/15 18:24:17 chagenbu Exp $ + +require_once 'PEAR.php'; + +define('NET_SOCKET_READ', 1); +define('NET_SOCKET_WRITE', 2); +define('NET_SOCKET_ERROR', 4); + +/** + * Generalized Socket class. + * + * @version 1.1 + * @author Stig Bakken + * @author Chuck Hagenbuch + */ +class Net_Socket extends PEAR { + + /** + * Socket file pointer. + * @var resource $fp + */ + var $fp = null; + + /** + * Whether the socket is blocking. Defaults to true. + * @var boolean $blocking + */ + var $blocking = true; + + /** + * Whether the socket is persistent. Defaults to false. + * @var boolean $persistent + */ + var $persistent = false; + + /** + * The IP address to connect to. + * @var string $addr + */ + var $addr = ''; + + /** + * The port number to connect to. + * @var integer $port + */ + var $port = 0; + + /** + * Number of seconds to wait on socket connections before assuming + * there's no more data. Defaults to no timeout. + * @var integer $timeout + */ + var $timeout = false; + + /** + * Number of bytes to read at a time in readLine() and + * readAll(). Defaults to 2048. + * @var integer $lineLength + */ + var $lineLength = 2048; + + /** + * Connect to the specified port. If called when the socket is + * already connected, it disconnects and connects again. + * + * @param string $addr IP address or host name. + * @param integer $port TCP port number. + * @param boolean $persistent (optional) Whether the connection is + * persistent (kept open between requests + * by the web server). + * @param integer $timeout (optional) How long to wait for data. + * @param array $options See options for stream_context_create. + * + * @access public + * + * @return boolean | PEAR_Error True on success or a PEAR_Error on failure. + */ + function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null) + { + if (is_resource($this->fp)) { + @fclose($this->fp); + $this->fp = null; + } + + if (!$addr) { + return $this->raiseError('$addr cannot be empty'); + } elseif (strspn($addr, '.0123456789') == strlen($addr) || + strstr($addr, '/') !== false) { + $this->addr = $addr; + } else { + $this->addr = @gethostbyname($addr); + } + + $this->port = $port % 65536; + + if ($persistent !== null) { + $this->persistent = $persistent; + } + + if ($timeout !== null) { + $this->timeout = $timeout; + } + + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; + $errno = 0; + $errstr = ''; + $old_track_errors = @ini_set('track_errors', 1); + if ($options && function_exists('stream_context_create')) { + if ($this->timeout) { + $timeout = $this->timeout; + } else { + $timeout = 0; + } + $context = stream_context_create($options); + + // Since PHP 5 fsockopen doesn't allow context specification + if (function_exists('stream_socket_client')) { + $flags = $this->persistent ? STREAM_CLIENT_PERSISTENT : STREAM_CLIENT_CONNECT; + $addr = $this->addr . ':' . $this->port; + $fp = stream_socket_client($addr, $errno, $errstr, $timeout, $flags, $context); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context); + } + } else { + if ($this->timeout) { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr); + } + } + + if (!$fp) { + if ($errno == 0 && isset($php_errormsg)) { + $errstr = $php_errormsg; + } + @ini_set('track_errors', $old_track_errors); + return $this->raiseError($errstr, $errno); + } + + @ini_set('track_errors', $old_track_errors); + $this->fp = $fp; + + return $this->setBlocking($this->blocking); + } + + /** + * Disconnects from the peer, closes the socket. + * + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function disconnect() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + @fclose($this->fp); + $this->fp = null; + return true; + } + + /** + * Find out if the socket is in blocking mode. + * + * @access public + * @return boolean The current blocking mode. + */ + function isBlocking() + { + return $this->blocking; + } + + /** + * Sets whether the socket connection should be blocking or + * not. A read call to a non-blocking socket will return immediately + * if there is no data available, whereas it will block until there + * is data for blocking sockets. + * + * @param boolean $mode True for blocking sockets, false for nonblocking. + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function setBlocking($mode) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $this->blocking = $mode; + socket_set_blocking($this->fp, $this->blocking); + return true; + } + + /** + * Sets the timeout value on socket descriptor, + * expressed in the sum of seconds and microseconds + * + * @param integer $seconds Seconds. + * @param integer $microseconds Microseconds. + * @access public + * @return mixed true on success or a PEAR_Error instance otherwise + */ + function setTimeout($seconds, $microseconds) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_set_timeout($this->fp, $seconds, $microseconds); + } + + /** + * Sets the file buffering size on the stream. + * See php's stream_set_write_buffer for more information. + * + * @param integer $size Write buffer size. + * @access public + * @return mixed on success or an PEAR_Error object otherwise + */ + function setWriteBuffer($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $returned = stream_set_write_buffer($this->fp, $size); + if ($returned == 0) { + return true; + } + return $this->raiseError('Cannot set write buffer.'); + } + + /** + * Returns information about an existing socket resource. + * Currently returns four entries in the result array: + * + *

+ * timed_out (bool) - The socket timed out waiting for data
+ * blocked (bool) - The socket was blocked
+ * eof (bool) - Indicates EOF event
+ * unread_bytes (int) - Number of bytes left in the socket buffer
+ *

+ * + * @access public + * @return mixed Array containing information about existing socket resource or a PEAR_Error instance otherwise + */ + function getStatus() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_get_status($this->fp); + } + + /** + * Get a specified line of data + * + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function gets($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fgets($this->fp, $size); + } + + /** + * Read a specified amount of data. This is guaranteed to return, + * and has the added benefit of getting everything in one fread() + * chunk; if you know the size of the data you're getting + * beforehand, this is definitely the way to go. + * + * @param integer $size The number of bytes to read from the socket. + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function read($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fread($this->fp, $size); + } + + /** + * Write a specified amount of data. + * + * @param string $data Data to write. + * @param integer $blocksize Amount of data to write at once. + * NULL means all at once. + * + * @access public + * @return mixed If the socket is not connected, returns an instance of PEAR_Error + * If the write succeeds, returns the number of bytes written + * If the write fails, returns false. + */ + function write($data, $blocksize = null) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + if (is_null($blocksize) && !OS_WINDOWS) { + return @fwrite($this->fp, $data); + } else { + if (is_null($blocksize)) { + $blocksize = 1024; + } + + $pos = 0; + $size = strlen($data); + while ($pos < $size) { + $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); + if ($written === false) { + return false; + } + $pos += $written; + } + + return $pos; + } + } + + /** + * Write a line of data to the socket, followed by a trailing "\r\n". + * + * @access public + * @return mixed fputs result, or an error + */ + function writeLine($data) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return fwrite($this->fp, $data . "\r\n"); + } + + /** + * Tests for end-of-file on a socket descriptor. + * + * Also returns true if the socket is disconnected. + * + * @access public + * @return bool + */ + function eof() + { + return (!is_resource($this->fp) || feof($this->fp)); + } + + /** + * Reads a byte of data + * + * @access public + * @return 1 byte of data from the socket, or a PEAR_Error if + * not connected. + */ + function readByte() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return ord(@fread($this->fp, 1)); + } + + /** + * Reads a word of data + * + * @access public + * @return 1 word of data from the socket, or a PEAR_Error if + * not connected. + */ + function readWord() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); + } + + /** + * Reads an int of data + * + * @access public + * @return integer 1 int of data from the socket, or a PEAR_Error if + * not connected. + */ + function readInt() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + } + + /** + * Reads a zero-terminated string of data + * + * @access public + * @return string, or a PEAR_Error if + * not connected. + */ + function readString() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $string = ''; + while (($char = @fread($this->fp, 1)) != "\x00") { + $string .= $char; + } + return $string; + } + + /** + * Reads an IP Address and returns it in a dot formatted string + * + * @access public + * @return Dot formatted string, or a PEAR_Error if + * not connected. + */ + function readIPAddress() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]), + ord($buf[2]), ord($buf[3])); + } + + /** + * Read until either the end of the socket or a newline, whichever + * comes first. Strips the trailing newline from the returned data. + * + * @access public + * @return All available data up to a newline, without that + * newline, or until the end of the socket, or a PEAR_Error if + * not connected. + */ + function readLine() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $line = ''; + $timeout = time() + $this->timeout; + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { + $line .= @fgets($this->fp, $this->lineLength); + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Read until the socket closes, or until there is no more data in + * the inner PHP buffer. If the inner buffer is empty, in blocking + * mode we wait for at least 1 byte of data. Therefore, in + * blocking mode, if there is no data at all to be read, this + * function will never exit (unless the socket is closed on the + * remote end). + * + * @access public + * + * @return string All data until the socket closes, or a PEAR_Error if + * not connected. + */ + function readAll() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $data = ''; + while (!feof($this->fp)) { + $data .= @fread($this->fp, $this->lineLength); + } + return $data; + } + + /** + * Runs the equivalent of the select() system call on the socket + * with a timeout specified by tv_sec and tv_usec. + * + * @param integer $state Which of read/write/error to check for. + * @param integer $tv_sec Number of seconds for timeout. + * @param integer $tv_usec Number of microseconds for timeout. + * + * @access public + * @return False if select fails, integer describing which of read/write/error + * are ready, or PEAR_Error if not connected. + */ + function select($state, $tv_sec, $tv_usec = 0) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $read = null; + $write = null; + $except = null; + if ($state & NET_SOCKET_READ) { + $read[] = $this->fp; + } + if ($state & NET_SOCKET_WRITE) { + $write[] = $this->fp; + } + if ($state & NET_SOCKET_ERROR) { + $except[] = $this->fp; + } + if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { + return false; + } + + $result = 0; + if (count($read)) { + $result |= NET_SOCKET_READ; + } + if (count($write)) { + $result |= NET_SOCKET_WRITE; + } + if (count($except)) { + $result |= NET_SOCKET_ERROR; + } + return $result; + } + + /** + * Turns encryption on/off on a connected socket. + * + * @param bool $enabled Set this parameter to true to enable encryption + * and false to disable encryption. + * @param integer $type Type of encryption. See + * http://se.php.net/manual/en/function.stream-socket-enable-crypto.php for values. + * + * @access public + * @return false on error, true on success and 0 if there isn't enough data and the + * user should try again (non-blocking sockets only). A PEAR_Error object + * is returned if the socket is not connected + */ + function enableCrypto($enabled, $type) + { + if (version_compare(phpversion(), "5.1.0", ">=")) { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + return @stream_socket_enable_crypto($this->fp, $enabled, $type); + } else { + return $this->raiseError('Net_Socket::enableCrypto() requires php version >= 5.1.0'); + } + } + +} diff --git a/plugins/www/http_download_file/lib/Pear/Net/URL.php b/plugins/www/http_download_file/lib/Pear/Net/URL.php new file mode 100644 index 0000000..3dcfef6 --- /dev/null +++ b/plugins/www/http_download_file/lib/Pear/Net/URL.php @@ -0,0 +1,485 @@ + | +// +-----------------------------------------------------------------------+ +// +// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $ +// +// Net_URL Class + + +class Net_URL +{ + var $options = array('encode_query_keys' => false); + /** + * Full url + * @var string + */ + var $url; + + /** + * Protocol + * @var string + */ + var $protocol; + + /** + * Username + * @var string + */ + var $username; + + /** + * Password + * @var string + */ + var $password; + + /** + * Host + * @var string + */ + var $host; + + /** + * Port + * @var integer + */ + var $port; + + /** + * Path + * @var string + */ + var $path; + + /** + * Query string + * @var array + */ + var $querystring; + + /** + * Anchor + * @var string + */ + var $anchor; + + /** + * Whether to use [] + * @var bool + */ + var $useBrackets; + + /** + * PHP4 Constructor + * + * @see __construct() + */ + function Net_URL($url = null, $useBrackets = true) + { + $this->__construct($url, $useBrackets); + } + + /** + * PHP5 Constructor + * + * Parses the given url and stores the various parts + * Defaults are used in certain cases + * + * @param string $url Optional URL + * @param bool $useBrackets Whether to use square brackets when + * multiple querystrings with the same name + * exist + */ + function __construct($url = null, $useBrackets = true) + { + $this->url = $url; + $this->useBrackets = $useBrackets; + + $this->initialize(); + } + + function initialize() + { + $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + + $this->user = ''; + $this->pass = ''; + $this->host = ''; + $this->port = 80; + $this->path = ''; + $this->querystring = array(); + $this->anchor = ''; + + // Only use defaults if not an absolute URL given + if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) { + $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http'); + + /** + * Figure out host/port + */ + if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) && + preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) + { + $host = $matches[1]; + if (!empty($matches[3])) { + $port = $matches[3]; + } else { + $port = $this->getStandardPort($this->protocol); + } + } + + $this->user = ''; + $this->pass = ''; + $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost'); + $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol)); + $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/'; + $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null; + $this->anchor = ''; + } + + // Parse the url and store the various parts + if (!empty($this->url)) { + $urlinfo = parse_url($this->url); + + // Default querystring + $this->querystring = array(); + + foreach ($urlinfo as $key => $value) { + switch ($key) { + case 'scheme': + $this->protocol = $value; + $this->port = $this->getStandardPort($value); + break; + + case 'user': + case 'pass': + case 'host': + case 'port': + $this->$key = $value; + break; + + case 'path': + if ($value{0} == '/') { + $this->path = $value; + } else { + $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path); + $this->path = sprintf('%s/%s', $path, $value); + } + break; + + case 'query': + $this->querystring = $this->_parseRawQueryString($value); + break; + + case 'fragment': + $this->anchor = $value; + break; + } + } + } + } + /** + * Returns full url + * + * @return string Full url + * @access public + */ + function getURL() + { + $querystring = $this->getQueryString(); + + $this->url = $this->protocol . '://' + . $this->user . (!empty($this->pass) ? ':' : '') + . $this->pass . (!empty($this->user) ? '@' : '') + . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) + . $this->path + . (!empty($querystring) ? '?' . $querystring : '') + . (!empty($this->anchor) ? '#' . $this->anchor : ''); + + return $this->url; + } + + /** + * Adds or updates a querystring item (URL parameter). + * Automatically encodes parameters with rawurlencode() if $preencoded + * is false. + * You can pass an array to $value, it gets mapped via [] in the URL if + * $this->useBrackets is activated. + * + * @param string $name Name of item + * @param string $value Value of item + * @param bool $preencoded Whether value is urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + if ($this->getOption('encode_query_keys')) { + $name = rawurlencode($name); + } + + if ($preencoded) { + $this->querystring[$name] = $value; + } else { + $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value); + } + } + + /** + * Removes a querystring item + * + * @param string $name Name of item + * @access public + */ + function removeQueryString($name) + { + if ($this->getOption('encode_query_keys')) { + $name = rawurlencode($name); + } + + if (isset($this->querystring[$name])) { + unset($this->querystring[$name]); + } + } + + /** + * Sets the querystring to literally what you supply + * + * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc + * @access public + */ + function addRawQueryString($querystring) + { + $this->querystring = $this->_parseRawQueryString($querystring); + } + + /** + * Returns flat querystring + * + * @return string Querystring + * @access public + */ + function getQueryString() + { + if (!empty($this->querystring)) { + foreach ($this->querystring as $name => $value) { + // Encode var name + $name = rawurlencode($name); + + if (is_array($value)) { + foreach ($value as $k => $v) { + $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v); + } + } elseif (!is_null($value)) { + $querystring[] = $name . '=' . $value; + } else { + $querystring[] = $name; + } + } + $querystring = implode(ini_get('arg_separator.output'), $querystring); + } else { + $querystring = ''; + } + + return $querystring; + } + + /** + * Parses raw querystring and returns an array of it + * + * @param string $querystring The querystring to parse + * @return array An array of the querystring data + * @access private + */ + function _parseRawQuerystring($querystring) + { + $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY); + $return = array(); + + foreach ($parts as $part) { + if (strpos($part, '=') !== false) { + $value = substr($part, strpos($part, '=') + 1); + $key = substr($part, 0, strpos($part, '=')); + } else { + $value = null; + $key = $part; + } + + if (!$this->getOption('encode_query_keys')) { + $key = rawurldecode($key); + } + + if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) { + $key = $matches[1]; + $idx = $matches[2]; + + // Ensure is an array + if (empty($return[$key]) || !is_array($return[$key])) { + $return[$key] = array(); + } + + // Add data + if ($idx === '') { + $return[$key][] = $value; + } else { + $return[$key][$idx] = $value; + } + } elseif (!$this->useBrackets AND !empty($return[$key])) { + $return[$key] = (array)$return[$key]; + $return[$key][] = $value; + } else { + $return[$key] = $value; + } + } + + return $return; + } + + /** + * Resolves //, ../ and ./ from a path and returns + * the result. Eg: + * + * /foo/bar/../boo.php => /foo/boo.php + * /foo/bar/../../boo.php => /boo.php + * /foo/bar/.././/boo.php => /foo/boo.php + * + * This method can also be called statically. + * + * @param string $path URL path to resolve + * @return string The result + */ + function resolvePath($path) + { + $path = explode('/', str_replace('//', '/', $path)); + + for ($i=0; $i 1 OR ($i == 1 AND $path[0] != '') ) ) { + unset($path[$i]); + unset($path[$i-1]); + $path = array_values($path); + $i -= 2; + + } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') { + unset($path[$i]); + $path = array_values($path); + $i--; + + } else { + continue; + } + } + + return implode('/', $path); + } + + /** + * Returns the standard port number for a protocol + * + * @param string $scheme The protocol to lookup + * @return integer Port number or NULL if no scheme matches + * + * @author Philippe Jausions + */ + function getStandardPort($scheme) + { + switch (strtolower($scheme)) { + case 'http': return 80; + case 'https': return 443; + case 'ftp': return 21; + case 'imap': return 143; + case 'imaps': return 993; + case 'pop3': return 110; + case 'pop3s': return 995; + default: return null; + } + } + + /** + * Forces the URL to a particular protocol + * + * @param string $protocol Protocol to force the URL to + * @param integer $port Optional port (standard port is used by default) + */ + function setProtocol($protocol, $port = null) + { + $this->protocol = $protocol; + $this->port = is_null($port) ? $this->getStandardPort($protocol) : $port; + } + + /** + * Set an option + * + * This function set an option + * to be used thorough the script. + * + * @access public + * @param string $optionName The optionname to set + * @param string $value The value of this option. + */ + function setOption($optionName, $value) + { + if (!array_key_exists($optionName, $this->options)) { + return false; + } + + $this->options[$optionName] = $value; + $this->initialize(); + } + + /** + * Get an option + * + * This function gets an option + * from the $this->options array + * and return it's value. + * + * @access public + * @param string $opionName The name of the option to retrieve + * @see $this->options + */ + function getOption($optionName) + { + if (!isset($this->options[$optionName])) { + return false; + } + + return $this->options[$optionName]; + } + +} +?> diff --git a/plugins/www/testgen4web_simpletest/CHANGELOG b/plugins/www/testgen4web_simpletest/CHANGELOG new file mode 100644 index 0000000..86db122 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/CHANGELOG @@ -0,0 +1,30 @@ +1.2.6. (2008.05.08) +Updated SimpleTest library to version 1.0.1 + +1.2.5 (2007.12.06) +----------------- +Added timeout threshold for navigation test. +The plugin may be configured to return as output either the detailed test report or only the navigation time test. +The archive result functionality is now enabled. + +1.2.4 (2007.11.19) +------------------ +Use init.inc.php + +1.2.3 (2007.10.11) +------------------ +Added the capability to use http proxy for tests + +1.2.2 (2007.09.25) +------------------ +Identity is now an optional field +Update simpletest libs +The name of the package for the plugin is now lowercase + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support diff --git a/plugins/www/testgen4web_simpletest/COPYRIGHT b/plugins/www/testgen4web_simpletest/COPYRIGHT new file mode 100644 index 0000000..e087645 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/COPYRIGHT @@ -0,0 +1,30 @@ +Ortro - An easy way to make scheduling and system/application monitoring +========================================================================= + +Copyright (C) 2006 and following years, Luca Corbo + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +This plugin for Ortro include works distributed under the following copyright notices: + +Simpletest +========== +Copyright: http://simpletest.sourceforge.net/projects/simpletest/ +License: GPL + +TestGen4Web +=========== +Copyright: 2004-2006 SpikeSource, Inc. +License: Open Software License v2.1 (see: http://www.spikesource.com/license.html) \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/LICENSE b/plugins/www/testgen4web_simpletest/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/www/testgen4web_simpletest/configure.php b/plugins/www/testgen4web_simpletest/configure.php new file mode 100644 index 0000000..53f214f --- /dev/null +++ b/plugins/www/testgen4web_simpletest/configure.php @@ -0,0 +1,97 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_actions['testgen4web_simpletest'][0]['description'] = PLUGIN_ARCHIVE_RESULTS; +$plugin_actions['testgen4web_simpletest'][0]['action'] = 'plugin'; +$plugin_actions['testgen4web_simpletest'][0]['file'] = 'display_archive_results'; +$plugin_actions['testgen4web_simpletest'][0]['image'] = 'archive.png'; + +$plugin_field['testgen4web_simpletest'][0]['version'] = '1.2.6'; +$plugin_field['testgen4web_simpletest'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['testgen4web_simpletest'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['testgen4web_simpletest'][0]['authors'][1] = 'Danilo Alfano '; +$plugin_field['testgen4web_simpletest'][0]['description'] = PLUGIN_TEST4WEB_DESCRIPTION; +$plugin_field['testgen4web_simpletest'][0]['title'] = PLUGIN_TEST4WEB_TITLE; + +$plugin_field['testgen4web_simpletest'][1]['type'] = 'text'; +$plugin_field['testgen4web_simpletest'][1]['name'] = 'testgen4web_simpletest_identity'; +$plugin_field['testgen4web_simpletest'][1]['value'] = ''; +$plugin_field['testgen4web_simpletest'][1]['attributes'] = 'disabled readonly'; +$plugin_field['testgen4web_simpletest'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['testgen4web_simpletest'][1]['num_rules'] = '0'; + +$plugin_field['testgen4web_simpletest'][2]['type'] = 'text'; +$plugin_field['testgen4web_simpletest'][2]['name'] = 'testgen4web_simpletest_proxy_host'; +$plugin_field['testgen4web_simpletest'][2]['value'] = ''; +$plugin_field['testgen4web_simpletest'][2]['attributes'] = 'disabled size=50'; +$plugin_field['testgen4web_simpletest'][2]['description'] = PLUGIN_TEST4WEB_PROXY_HOST_DESCRIPTION; +$plugin_field['testgen4web_simpletest'][2]['num_rules'] = '0'; + +$plugin_field['testgen4web_simpletest'][3]['type'] = 'text'; +$plugin_field['testgen4web_simpletest'][3]['name'] = 'testgen4web_simpletest_proxy_user'; +$plugin_field['testgen4web_simpletest'][3]['value'] = ''; +$plugin_field['testgen4web_simpletest'][3]['attributes'] = 'disabled size=30'; +$plugin_field['testgen4web_simpletest'][3]['description'] = PLUGIN_TEST4WEB_PROXY_USER_DESCRIPTION; +$plugin_field['testgen4web_simpletest'][3]['num_rules'] = '0'; + +$plugin_field['testgen4web_simpletest'][4]['type'] = 'password'; +$plugin_field['testgen4web_simpletest'][4]['name'] = 'testgen4web_simpletest_proxy_password'; +$plugin_field['testgen4web_simpletest'][4]['value'] = ''; +$plugin_field['testgen4web_simpletest'][4]['attributes'] ='disabled size=30'; +$plugin_field['testgen4web_simpletest'][4]['description'] = PLUGIN_TEST4WEB_PROXY_PASSWORD_DESCRIPTION; +$plugin_field['testgen4web_simpletest'][4]['num_rules'] = '0'; + +$plugin_field['testgen4web_simpletest'][5]['type'] = 'textarea'; +$plugin_field['testgen4web_simpletest'][5]['name'] = 'testgen4web_simpletest_input_script'; +$plugin_field['testgen4web_simpletest'][5]['value'] = ''; +$plugin_field['testgen4web_simpletest'][5]['attributes'] = 'disabled rows=50 cols=80'; +$plugin_field['testgen4web_simpletest'][5]['description'] = PLUGIN_TEST4WEB_XML_DESCRIPTION; +$plugin_field['testgen4web_simpletest'][5]['num_rules'] = '1'; +$plugin_field['testgen4web_simpletest'][5]['rule_msg'][0] = PLUGIN_TEST4WEB_RULE_5_0; +$plugin_field['testgen4web_simpletest'][5]['rule_type'][0] = 'required'; +$plugin_field['testgen4web_simpletest'][5]['rule_attribute'][0] = ''; + +$plugin_field['testgen4web_simpletest'][6]['type'] = 'select'; +$plugin_field['testgen4web_simpletest'][6]['name'] = 'testgen4web_simpletest_type'; +$plugin_field['testgen4web_simpletest'][6]['value'] = array('details' => PLUGIN_TEST4WEB_DETAILS, + 'time' => PLUGIN_TEST4WEB_ONLY_TIME); +$plugin_field['testgen4web_simpletest'][6]['attributes'] = ''; +$plugin_field['testgen4web_simpletest'][6]['description'] = PLUGIN_TEST4WEB_TYPE; +$plugin_field['testgen4web_simpletest'][6]['num_rules'] = '0'; + +$plugin_field['testgen4web_simpletest'][7]['type'] = 'text'; +$plugin_field['testgen4web_simpletest'][7]['name'] = 'testgen4web_simpletest_threshold'; +$plugin_field['testgen4web_simpletest'][7]['value'] = '0'; +$plugin_field['testgen4web_simpletest'][7]['attributes'] = 'disabled'; +$plugin_field['testgen4web_simpletest'][7]['description'] = PLUGIN_TEST4WEB_THRESHOLD_DESCRIPTION; +$plugin_field['testgen4web_simpletest'][7]['num_rules'] = '2'; +$plugin_field['testgen4web_simpletest'][7]['rule_msg'][0] = PLUGIN_TEST4WEB_RULE_7_0; +$plugin_field['testgen4web_simpletest'][7]['rule_type'][0] = 'required'; +$plugin_field['testgen4web_simpletest'][7]['rule_attribute'][0] = ''; +$plugin_field['testgen4web_simpletest'][7]['rule_msg'][1] = PLUGIN_TEST4WEB_RULE_7_1; +$plugin_field['testgen4web_simpletest'][7]['rule_type'][1] = 'numeric'; +$plugin_field['testgen4web_simpletest'][7]['rule_attribute'][1] = ''; + +$plugin_field['testgen4web_simpletest'][8]['type'] = 'text'; +$plugin_field['testgen4web_simpletest'][8]['name'] = 'testgen4web_simpletest_retention'; +$plugin_field['testgen4web_simpletest'][8]['value'] = ''; +$plugin_field['testgen4web_simpletest'][8]['attributes'] = 'disabled'; +$plugin_field['testgen4web_simpletest'][8]['description'] = PLUGIN_RETENTION; +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/core.php b/plugins/www/testgen4web_simpletest/core.php new file mode 100644 index 0000000..e43623a --- /dev/null +++ b/plugins/www/testgen4web_simpletest/core.php @@ -0,0 +1,180 @@ + + * @author Danilo Alfano + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +//---- Start plugin code ----- + +try { + + $loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); + $loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + + //Get the params required by plugin from argv + $user = $job_infos['identity']['username']; + $pwd = $job_infos['identity']['password']; + + $input_script = $parameters['testgen4web_simpletest_input_script']; + $proxy_host = $parameters['testgen4web_simpletest_proxy_host']; + $proxy_user = $parameters['testgen4web_simpletest_proxy_user']; + $proxy_password = $parameters['testgen4web_simpletest_proxy_password']; + + $proxy_string = ''; + + if (isset($proxy_host) && $proxy_host != '') { + $proxy_string = ' --proxy-host=\'' . $proxy_host . + '\' --proxy-user=\'' . $proxy_user . + '\' --proxy-password=\'' . $proxy_password . '\''; + } + + $path = dirname($argv[0]); + $tempFile = 'Test' . $id_job . time() . rand(); + $tempDir = $path . DIRECTORY_SEPARATOR; + + //Replace username e password in the xml code + $input_script = str_replace('${USERNAME}', $user, $input_script); + $input_script = str_replace('${PASSWORD}', $pwd, $input_script); + + //Generate the t4g input file + $fh = fopen($tempDir . $tempFile, 'w+'); + fwrite($fh, $input_script); + + fclose($fh); + chmod($tempDir . $tempFile, 0600); + + //Translate the t4g code in simpletest code + $cmdLine = 'php -d include_path=' . get_include_path() . ' ' . + $current_path . + '/lib/php-simpletest-translator/PHPGenerator.php --input-file=' . + $tempDir . $tempFile . + ' --output-dir=' . $current_path . $proxy_string . ' 2>&1'; + + exec($cmdLine, $stdout, $exit_code); + + //remove the t4g + @unlink($tempDir . $tempFile); + unset($stdout); + unset($exit_code); + + $cmdLine = 'php ' . $current_path . DS . $tempFile . '.php PHP_SIMPLETEST_HOME=' . + $current_path . '/lib 2>&1'; + + // Get timestamp + $start_navigation_time = time(); + //execute the test + exec($cmdLine, $stdout, $exit_code); + + // stop timestamp + $end_navigation_time = time(); + // test duration + $elapsed_time = $end_navigation_time - $start_navigation_time; + + // Output details + if ($parameters['testgen4web_simpletest_type'] == 'details') { + array_shift($stdout); + array_push($stdout, 'Execution Time for All Tests [s]: ' . + $elapsed_time); + $attachments['txt'] = implode("\n", $stdout); + $attachments['html'] = implode("
", $stdout); + } else { + $attachments['txt'] = $elapsed_time; + } + + @unlink($tempDir . $tempFile . '.php'); + + //Define threshold for timeout + if (isset($parameters['testgen4web_simpletest_threshold']) && + $parameters['testgen4web_simpletest_threshold']!='0') { + $threshold = $parameters['testgen4web_simpletest_threshold']; + } else { + $threshold = PHP_INT_MAX ; + } + + if ($exit_code != '0') { + // the test not finished. + $loggerPlugin->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . $attachments['txt']); + $result = '0'; + } else { + // test finished , navigation has no failures. + if ((strpos($attachments['txt'], 'FAILURES!!!') === false)) { + if ($elapsed_time < $threshold) { + $result = '1'; + $loggerPlugin->trace('INFO', 'id_job=' . + $id_job . + ' -> Test OK'); + } else { + $result = '0'; + $loggerPlugin->trace('INFO', 'id_job=' . + $id_job . + ' -> Test KO, timeout'); + } + } else { + // test finished , navigation has errors + $loggerPlugin->trace('ERROR', 'exit_code=' . + $exit_code . "\n" . + "Message:\n" . + $attachments['txt']); + $result = '0'; + } + } + + $msg_exec = $attachments['txt']; + + //---- Archive job result ---- + $retention_data['archive_mode'] = 'DB'; + $retention_data['retention'] = $parameters['testgen4web_simpletest_retention']; + + //---- End plugin code ----- + +} catch (Exception $e) { + $cronUtil->traceError($plugin_name, $e); + $msg_exec = "Plugin exception occourred: " . $e->getMessage() . "\n" . + "Please contact system administrator"; + +} + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); + +if ($retention_data['retention'] > 0 && is_numeric($retention_data['retention'])) { + //apply retention policy + $cronUtil->archiveJobResult($id_job, $retention_data); +} +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Config.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Config.php new file mode 100644 index 0000000..52db29f --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Config.php @@ -0,0 +1,33 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + if(!defined('__TESTGEN4WEB_ROOT')) { + define('__TESTGEN4WEB_ROOT', dirname(__FILE__)); + } + + require_once __TESTGEN4WEB_ROOT . '/Util/Logger.php'; + + $logger =& new TestGen4Web_Util_Logger(); + $logger->setLevel("LOG_DEBUG"); + +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/Generator.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/Generator.php new file mode 100644 index 0000000..db08179 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/Generator.php @@ -0,0 +1,196 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + if(!defined('__TESTGEN4WEB_ROOT')) { + define('__TESTGEN4WEB_ROOT', dirname(dirname(__FILE__))); + } + + require_once __TESTGEN4WEB_ROOT . '/Config.php'; + require_once __TESTGEN4WEB_ROOT . '/Util/Util.php'; + require_once __TESTGEN4WEB_ROOT . '/Parser/ActionParser.php'; + + /** + * Code Generator base class. + * + * @category + * @package TestGen4Web_Generator + * @author Nimish Pachapurkar + * @version $Revision: $ + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @link + */ + abstract class TestGen4Web_Generator_Generator { +/*{{{ Members */ + + protected $_parser; + protected $_filepath; + protected $_actions; + protected $_pattern; + protected $_genClassName; + protected $_genString; + protected $_genFile; + protected $_targetDir; + protected $_logger; + +/*}}}*/ +/*{{{ public function __construct() */ + + public function __construct($generatorType="simpletest") { + $this->_parser =& new TestGen4Web_Parser_ActionParser(); + // Matches INPUT[@ID="user"] + // Matches INPUT[@TYPE="password" and @NAME="pass"] + $this->_pattern = '/([^\[]*)\[@([^=]*)="([^"]*)"( and @([^=]*)="([^"]*)")?\]/'; + + global $logger; + $this->_logger =& $logger; + } + +/*}}}*/ +/*{{{ public function setFilePath() */ + + public function setFilePath($filepath) { + $this->_filepath = $filepath; + $this->_parser->setInputFile($this->_filepath); + $this->_genClassName = $this->getGeneratedClassName(); + } + + public function setProxyConnection($proxyHost, $proxyUser, $proxyPassword) { + $this->_proxyHost = $proxyHost; + $this->_proxyUser = $proxyUser; + $this->_proxyPassword = $proxyPassword ; + } + +/*}}}*/ +/*{{{ public function generate() */ + + public function generate() { + $this->_parser->parse(); + $doc =& $this->_parser->getDocumentArray(); + $this->_actions =& $doc['TG4W']; + $this->makeTargetDir(); + } + +/*}}}*/ +/*{{{ public function getElementFromXpath() */ + public function getElementFromXpath($xpath) { + if(empty($xpath)) { + return false; + } + + $element = array(); + + $pos = strrpos($xpath, "/"); + if($pos !== false && $pos < strlen($xpath)) { + $lastPart = substr($xpath, $pos+1); + } + else { + $lastPart = $xpath; + } + $matches = array(); + preg_match($this->_pattern, $lastPart, $matches); + + if(is_array($matches) && count($matches) > 0) { + // Remove unwanted matches + if(isset($matches[0])) { + array_splice($matches, 0, 1); + if(isset($matches[3])) { + array_splice($matches, 3, 1); + } + } + $this->_logger->debug("Array matches: " . print_r($matches, true)); + for($i = 0; $i < count($matches); $i++) { + if($i == 0) { + // This should be the HTML tag + $element['TAG'] = $matches[$i]; + } + else if ($i%2 != 0) { + // Rest all are name value pairs + if(isset($matches[$i+1])) { + $element[$matches[$i]] = $matches[$i+1]; + } + else { + $element[$matches[$i]] = false; + } + } + } + } + else { + $element['TAG'] = "*"; + $element['*'] = false; + } + return $element; + } + +/*}}}*/ +/*{{{ protected function getGeneratedClassName() */ + + protected function getGeneratedClassName($filepath) { + $genClassName = trim(basename($this->_filepath, '.xml')); + if(!empty($genClassName)) { + $genClassName = str_replace('_', '', $genClassName); + $genClassName = str_replace('-', '', $genClassName); + $genClassName = str_replace('.', '', $genClassName); + $genClassName = str_replace(' ', '', $genClassName); + $genClassName = str_replace('\\', '', $genClassName); + $firstLetter = substr($genClassName, 0, 1); + if(is_numeric($firstLetter)) { + $genClassName = "NaN_" . $genClassName; + } + } + else { + $genClassName = 'MyWebTest'; + } + + return ucfirst($genClassName); + } + +/*}}}*/ +/*{{{ protected function makeTargetDir() */ + + protected function makeTargetDir() { + global $util; + if(empty($this->_targetDir)) { + $this->_targetDir = "testgen"; + } + return $util->makeDirRecursive($this->_targetDir); + } + +/*}}}*/ +/*{{{ Getters and Setters */ + + public function getTargetDir() { + return $this->_targetDir; + } + + public function setTargetDir($targetDir) { + $this->_targetDir = $targetDir; + } + + public function getGeneratedFileName() { + return $this->_genFile; + } + +/*}}}*/ + } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestActions.inc.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestActions.inc.php new file mode 100644 index 0000000..ea41584 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestActions.inc.php @@ -0,0 +1,185 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + $SIMPLETEST_ACTIONS = array( + "wait-for-ms" => array( + "*" => array( + "*" => array( + "function" => "sleep", + "params" => 1 + ) + ) + ), + "goto" => array( + "window.location" => array( + "*" => array( + "function" => "get", + "params" => 1 + ) + ), + "*" => array( + "*" => array( + "function" => "get", + "params" => 1 + ) + ) + ), + "verify-link-href" => array( + // No way to verify link href as of now + // just verify label + "A" => array( + "CDATA" => array( + "function" => "assertLink", + "params" => 1 + ), + "ID" => array( + "function" => "assertLinkById", + "params" => 1 + ) + ) + ), + "verify-link-text" => array( + "A" => array( + "CDATA" => array( + "function" => "assertLink", + "params" => 1 + ), + "ID" => array( + "function" => "assertLinkById", + "params" => 1 + ) + ) + ), + "click" => array( + "A" => array( + "CDATA" => array( + "function" => "clickLink", + "params" => 1 + ), + "ID" => array( + "function" => "clickLinkById", + "params" => 1 + ) + ), + "INPUT" => array( + "VALUE" => array( + "function" => "click", + "params" => 1 + ), + "ID" => array( + "function" => "setFieldById", + "params" => 2 + ), + "NAME" => array( + "function" => "setFieldByName", + "params" => 2 + ) + ) + ), + "verify-title" => array( + "*" => array( + "*" => array( + "function" => "assertTitle", + "params" => 1 + ) + ) + ), + "fill" => array( + "INPUT" => array( + "ID" => array( + "function" => "setFieldById", + "params" => 2 + ), + "NAME" => array( + "function" => "setFieldByName", + "params" => 2 + ), + "VALUE" => array( + "function" => "setField", + "params" => 2 + ) + ), + "TEXTAREA" => array( + "ID" => array( + "function" => "setFieldById", + "params" => 2 + ), + "NAME" => array( + "function" => "setFieldByName", + "params" => 2 + ) + ) + ), + "select" => array( + "SELECT" => array( + "ID" => array( + "function" => "setFieldById", + "params" => 2 + ), + "NAME" => array( + "function" => "setFieldByName", + "params" => 2 + ) + ) + ), + "check" => array( + "INPUT" => array( + "NAME" => array( + "function" => "setFieldByName", + "params" => 2 + ), + "ID" => array( + "function" => "setFieldById", + "params" => 2 + ), + "VALUE" => array( + "function" => "setField", + "params" => 2 + ) + ) + ), + "verify-button-value" => array( + "INPUT" => array( + "VALUE" => array( + "function" => "assertField", + "params" => 1 + ) + ) + ), + "assert-text-exists" => array( + "*" => array( + "*" => array( + "function" => "assertText", + "params" => 1 + ) + ) + ), + "assert-text-not-exists" => array( + "*" => array( + "*" => array( + "function" => "assertNoText", + "params" => 1 + ) + ) + ) + ); +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestGenerator.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestGenerator.php new file mode 100644 index 0000000..8ecade1 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/SimpleTestGenerator.php @@ -0,0 +1,227 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + if(!defined('__TESTGEN4WEB_ROOT')) { + define('__TESTGEN4WEB_ROOT', dirname(dirname(dirname(__FILE__)))); + } + + require_once __TESTGEN4WEB_ROOT . '/Generator/Generator.php'; + require_once __TESTGEN4WEB_ROOT . '/Generator/SimpleTest/SimpleTestActions.inc.php'; + + class TestGen4Web_Generator_SimpleTest_SimpleTestGenerator extends TestGen4Web_Generator_Generator { + /*{{{ Members */ + protected $_stub; + protected $_include; + protected $_functions; + + /*}}}*/ + /*{{{ public function __construct() */ + + public function __construct() { + parent::__construct(); + $this->_stub = __TESTGEN4WEB_ROOT . "/Generator/SimpleTest/Stub/MyWebTest.php"; + $this->_include = __TESTGEN4WEB_ROOT . "/Generator/SimpleTest/Stub/simpletest.inc.php"; + $this->initializeFunctions(); + } + + /*}}}*/ + /*{{{ public function generate() */ + + public function generate() { + parent::generate(); + + $this->processSimpleTest(); + } + + /*}}}*/ + /*{{{ protected function initializeFunctions() */ + + protected function initializeFunctions() { + global $SIMPLETEST_ACTIONS; + $this->_functions =& $SIMPLETEST_ACTIONS; + } + + /*}}}*/ + /*{{{ protected function getFunctionString() */ + + protected function getFunctionString( + $action, &$element, $param2=false + ) { + $param1 = false; + if(is_array($element)) { + foreach($element as $key => $value) { + switch($key) { + case 'TAG': + $tag = $value; + break; + + //only one of these + case 'CDATA': + // Remove second param + $param2 = false; + + case 'NAME': + case 'VALUE': + case 'ID': + case '*': + $name = $key; + $param1 = $value; + break; + + default: + $name = false; + } + } + } + $this->_logger->debug("[Action: " . $action . "] [Tag: " . $tag . "] [Name: " . $name . "] [Param1: " . $param1 . "]", __FILE__, __LINE__); + + $functionCall = ""; + if(isset($this->_functions[$action])) { + $curAction =& $this->_functions[$action]; + if($action == 'wait-for-ms') { + $functionCall .= $curAction['*']['*']['function'] . '(' . $param2 / 1000 . "); \n"; + } elseif(isset($curAction[$tag])) { + $curTag =& $curAction[$tag]; + if($name && isset($curTag[$name])) { + if($action == 'wait-for-ms') { + $functionCall .= $curTag[$name]['function'] . '('; + } else { + $functionCall .= '$this->' . $curTag[$name]['function'] . '('; + } + if($curTag[$name]['params'] == 1) { + // if only one parameter is allowed + if(!empty($param1)) { + // ... and first param is set + // ignore the second param + $param2 = false; + } + } + // Assign params + if(!empty($param1)) { + $functionCall .= '"' . $param1 . '"'; + } + if(!empty($param1) && !empty($param2)) { + $functionCall .= ', '; + } + if(!empty($param2)) { + if($action == 'wait-for-ms') { + $functionCall .= $param2 / 1000; + } else { + $functionCall .= '"' . $param2 . '"'; + } + } + $functionCall .= ');' . "\n"; + } + } + } + return $functionCall; + } + + /*}}}*/ + /*{{{ protected function processSimpleTest() */ + + protected function processSimpleTest() { + if(empty($this->_actions)) { + $this->_logger->warn("No actions to generate", + __FILE__, __LINE__); + return false; + } + + $this->_genFile = $this->_targetDir . DIRECTORY_SEPARATOR . $this->_genClassName . ".php"; + + copy($this->_stub, $this->_genFile); + copy($this->_include, $this->_targetDir . DIRECTORY_SEPARATOR . basename($this->_include)); + $this->_genString = file_get_contents($this->_genFile); + $this->processActions(); + } + + /*}}}*/ + /*{{{ protected function processActions() */ + + protected function processActions() { + + $code = array(); + + for($i = 0; $i < count($this->_actions['ACTIONS']); $i++) { + $action =& $this->_actions['ACTIONS'][$i]; + $this->_logger->debug("Action is: " . print_r($action, true), + __FILE__, __LINE__); + $action['TYPE'] = strtolower($action['__ATTRIBUTES__']['TYPE']); + + $element =& $this->getElementFromXpath($action['XPATH']); + $this->_logger->debug("Element: " . print_r($element, true), + __FILE__, __LINE__); + $code[] = $this->getFunctionString( + $action['TYPE'], $element, $action['VALUE'] + ); + $this->_logger->debug("Code: " . $code[count($code)-1], + __FILE__, __LINE__); + } + $this->writeFile($code); + } + + /*}}}*/ + /*{{{ protected function writeFile() */ + + protected function writeFile(&$code) { + $codeStr = ""; + for($i = 0; $i < count($code); $i++) { + if(!empty($code[$i])) { + $codeStr .= "\t\t\t" . $code[$i]; + } + } + + // Check if test is driven throught e proxy connection + if (isset($this->_proxyHost)) { + $proxyCode = "\t\t\t" . + '$this->useProxy(\'' . + $this->_proxyHost . '\',\'' . + $this->_proxyUser . '\',\'' . + $this->_proxyPassword . '\');'; + } + // set an empty string to replace + else $proxyCode=""; + + // Replace the code in template + $this->_genString = str_replace('//%%PROXY%%//' , $proxyCode , $this->_genString); + + $this->_genString = str_replace('%%CLASS_NAME%%', $this->_genClassName, $this->_genString); + $this->_genString = str_replace('//%%CODE%%//', $codeStr, $this->_genString); + file_put_contents($this->_genFile, $this->_genString); + } + } + + /*}}}*/ + /*{{{ MAIN */ + + // __MAIN__ + if(is_array($argv) && in_array('__main__', $argv) && strpos($argv[0], basename(__FILE__)) !== false) { + //$file = "/opt/npac/svn-root/views/npac/testgen4web/recorder/samples/logintest4.xml"; + $file = "/opt/npac/svn-root/views/npac/testgen4web/recorder/samples/sugar3.xml"; + $generator =& new TestGen4Web_Generator_SimpleTest_SimpleTestGenerator(); + $generator->setFilePath($file); + $generator->generate(); + } + + /*}}}*/ +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/MyWebTest.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/MyWebTest.php new file mode 100644 index 0000000..3ca553e --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/MyWebTest.php @@ -0,0 +1,54 @@ +WebTestCase(); + } + + // function + function testEverything() { +//%%PROXY%%// + +//%%CODE%%// + } + + } + + // __main__ + // Remove the following section if you are including this class + // as part of a group test elsewhere. + + if(is_array($argv) && strpos($argv[0], basename(__FILE__)) !== false) { + $testsuite = &new GroupTest("TestGen4Web Generated Web Test Suite"); + $testsuite->addTestClass('%%CLASS_NAME%%'); + $testsuite->run(new TextReporter()); + } + +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/simpletest.inc.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/simpletest.inc.php new file mode 100644 index 0000000..fc03d90 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Generator/SimpleTest/Stub/simpletest.inc.php @@ -0,0 +1,47 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ +?> + PHP_SIMPLETEST_HOME=/path/to/simpletest/home'\n"; + die($msg); + } + } + error_log("PHP_SIMPLETEST_HOME=" . $PHP_SIMPLETEST_HOME); + $include_path = get_include_path(); + set_include_path($PHP_SIMPLETEST_HOME. PATH_SEPARATOR . $include_path); + define('__PHP_SIMPLETEST_HOME', $PHP_SIMPLETEST_HOME); + echo $PHP_SIMPLETEST_REPORT_PATH; +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/PHPGenerator.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/PHPGenerator.php new file mode 100644 index 0000000..cfe4291 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/PHPGenerator.php @@ -0,0 +1,120 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + if(!defined('__TESTGEN4WEB_ROOT')) { + define('__TESTGEN4WEB_ROOT', dirname(__FILE__)); + } + + require_once __TESTGEN4WEB_ROOT . '/Config.php'; + + function help() { + echo "Usage: php PHPGenerator.php [options]\n"; + echo " where options are: \n"; + echo " --input-file= Input XML recording.\n"; + echo " [--test-type=] Type of test suite to be generated (defaults to 'simpletest')\n"; + echo " [--output-dir=] Output directory where generated source code is placed.\n"; + echo " [--help] Print this message and exit.\n"; + echo " \n"; + echo " Proxy settings: If you are behind a proxy and no connect directly to internet\n"; + echo " you have to specify these parameters\n"; + echo " [--proxy-host=] Proxy host to connect\n"; + echo " [--proxy-user=] User used to autenthicate if needed\n"; + echo " [--proxy-password=] User password to autenthicate.\n"; + echo "\n"; + } + + function getTestGeneratorClass($testtype) { + $testtype = strtolower($testtype); + switch($testtype) { + case "simpletest": + return "/Generator/SimpleTest/SimpleTestGenerator.php"; + + default: + return false; + } + } + + $options = array(); + + for($ii=1; $ii < $argc; $ii++) { + if(strpos($argv[$ii], "--input-file=") === 0) { + parse_str($argv[$ii], $option); + $options['--input-file'] = $option['--input-file']; + } + else if(strpos($argv[$ii], "--test-type=") === 0) { + parse_str($argv[$ii], $option); + $options['--test-type'] = $option['--test-type']; + } + else if(strpos($argv[$ii], "--output-dir=") === 0) { + parse_str($argv[$ii], $option); + $options['--output-dir'] = $option['--output-dir']; + } + else if(strpos($argv[$ii], "--proxy-host=") === 0) { + parse_str($argv[$ii], $option); + $options['--proxy-host'] = $option['--proxy-host']; + } + else if(strpos($argv[$ii], "--proxy-user=") === 0) { + parse_str($argv[$ii], $option); + $options['--proxy-user'] = $option['--proxy-user']; + } + else if(strpos($argv[$ii], "--proxy-password=") === 0) { + parse_str($argv[$ii], $option); + $options['--proxy-password'] = $option['--proxy-password']; + } + else if(strpos($argv[$ii], "--help") === 0) { + help(); + exit(0); + } + } + + $logger->debug(print_r($options, true)); + $options['--input-file'] = realpath($options['--input-file']); + if(empty($options['--input-file'])) { + die("Input file must be specified."); + } + else if(!is_readable($options['--input-file'])) { + die("Cannot read input file: " . $options['--input-file'] . "\n"); + } + else if(empty($options['--test-type'])) { + $options['--test-type'] = "simpletest"; + } + + $logger->info("Parsing recording: " . $options['--input-file']); + + $testClass = getTestGeneratorClass($options['--test-type']); + if(empty($testClass)) { + die("Unknown test type: " . $options['--test-type'] . "\n"); + } + else { + require_once __TESTGEN4WEB_ROOT . $testClass; + } + + $generator =& new TestGen4Web_Generator_SimpleTest_SimpleTestGenerator(); + $generator->setFilePath($options['--input-file']); + $generator->setTargetDir($options['--output-dir']); + $generator->setProxyConnection($options['--proxy-host'], $options['--proxy-user'], $options['--proxy-password']); + $generator->generate(); + + $logger->info("Test Code generated in: " + . realpath($generator->getGeneratedFileName())); +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/ActionParser.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/ActionParser.php new file mode 100644 index 0000000..3776262 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/ActionParser.php @@ -0,0 +1,81 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + if(!defined('__TESTGEN4WEB_ROOT')) { + define('__TESTGEN4WEB_ROOT', dirname(dirname(__FILE__))); + } + + require_once __TESTGEN4WEB_ROOT . '/Parser/XMLParser.php'; + + class TestGen4Web_Parser_ActionParser extends TestGen4Web_Parser_XMLParser { + + protected $_lastActionId; + protected $_lastFilePath; + + public function __constructor() { + parent::__constructor(); + $this->_docroot = array(); + } + + public function startHandler($xp, $name, $attrs) { + parent::startHandler(&$xp, &$name, &$attrs); + switch($name) { + case "TG4W": + // Get the metadata + $this->_docroot['TG4W'][ATTRIBUTES] =& $this->handleAttrTag($name, $attrs); + break; + + case "ACTION": + $this->_docroot['TG4W']['ACTIONS'][] = array(); + $this->_lastActionId = count($this->_docroot['TG4W']['ACTIONS']) - 1; + $this->_docroot['TG4W']['ACTIONS'][$this->_lastActionId][ATTRIBUTES] =& $this->handleAttrTag($name, $attrs); + break; + } + } + + public function endHandler($xp, $name) { + switch($name) { + case "XPATH": + $this->_docroot['TG4W']['ACTIONS'][$this->_lastActionId]['XPATH'] = trim($this->getCData()); + break; + + case "VALUE": + $this->_docroot['TG4W']['ACTIONS'][$this->_lastActionId]['VALUE'] = trim($this->getCData()); + break; + } + parent::endHandler(&$xp, &$name, &$attrs); + } + } + + // __MAIN__ + if(is_array($argv) && in_array('__main__', $argv) && strpos($argv[0], basename(__FILE__)) !== false) { + $file = "/opt/npac/svn-root/views/npac/testgen4web/recorder/samples/logintest4.xml"; + $parser =& new TestGen4Web_ActionParser(); + if(is_readable($file)) { + $parser->setInputFile($file); + $parser->parse(); + print "After parsing\n"; + print_r($parser->getDocumentArray()); + } + } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/XMLParser.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/XMLParser.php new file mode 100644 index 0000000..6d0879a --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Parser/XMLParser.php @@ -0,0 +1,190 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + if(!defined('__TESTGEN4WEB_ROOT')) { + define('__TESTGEN4WEB_ROOT', dirname(dirname(__FILE__))); + } + + require_once 'XML/Parser.php'; + require_once __TESTGEN4WEB_ROOT . '/Config.php'; + + if(!defined("ATTRIBUTES")) { + define("ATTRIBUTES", "__ATTRIBUTES__"); + } + + /** + * An XML parser that extends the functionality of PEAR XML_Parser + * module. + * + * @author Nimish Pachapurkar + * @version $Revision: $ + * @package TestGen4Web_Parser + */ + class TestGen4Web_Parser_XMLParser extends XML_Parser { + /*{{{ Members */ + + protected $openTags; + protected $_docroot; + protected $_logger; + + /*}}}*/ + /*{{{ Constructor*/ + + /** + * Constructor + * @access public + */ + public function __contructor() { + global $logger; + parent::XML_Parser(); + $this->_logger =& $logger; + } + + /*}}}*/ + /*{{{ public function handleAttrTag() */ + + /** + * Function that handles an element with attributes. + * + * @param $name Name of the element + * @param $attrs Attributes array (name, value pairs) + * @return Array An element + * @access public + */ + protected function handleAttrTag($name, $attrs) { + $tag = array(); + foreach($attrs as $attr_name => $value) { + $tag[$attr_name] = $value; + } + return $tag; + } + + /*}}}*/ + /*{{{ public function startHandler() */ + + /** + * Function to handle start of an element + * + * @param $xp XMLParser handle + * @param $name Element name + * @param $attributes Attribute array + * @access public + */ + public function startHandler($xp, $name, $attributes) { + $this->openTags[] = $name; + } + + /*}}}*/ + /*{{{ public function endHandler()*/ + + /** + * Function to handle end of an element + * + * @param $xp XML_Parser handle + * @param $name Name of the element + * @access public + */ + public function endHandler($xp, $name) { + // Handle error tags + $lastTag = $this->getLastOpenTag($name); + switch($name) { + case "MESSAGE": + if($lastTag == "ERROR") { + $this->_docroot["ERROR"]["MESSAGE"] = $this->getCData(); + } + break; + } + // Empty CData + $this->lastCData = ""; + + // Close tag + if($this->openTags[count($this->openTags)-1] == $name) { + array_pop($this->openTags); + } + } + + /*}}}*/ + /*{{{ public function cdataHandler() */ + + /** + * Function to handle character data + * + * @param $xp XMLParser handle + * @param $cdata Character data + * @access public + */ + public function cdataHandler($xp, $cdata) { + $this->lastCData .= $cdata; + } + + /*}}}*/ + /*{{{ public function getCData() */ + + /** + * Returns the CData collected so far. + * + * @return String Character data collected. + * @access public + */ + protected function getCData() { + return $this->lastCData; + } + + /*}}}*/ + /*{{{ public function getLastOpenTag() */ + + /** + * Returns the name of parent tag of give tag + * + * @param $tag Name of a child tag + * @return String Name of the parent tag of $tag + * @access public + */ + protected function getLastOpenTag($tag) { + $lastTagIndex = count($this->openTags)-1; + if($this->openTags[$lastTagIndex] == $tag) { + if($lastTagIndex > 0) { + return $this->openTags[$lastTagIndex-1]; + } + } + return false; + } + + /*}}}*/ + /*{{{ public function getDocumentArray() */ + + /** + * Return the document array gathered during parsing. + * Document array is a data structure that mimics the XML + * contents. + * + * @return Array Document array + * @access public + */ + public function getDocumentArray() { + return $this->_docroot; + } + + /*}}}*/ + } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Logger.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Logger.php new file mode 100644 index 0000000..2b5c9d2 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Logger.php @@ -0,0 +1,115 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + class TestGen4Web_Util_Logger { + + private $level; + private $logLevels = array( + "LOG_CRITICAL", + "LOG_ERROR", + "LOG_WARNING", + "LOG_NOTICE", + "LOG_INFO", + "LOG_DEBUG" + ); + + public function setLevel($level) { + if(!is_numeric($level)) { + for($i = 0; $i < count($this->logLevels); $i++) { + if(strcasecmp($this->logLevels[$i], $level) === 0) { + $level = $i; + break; + } + } + } + $this->level = $level; + } + + public function critical($str, $file="", $line="") { + if($this->level >= 0) { + error_log("[CRITICAL] [" . $file . ":" . $line . "] " . $str); + } + } + + public function error($str, $file="", $line="") { + if($this->level >= 1) { + error_log("[ERROR] [" . $file . ":" . $line . "] " . $str); + } + } + + public function warn($str, $file="", $line="") { + if($this->level >= 2) { + error_log("[WARNING] [" . $file . ":" . $line . "] " . $str); + } + } + + public function notice($str, $file="", $line="") { + if($this->level >= 3) { + error_log("[NOTICE] [" . $file . ":" . $line . "] " . $str); + } + } + + public function info($str, $file="", $line="") { + if($this->level >= 4) { + error_log("[INFO] [" . $file . ":" . $line . "] " . $str); + } + } + + public function debug($str, $file="", $line="") { + if($this->level >= 5) { + error_log("[DEBUG] [" . $file . ":" . $line . "] " . $str); + } + } + + public function getLevelName($level) { + return $this->logLevels[$level]; + } + } + + // testing + if(isset($_SERVER["argv"][1]) && $_SERVER["argv"][1] == "__main__") { + $logger = new Logger(); + for($i = 0; $i < 6; $i++) { + $logger->setLevel($i); + error_log("############## Level now: " . $i); + $logger->debug(""); + $logger->info(""); + $logger->notice(""); + $logger->warn(""); + $logger->error(""); + $logger->critical(""); + } + + error_log("############# With Level Names"); + for($i = 0; $i < 6; $i++) { + $logger->setLevel($logger->getLevelName($i)); + error_log("############## Level now: " . $logger->getLevelName($i)); + $logger->debug(""); + $logger->info("", __FILE__, __LINE__); + $logger->notice(""); + $logger->warn(""); + $logger->error(""); + $logger->critical(""); + } + } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Util.php b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Util.php new file mode 100644 index 0000000..ec7aa76 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/php-simpletest-translator/Util/Util.php @@ -0,0 +1,99 @@ + + * @copyright Copyright (C) 2004-2006 SpikeSource, Inc. + * @license http://www.spikesource.com/license.html Open Software License v2.1 + * @version $Revision: $ + * @link + * + * modifications: + * + */ + + class TestGen4Web_Util_Util { + + /*{{{ public function capitalizeDriveLetter() */ + + /** + * Convert the drive letter to upper case + * + * @param $path Windows path with "c:" + * @return String Path with driver letter capitalized. + * @access public + */ + public function capitalizeDriveLetter($path) { + if(strpos($path, ":") === 1) { + $path = strtoupper(substr($path, 0, 1)) . substr($path, 1); + } + return $path; + } + + /*}}}*/ + /*{{{ public function replaceBackslashes() */ + + /** + * Convert the back slash path separators with forward slashes. + * + * @param $path Windows path with backslash path separators + * @return String Path with back slashes replaced with forward slashes. + * @access public + */ + public function replaceBackslashes($path) { + $path = str_replace("\\", "/", $path); + return $this->capitalizeDriveLetter($path); + } + + /*}}}*/ + /*{{{ public function makeDirRecursive() */ + + /** + * Make directory recursively. + * (Taken from: http://aidan.dotgeek.org/lib/?file=function.mkdirr.php) + * + * @param $dir Directory path to create + * @param $mode=0755 + * @return True on success, False on failure + * @access public + */ + public function makeDirRecursive($dir, $mode=0755) { + // Check if directory already exists + if (is_dir($dir) || empty($dir)) { + return true; + } + + // Ensure a file does not already exist with the same name + if (is_file($dir)) { + error_log("File already exists: " . $dir, + __FILE__, __LINE__); + return false; + } + + $dir = $this->replaceBackslashes($dir); + + // Crawl up the directory tree + $next_pathname = substr($dir, 0, strrpos($dir, "/")); + if($this->makeDirRecursive($next_pathname, $mode)) { + if (!file_exists($dir)) { + return mkdir($dir, $mode); + } + } + + return false; + } + /*}}}*/ + } + + $util = new TestGen4Web_Util_Util(); + global $util; +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE b/plugins/www/testgen4web_simpletest/lib/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE new file mode 100644 index 0000000..8ac9cf2 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE @@ -0,0 +1,348 @@ +Simple Test interface changes +============================= +Because the SimpleTest tool set is still evolving it is likely that tests +written with earlier versions will fail with the newest ones. The most +dramatic changes are in the alpha releases. Here is a list of possible +problems and their fixes... + +No method getRelativeUrls() or getAbsoluteUrls() +------------------------------------------------ +These methods were always a bit weird anyway, and +the new parsing of the base tag makes them more so. +They have been replaced with getUrls() instead. If +you want the old functionality then simply chop +off the current domain from getUrl(). + +Method setWildcard() removed in mocks +------------------------------------- +Even setWildcard() has been removed in 1.0.1beta now. +If you want to test explicitely for a '*' string, then +simply pass in new IdenticalExpectation('*') instead. + +No method _getTest() on mocks +----------------------------- +This has finally been removed. It was a pretty esoteric +flex point anyway. It was there to allow the mocks to +work with other test tools, but no one does this. + +No method assertError(), assertNoErrors(), swallowErrors() +---------------------------------------------------------- +These have been deprecated in 1.0.1beta in favour of +expectError() and expectException(). assertNoErrors() is +redundant if you use expectError() as failures are now reported +immediately. + +No method TestCase::signal() +---------------------------- +This has been deprecated in favour of triggering an error or +throwing an exception. Deprecated as of 1.0.1beta. + +No method TestCase::sendMessage() +--------------------------------- +This has been deprecated as of 1.0.1beta. + +Failure to connect now emits failures +------------------------------------- +It used to be that you would have to use the +getTransferError() call on the web tester to see if +there was a socket level error in a fetch. This check +is now always carried out by the WebTestCase unless +the fetch is prefaced with WebTestCase::ignoreErrors(). +The ignore directive only lasts for test case fetching +action such as get() and click(). + +No method SimpleTestOptions::ignore() +------------------------------------- +This is deprecated in version 1.0.1beta and has been moved +to SimpleTest::ignore() as that is more readable. In +addition, parent classes are also ignored automatically. +If you are using PHP5 you can skip this directive simply +by marking your test case as abstract. + +No method assertCopy() +---------------------- +This is deprecated in 1.0.1 in favour of assertClone(). +The assertClone() method is slightly different in that +the objects must be identical, but without being a +reference. It is thus not a strict inversion of +assertReference(). + +Constructor wildcard override has no effect in mocks +---------------------------------------------------- +As of 1.0.1beta this is now set with setWildcard() instead +of in the constructor. + +No methods setStubBaseClass()/getStubBaseClass() +------------------------------------------------ +As mocks are now used instead of stubs, these methods +stopped working and are now removed as of the 1.0.1beta +release. The mock objects may be freely used instead. + +No method addPartialMockCode() +------------------------------ +The ability to insert arbitrary partial mock code +has been removed. This was a low value feature +causing needless complications. It was removed +in the 1.0.1beta release. + +No method setMockBaseClass() +---------------------------- +The ability to change the mock base class has been +scheduled for removal and is deprecated since the +1.0.1beta version. This was a rarely used feature +except as a workaround for PHP5 limitations. As +these limitations are being resolved it's hoped +that the bundled mocks can be used directly. + +No class Stub +------------- +Server stubs are deprecated from 1.0.1 as the mocks now +have exactly the same interface. Just use mock objects +instead. + +No class SimpleTestOptions +-------------------------- +This was replced by the shorter SimpleTest in 1.0.1beta1 +and is since deprecated. + +No file simple_test.php +----------------------- +This was renamed test_case.php in 1.0.1beta to more accurately +reflect it's purpose. This file should never be directly +included in test suites though, as it's part of the +underlying mechanics and has a tendency to be refactored. + +No class WantedPatternExpectation +--------------------------------- +This was deprecated in 1.0.1alpha in favour of the simpler +name PatternExpectation. + +No class NoUnwantedPatternExpectation +------------------------------------- +This was deprecated in 1.0.1alpha in favour of the simpler +name NoPatternExpectation. + +No method assertNoUnwantedPattern() +----------------------------------- +This has been renamed to assertNoPattern() in 1.0.1alpha and +the old form is deprecated. + +No method assertWantedPattern() +------------------------------- +This has been renamed to assertPattern() in 1.0.1alpha and +the old form is deprecated. + +No method assertExpectation() +----------------------------- +This was renamed as assert() in 1.0.1alpha and the old form +has been deprecated. + +No class WildcardExpectation +---------------------------- +This was a mostly internal class for the mock objects. It was +renamed AnythingExpectation to bring it closer to JMock and +NMock in version 1.0.1alpha. + +Missing UnitTestCase::assertErrorPattern() +------------------------------------------ +This method is deprecated for version 1.0.1 onwards. +This method has been subsumed by assertError() that can now +take an expectation. Simply pass a PatternExpectation +into assertError() to simulate the old behaviour. + +No HTML when matching page elements +----------------------------------- +This behaviour has been switched to using plain text as if it +were seen by the user of the browser. This means that HTML tags +are suppressed, entities are converted and whitespace is +normalised. This should make it easier to match items in forms. +Also images are replaced with their "alt" text so that they +can be matched as well. + +No method SimpleRunner::_getTestCase() +-------------------------------------- +This was made public as getTestCase() in 1.0RC2. + +No method restartSession() +-------------------------- +This was renamed to restart() in the WebTestCase, SimpleBrowser +and the underlying SimpleUserAgent in 1.0RC2. Because it was +undocumented anyway, no attempt was made at backward +compatibility. + +My custom test case ignored by tally() +-------------------------------------- +The _assertTrue method has had it's signature changed due to a bug +in the PHP 5.0.1 release. You must now use getTest() from within +that method to get the test case. Mock compatibility with other +unit testers is now deprecated as of 1.0.1alpha as PEAR::PHPUnit2 +should soon have mock support of it's own. + +Broken code extending SimpleRunner +---------------------------------- +This was replaced with SimpleScorer so that I could use the runner +name in another class. This happened in RC1 development and there +is no easy backward compatibility fix. The solution is simply to +extend SimpleScorer instead. + +Missing method getBaseCookieValue() +----------------------------------- +This was renamed getCurrentCookieValue() in RC1. + +Missing files from the SimpleTest suite +--------------------------------------- +Versions of SimpleTest prior to Beta6 required a SIMPLE_TEST constant +to point at the SimpleTest folder location before any of the toolset +was loaded. This is no longer documented as it is now unnecessary +for later versions. If you are using an earlier version you may +need this constant. Consult the documentation that was bundled with +the release that you are using or upgrade to Beta6 or later. + +No method SimpleBrowser::getCurrentUrl() +-------------------------------------- +This is replaced with the more versatile showRequest() for +debugging. It only existed in this context for version Beta5. +Later versions will have SimpleBrowser::getHistory() for tracking +paths through pages. It is renamed as getUrl() since 1.0RC1. + +No method Stub::setStubBaseClass() +---------------------------------- +This method has finally been removed in 1.0RC1. Use +SimpleTestOptions::setStubBaseClass() instead. + +No class CommandLineReporter +---------------------------- +This was renamed to TextReporter in Beta3 and the deprecated version +was removed in 1.0RC1. + +No method requireReturn() +------------------------- +This was deprecated in Beta3 and is now removed. + +No method expectCookie() +------------------------ +This method was abruptly removed in Beta4 so as to simplify the internals +until another mechanism can replace it. As a workaround it is necessary +to assert that the cookie has changed by setting it before the page +fetch and then assert the desired value. + +No method clickSubmitByFormId() +------------------------------- +This method had an incorrect name as no button was involved. It was +renamed to submitByFormId() in Beta4 and the old version deprecated. +Now removed. + +No method paintStart() or paintEnd() +------------------------------------ +You should only get this error if you have subclassed the lower level +reporting and test runner machinery. These methods have been broken +down into events for test methods, events for test cases and events +for group tests. The new methods are... + +paintStart() --> paintMethodStart(), paintCaseStart(), paintGroupStart() +paintEnd() --> paintMethodEnd(), paintCaseEnd(), paintGroupEnd() + +This change was made in Beta3, ironically to make it easier to subclass +the inner machinery. Simply duplicating the code you had in the previous +methods should provide a temporary fix. + +No class TestDisplay +-------------------- +This has been folded into SimpleReporter in Beta3 and is now deprecated. +It was removed in RC1. + +No method WebTestCase::fetch() +------------------------------ +This was renamed get() in Alpha8. It is removed in Beta3. + +No method submit() +------------------ +This has been renamed clickSubmit() in Beta1. The old method was +removed in Beta2. + +No method clearHistory() +------------------------ +This method is deprecated in Beta2 and removed in RC1. + +No method getCallCount() +------------------------ +This method has been deprecated since Beta1 and has now been +removed. There are now more ways to set expectations on counts +and so this method should be unecessery. Removed in RC1. + +Cannot find file * +------------------ +The following public name changes have occoured... + +simple_html_test.php --> reporter.php +simple_mock.php --> mock_objects.php +simple_unit.php --> unit_tester.php +simple_web.php --> web_tester.php + +The old names were deprecated in Alpha8 and removed in Beta1. + +No method attachObserver() +-------------------------- +Prior to the Alpha8 release the old internal observer pattern was +gutted and replaced with a visitor. This is to trade flexibility of +test case expansion against the ease of writing user interfaces. + +Code such as... + +$test = &new MyTestCase(); +$test->attachObserver(new TestHtmlDisplay()); +$test->run(); + +...should be rewritten as... + +$test = &new MyTestCase(); +$test->run(new HtmlReporter()); + +If you previously attached multiple observers then the workaround +is to run the tests twice, once with each, until they can be combined. +For one observer the old method is simulated in Alpha 8, but is +removed in Beta1. + +No class TestHtmlDisplay +------------------------ +This class has been renamed to HtmlReporter in Alpha8. It is supported, +but deprecated in Beta1 and removed in Beta2. If you have subclassed +the display for your own design, then you will have to extend this +class (HtmlReporter) instead. + +If you have accessed the event queue by overriding the notify() method +then I am afraid you are in big trouble :(. The reporter is now +carried around the test suite by the runner classes and the methods +called directly. In the unlikely event that this is a problem and +you don't want to upgrade the test tool then simplest is to write your +own runner class and invoke the tests with... + +$test->accept(new MyRunner(new MyReporter())); + +...rather than the run method. This should be easier to extend +anyway and gives much more control. Even this method is overhauled +in Beta3 where the runner class can be set within the test case. Really +the best thing to do is to upgrade to this version as whatever you were +trying to achieve before should now be very much easier. + +Missing set options method +-------------------------- +All test suite options are now in one class called SimpleTestOptions. +This means that options are set differently... + +GroupTest::ignore() --> SimpleTestOptions::ignore() +Mock::setMockBaseClass() --> SimpleTestOptions::setMockBaseClass() + +These changed in Alpha8 and the old versions are now removed in RC1. + +No method setExpected*() +------------------------ +The mock expectations changed their names in Alpha4 and the old names +ceased to be supported in Alpha8. The changes are... + +setExpectedArguments() --> expectArguments() +setExpectedArgumentsSequence() --> expectArgumentsAt() +setExpectedCallCount() --> expectCallCount() +setMaximumCallCount() --> expectMaximumCallCount() + +The parameters remained the same. diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/LICENSE b/plugins/www/testgen4web_simpletest/lib/simpletest/LICENSE new file mode 100644 index 0000000..09f465a --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/LICENSE @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/README b/plugins/www/testgen4web_simpletest/lib/simpletest/README new file mode 100644 index 0000000..c52e3f7 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/README @@ -0,0 +1,108 @@ +SimpleTest +========== +You probably got this package from... +http://simpletest.sourceforge.net/projects/simpletest/ + +If there is no licence agreement with this package please download +a version from the location above. You must read and accept that +licence to use this software. The file is titled simply LICENSE. + +What is it? It's a framework for unit testing, web site testing and +mock objects for PHP 4.2.0+ (and PHP 5.0 to 5.3 without E_STRICT). + +If you have used JUnit, you will find this PHP unit testing version very +similar. Also included is a mock objects and server stubs generator. +The stubs can have return values set for different arguments, can have +sequences set also by arguments and can return items by reference. +The mocks inherit all of this functionality and can also have +expectations set, again in sequences and for different arguments. + +A web tester similar in concept to JWebUnit is also included. There is no +JavaScript or tables support, but forms, authentication, cookies and +frames are handled. + +You can see a release schedule at http://www.lastcraft.com/overview.php +which is also copied to the documentation folder with this release. +A full PHPDocumenter API documentation exists at +http://simpletest.sourceforge.net/. + +The user interface is minimal +in the extreme, but a lot of information flows from the test suite. +After version 1.0 we will release a better web UI, but we are leaving XUL +and GTk versions to volunteers as everybody has their own opinion +on a good GUI, and we don't want to discourage development by shipping +one with the toolkit. YOucan download an Eclipse plug-in separately. + +You are looking at a second full release. The unit tests for SimpleTest +itself can be run here... + +simpletest/test/unit_tests.php + +And tests involving live network connections as well are here... + +simpletest/test/all_tests.php + +The full tests will typically overrun the 8Mb limit often allowed +to a PHP process. A workaround is to run the tests on the command +with a custom php.ini file if you do not have access to your server +version. + +You will have to edit the all_tests.php file if you are accesssing +the internet through a proxy server. See the comments in all_tests.php +for instructions. + +The full tests read some test data from the LastCraft site. If the site +is down or has been modified for a later version then you will get +spurious errors. A unit_tests.php failure on the other hand would be +very serious. As far as we know we haven't yet managed to check in any +unit test failures, so please correct us if you find one. + +Even if all of the tests run please verify that your existing test suites +also function as expected. If they don't see the file... + +HELP_MY_TESTS_DONT_WORK_ANYMORE + +This contains information on interface changes. It also points out +deprecated interfaces, so you should read this even if all of +your current tests appear to run. + +There is a documentation folder which contains the core reference information +in English and French, although this information is fairly basic. +You can find a tutorial on... + +http://www.lastcraft.com/first_test_tutorial.php + +...to get you started and this material will eventually become included +with the project documentation. A French translation exists at... + +http://www.onpk.net/index.php/2005/01/12/254-tutoriel-simpletest-decouvrir-les-tests-unitaires. + +If you download and use, and possibly even extend this tool, please let us +know. Any feedback, even bad, is always welcome and we will work to get +your suggestions into the next release. Ideally please send your +comments to... + +simpletest-support@lists.sourceforge.net + +...so that others can read them too. We usually try to respond within 48 +hours. + +There is no change log except at Sourceforge. You can visit the +release notes to see the completed TODO list after each cycle and also the +status of any bugs, but if the bug is recent then it will be fixed in SVN only. +The SVN check-ins always have all the tests passing and so SVN snapshots should +be pretty usable, although the code may not look so good internally. + +Oh, yes. It is called "Simple" because it should be simple to +use. We intend to add a complete set of tools for a test first +and "test as you code" type of development. "Simple" does not +mean "Lite" in this context. + +Thanks to everyone who has sent comments and offered suggestions. They +really are invaluable, but sadly you are too many to mention in full. +Thanks to all on the advanced PHP forum on SitePoint, especially Harry +Feucks. Early adopters are always an inspiration. + +Marcus Baker, Jason Sweat, Travis Swicegood, Perrick Penet and Edward Z. Yang. +-- +marcus@lastcraft.com diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/Test.php b/plugins/www/testgen4web_simpletest/lib/simpletest/Test.php new file mode 100644 index 0000000..d91b1ea --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/Test.php @@ -0,0 +1,62 @@ +WebTestCase(); + } + + // function + function testEverything() { + $this->get("https://apuleio.telecomitalia.local/ortro/"); + $this->assertTitle("ortro - An easy way to make scheduling and system/application monitoring"); + $this->setFieldByName("passwd", "luca"); + //$this->click("Login"); + $this->assertTitle("ortro - An easy way to make scheduling and system/application monitoring"); + $this->clickLink("Systems"); + $this->assertTitle("ortro - An easy way to make scheduling and system/application monitoring"); + $this->setFieldById("id_chk", "true"); + $this->clickLink("Hosts"); + $this->assertTitle("ortro - An easy way to make scheduling and system/application monitoring"); + + } + + } + + // __main__ + // Remove the following section if you are including this class + // as part of a group test elsewhere. + + if(is_array($argv) && strpos($argv[0], basename(__FILE__)) !== false) { + $testsuite = &new GroupTest("TestGen4Web Generated Web Test Suite"); + $testsuite->addTestClass('Test'); + $testsuite->run(new TextReporter()); + } + +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/VERSION b/plugins/www/testgen4web_simpletest/lib/simpletest/VERSION new file mode 100644 index 0000000..7f20734 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/VERSION @@ -0,0 +1 @@ +1.0.1 \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/authentication.php b/plugins/www/testgen4web_simpletest/lib/simpletest/authentication.php new file mode 100644 index 0000000..c56d11b --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/authentication.php @@ -0,0 +1,238 @@ +_type = $type; + $this->_root = $url->getBasePath(); + $this->_username = false; + $this->_password = false; + } + + /** + * Adds another location to the realm. + * @param SimpleUrl $url Somewhere in realm. + * @access public + */ + function stretch($url) { + $this->_root = $this->_getCommonPath($this->_root, $url->getPath()); + } + + /** + * Finds the common starting path. + * @param string $first Path to compare. + * @param string $second Path to compare. + * @return string Common directories. + * @access private + */ + function _getCommonPath($first, $second) { + $first = explode('/', $first); + $second = explode('/', $second); + for ($i = 0; $i < min(count($first), count($second)); $i++) { + if ($first[$i] != $second[$i]) { + return implode('/', array_slice($first, 0, $i)) . '/'; + } + } + return implode('/', $first) . '/'; + } + + /** + * Sets the identity to try within this realm. + * @param string $username Username in authentication dialog. + * @param string $username Password in authentication dialog. + * @access public + */ + function setIdentity($username, $password) { + $this->_username = $username; + $this->_password = $password; + } + + /** + * Accessor for current identity. + * @return string Last succesful username. + * @access public + */ + function getUsername() { + return $this->_username; + } + + /** + * Accessor for current identity. + * @return string Last succesful password. + * @access public + */ + function getPassword() { + return $this->_password; + } + + /** + * Test to see if the URL is within the directory + * tree of the realm. + * @param SimpleUrl $url URL to test. + * @return boolean True if subpath. + * @access public + */ + function isWithin($url) { + if ($this->_isIn($this->_root, $url->getBasePath())) { + return true; + } + if ($this->_isIn($this->_root, $url->getBasePath() . $url->getPage() . '/')) { + return true; + } + return false; + } + + /** + * Tests to see if one string is a substring of + * another. + * @param string $part Small bit. + * @param string $whole Big bit. + * @return boolean True if the small bit is + * in the big bit. + * @access private + */ + function _isIn($part, $whole) { + return strpos($whole, $part) === 0; + } +} + +/** + * Manages security realms. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleAuthenticator { + var $_realms; + + /** + * Clears the realms. + * @access public + */ + function SimpleAuthenticator() { + $this->restartSession(); + } + + /** + * Starts with no realms set up. + * @access public + */ + function restartSession() { + $this->_realms = array(); + } + + /** + * Adds a new realm centered the current URL. + * Browsers vary wildly on their behaviour in this + * regard. Mozilla ignores the realm and presents + * only when challenged, wasting bandwidth. IE + * just carries on presenting until a new challenge + * occours. SimpleTest tries to follow the spirit of + * the original standards committee and treats the + * base URL as the root of a file tree shaped realm. + * @param SimpleUrl $url Base of realm. + * @param string $type Authentication type for this + * realm. Only Basic authentication + * is currently supported. + * @param string $realm Name of realm. + * @access public + */ + function addRealm($url, $type, $realm) { + $this->_realms[$url->getHost()][$realm] = new SimpleRealm($type, $url); + } + + /** + * Sets the current identity to be presented + * against that realm. + * @param string $host Server hosting realm. + * @param string $realm Name of realm. + * @param string $username Username for realm. + * @param string $password Password for realm. + * @access public + */ + function setIdentityForRealm($host, $realm, $username, $password) { + if (isset($this->_realms[$host][$realm])) { + $this->_realms[$host][$realm]->setIdentity($username, $password); + } + } + + /** + * Finds the name of the realm by comparing URLs. + * @param SimpleUrl $url URL to test. + * @return SimpleRealm Name of realm. + * @access private + */ + function _findRealmFromUrl($url) { + if (! isset($this->_realms[$url->getHost()])) { + return false; + } + foreach ($this->_realms[$url->getHost()] as $name => $realm) { + if ($realm->isWithin($url)) { + return $realm; + } + } + return false; + } + + /** + * Presents the appropriate headers for this location. + * @param SimpleHttpRequest $request Request to modify. + * @param SimpleUrl $url Base of realm. + * @access public + */ + function addHeaders(&$request, $url) { + if ($url->getUsername() && $url->getPassword()) { + $username = $url->getUsername(); + $password = $url->getPassword(); + } elseif ($realm = $this->_findRealmFromUrl($url)) { + $username = $realm->getUsername(); + $password = $realm->getPassword(); + } else { + return; + } + $this->addBasicHeaders($request, $username, $password); + } + + /** + * Presents the appropriate headers for this + * location for basic authentication. + * @param SimpleHttpRequest $request Request to modify. + * @param string $username Username for realm. + * @param string $password Password for realm. + * @access public + * @static + */ + function addBasicHeaders(&$request, $username, $password) { + if ($username && $password) { + $request->addHeaderLine( + 'Authorization: Basic ' . base64_encode("$username:$password")); + } + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/autorun.php b/plugins/www/testgen4web_simpletest/lib/simpletest/autorun.php new file mode 100644 index 0000000..7d97d2d --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/autorun.php @@ -0,0 +1,87 @@ +createSuiteFromClasses( + basename(initial_file()), + $loader->selectRunnableTests($candidates)); + $result = $suite->run(new DefaultReporter()); + if (SimpleReporter::inCli()) { + exit($result ? 0 : 1); + } +} + +/** + * Checks the current test context to see if a test has + * ever been run. + * @return boolean True if tests have run. + */ +function tests_have_run() { + if ($context = SimpleTest::getContext()) { + return (boolean)$context->getTest(); + } + return false; +} + +/** + * The first autorun file. + * @return string Filename of first autorun script. + */ +function initial_file() { + static $file = false; + if (! $file) { + $file = reset(get_included_files()); + } + return $file; +} + +/** + * Just the classes from the first autorun script. May + * get a few false positives, as it just does a regex based + * on following the word "class". + * @return array List of all possible classes in first + * autorun script. + */ +function classes_defined_in_initial_file() { + if (preg_match_all('/\bclass\s+(\w+)/i', file_get_contents(initial_file()), $matches)) { + return array_map('strtolower', $matches[1]); + } + return array(); +} + +/** + * Every class since the first autorun include. This + * is safe enough if require_once() is alwyas used. + * @return array Class names. + */ +function capture_new_classes() { + global $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES; + return array_map('strtolower', array_diff(get_declared_classes(), + $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES ? + $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES : array())); +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/browser.php b/plugins/www/testgen4web_simpletest/lib/simpletest/browser.php new file mode 100644 index 0000000..e2a1fe1 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/browser.php @@ -0,0 +1,1098 @@ +_sequence = array(); + $this->_position = -1; + } + + /** + * Test for no entries yet. + * @return boolean True if empty. + * @access private + */ + function _isEmpty() { + return ($this->_position == -1); + } + + /** + * Test for being at the beginning. + * @return boolean True if first. + * @access private + */ + function _atBeginning() { + return ($this->_position == 0) && ! $this->_isEmpty(); + } + + /** + * Test for being at the last entry. + * @return boolean True if last. + * @access private + */ + function _atEnd() { + return ($this->_position + 1 >= count($this->_sequence)) && ! $this->_isEmpty(); + } + + /** + * Adds a successfully fetched page to the history. + * @param SimpleUrl $url URL of fetch. + * @param SimpleEncoding $parameters Any post data with the fetch. + * @access public + */ + function recordEntry($url, $parameters) { + $this->_dropFuture(); + array_push( + $this->_sequence, + array('url' => $url, 'parameters' => $parameters)); + $this->_position++; + } + + /** + * Last fully qualified URL for current history + * position. + * @return SimpleUrl URL for this position. + * @access public + */ + function getUrl() { + if ($this->_isEmpty()) { + return false; + } + return $this->_sequence[$this->_position]['url']; + } + + /** + * Parameters of last fetch from current history + * position. + * @return SimpleFormEncoding Post parameters. + * @access public + */ + function getParameters() { + if ($this->_isEmpty()) { + return false; + } + return $this->_sequence[$this->_position]['parameters']; + } + + /** + * Step back one place in the history. Stops at + * the first page. + * @return boolean True if any previous entries. + * @access public + */ + function back() { + if ($this->_isEmpty() || $this->_atBeginning()) { + return false; + } + $this->_position--; + return true; + } + + /** + * Step forward one place. If already at the + * latest entry then nothing will happen. + * @return boolean True if any future entries. + * @access public + */ + function forward() { + if ($this->_isEmpty() || $this->_atEnd()) { + return false; + } + $this->_position++; + return true; + } + + /** + * Ditches all future entries beyond the current + * point. + * @access private + */ + function _dropFuture() { + if ($this->_isEmpty()) { + return; + } + while (! $this->_atEnd()) { + array_pop($this->_sequence); + } + } +} + +/** + * Simulated web browser. This is an aggregate of + * the user agent, the HTML parsing, request history + * and the last header set. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleBrowser { + var $_user_agent; + var $_page; + var $_history; + var $_ignore_frames; + var $_maximum_nested_frames; + + /** + * Starts with a fresh browser with no + * cookie or any other state information. The + * exception is that a default proxy will be + * set up if specified in the options. + * @access public + */ + function SimpleBrowser() { + $this->_user_agent = &$this->_createUserAgent(); + $this->_user_agent->useProxy( + SimpleTest::getDefaultProxy(), + SimpleTest::getDefaultProxyUsername(), + SimpleTest::getDefaultProxyPassword()); + $this->_page = &new SimplePage(); + $this->_history = &$this->_createHistory(); + $this->_ignore_frames = false; + $this->_maximum_nested_frames = DEFAULT_MAX_NESTED_FRAMES; + } + + /** + * Creates the underlying user agent. + * @return SimpleFetcher Content fetcher. + * @access protected + */ + function &_createUserAgent() { + $user_agent = &new SimpleUserAgent(); + return $user_agent; + } + + /** + * Creates a new empty history list. + * @return SimpleBrowserHistory New list. + * @access protected + */ + function &_createHistory() { + $history = &new SimpleBrowserHistory(); + return $history; + } + + /** + * Disables frames support. Frames will not be fetched + * and the frameset page will be used instead. + * @access public + */ + function ignoreFrames() { + $this->_ignore_frames = true; + } + + /** + * Enables frames support. Frames will be fetched from + * now on. + * @access public + */ + function useFrames() { + $this->_ignore_frames = false; + } + + /** + * Switches off cookie sending and recieving. + * @access public + */ + function ignoreCookies() { + $this->_user_agent->ignoreCookies(); + } + + /** + * Switches back on the cookie sending and recieving. + * @access public + */ + function useCookies() { + $this->_user_agent->useCookies(); + } + + /** + * Parses the raw content into a page. Will load further + * frame pages unless frames are disabled. + * @param SimpleHttpResponse $response Response from fetch. + * @param integer $depth Nested frameset depth. + * @return SimplePage Parsed HTML. + * @access private + */ + function &_parse($response, $depth = 0) { + $page = &$this->_buildPage($response); + if ($this->_ignore_frames || ! $page->hasFrames() || ($depth > $this->_maximum_nested_frames)) { + return $page; + } + $frameset = &new SimpleFrameset($page); + foreach ($page->getFrameset() as $key => $url) { + $frame = &$this->_fetch($url, new SimpleGetEncoding(), $depth + 1); + $frameset->addFrame($frame, $key); + } + return $frameset; + } + + /** + * Assembles the parsing machinery and actually parses + * a single page. Frees all of the builder memory and so + * unjams the PHP memory management. + * @param SimpleHttpResponse $response Response from fetch. + * @return SimplePage Parsed top level page. + * @access protected + */ + function &_buildPage($response) { + $builder = &new SimplePageBuilder(); + $page = &$builder->parse($response); + $builder->free(); + unset($builder); + return $page; + } + + /** + * Fetches a page. Jointly recursive with the _parse() + * method as it descends a frameset. + * @param string/SimpleUrl $url Target to fetch. + * @param SimpleEncoding $encoding GET/POST parameters. + * @param integer $depth Nested frameset depth protection. + * @return SimplePage Parsed page. + * @access private + */ + function &_fetch($url, $encoding, $depth = 0) { + $response = &$this->_user_agent->fetchResponse($url, $encoding); + if ($response->isError()) { + $page = &new SimplePage($response); + } else { + $page = &$this->_parse($response, $depth); + } + return $page; + } + + /** + * Fetches a page or a single frame if that is the current + * focus. + * @param SimpleUrl $url Target to fetch. + * @param SimpleEncoding $parameters GET/POST parameters. + * @return string Raw content of page. + * @access private + */ + function _load($url, $parameters) { + $frame = $url->getTarget(); + if (! $frame || ! $this->_page->hasFrames() || (strtolower($frame) == '_top')) { + return $this->_loadPage($url, $parameters); + } + return $this->_loadFrame(array($frame), $url, $parameters); + } + + /** + * Fetches a page and makes it the current page/frame. + * @param string/SimpleUrl $url Target to fetch as string. + * @param SimplePostEncoding $parameters POST parameters. + * @return string Raw content of page. + * @access private + */ + function _loadPage($url, $parameters) { + $this->_page = &$this->_fetch($url, $parameters); + $this->_history->recordEntry( + $this->_page->getUrl(), + $this->_page->getRequestData()); + return $this->_page->getRaw(); + } + + /** + * Fetches a frame into the existing frameset replacing the + * original. + * @param array $frames List of names to drill down. + * @param string/SimpleUrl $url Target to fetch as string. + * @param SimpleFormEncoding $parameters POST parameters. + * @return string Raw content of page. + * @access private + */ + function _loadFrame($frames, $url, $parameters) { + $page = &$this->_fetch($url, $parameters); + $this->_page->setFrame($frames, $page); + return $page->getRaw(); + } + + /** + * Removes expired and temporary cookies as if + * the browser was closed and re-opened. + * @param string/integer $date Time when session restarted. + * If omitted then all persistent + * cookies are kept. + * @access public + */ + function restart($date = false) { + $this->_user_agent->restart($date); + } + + /** + * Adds a header to every fetch. + * @param string $header Header line to add to every + * request until cleared. + * @access public + */ + function addHeader($header) { + $this->_user_agent->addHeader($header); + } + + /** + * Ages the cookies by the specified time. + * @param integer $interval Amount in seconds. + * @access public + */ + function ageCookies($interval) { + $this->_user_agent->ageCookies($interval); + } + + /** + * Sets an additional cookie. If a cookie has + * the same name and path it is replaced. + * @param string $name Cookie key. + * @param string $value Value of cookie. + * @param string $host Host upon which the cookie is valid. + * @param string $path Cookie path if not host wide. + * @param string $expiry Expiry date. + * @access public + */ + function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { + $this->_user_agent->setCookie($name, $value, $host, $path, $expiry); + } + + /** + * Reads the most specific cookie value from the + * browser cookies. + * @param string $host Host to search. + * @param string $path Applicable path. + * @param string $name Name of cookie to read. + * @return string False if not present, else the + * value as a string. + * @access public + */ + function getCookieValue($host, $path, $name) { + return $this->_user_agent->getCookieValue($host, $path, $name); + } + + /** + * Reads the current cookies for the current URL. + * @param string $name Key of cookie to find. + * @return string Null if there is no current URL, false + * if the cookie is not set. + * @access public + */ + function getCurrentCookieValue($name) { + return $this->_user_agent->getBaseCookieValue($name, $this->_page->getUrl()); + } + + /** + * Sets the maximum number of redirects before + * a page will be loaded anyway. + * @param integer $max Most hops allowed. + * @access public + */ + function setMaximumRedirects($max) { + $this->_user_agent->setMaximumRedirects($max); + } + + /** + * Sets the maximum number of nesting of framed pages + * within a framed page to prevent loops. + * @param integer $max Highest depth allowed. + * @access public + */ + function setMaximumNestedFrames($max) { + $this->_maximum_nested_frames = $max; + } + + /** + * Sets the socket timeout for opening a connection. + * @param integer $timeout Maximum time in seconds. + * @access public + */ + function setConnectionTimeout($timeout) { + $this->_user_agent->setConnectionTimeout($timeout); + } + + /** + * Sets proxy to use on all requests for when + * testing from behind a firewall. Set URL + * to false to disable. + * @param string $proxy Proxy URL. + * @param string $username Proxy username for authentication. + * @param string $password Proxy password for authentication. + * @access public + */ + function useProxy($proxy, $username = false, $password = false) { + $this->_user_agent->useProxy($proxy, $username, $password); + } + + /** + * Fetches the page content with a HEAD request. + * Will affect cookies, but will not change the base URL. + * @param string/SimpleUrl $url Target to fetch as string. + * @param hash/SimpleHeadEncoding $parameters Additional parameters for + * HEAD request. + * @return boolean True if successful. + * @access public + */ + function head($url, $parameters = false) { + if (! is_object($url)) { + $url = new SimpleUrl($url); + } + if ($this->getUrl()) { + $url = $url->makeAbsolute($this->getUrl()); + } + $response = &$this->_user_agent->fetchResponse($url, new SimpleHeadEncoding($parameters)); + return ! $response->isError(); + } + + /** + * Fetches the page content with a simple GET request. + * @param string/SimpleUrl $url Target to fetch. + * @param hash/SimpleFormEncoding $parameters Additional parameters for + * GET request. + * @return string Content of page or false. + * @access public + */ + function get($url, $parameters = false) { + if (! is_object($url)) { + $url = new SimpleUrl($url); + } + if ($this->getUrl()) { + $url = $url->makeAbsolute($this->getUrl()); + } + return $this->_load($url, new SimpleGetEncoding($parameters)); + } + + /** + * Fetches the page content with a POST request. + * @param string/SimpleUrl $url Target to fetch as string. + * @param hash/SimpleFormEncoding $parameters POST parameters. + * @return string Content of page. + * @access public + */ + function post($url, $parameters = false) { + if (! is_object($url)) { + $url = new SimpleUrl($url); + } + if ($this->getUrl()) { + $url = $url->makeAbsolute($this->getUrl()); + } + return $this->_load($url, new SimplePostEncoding($parameters)); + } + + /** + * Equivalent to hitting the retry button on the + * browser. Will attempt to repeat the page fetch. If + * there is no history to repeat it will give false. + * @return string/boolean Content if fetch succeeded + * else false. + * @access public + */ + function retry() { + $frames = $this->_page->getFrameFocus(); + if (count($frames) > 0) { + $this->_loadFrame( + $frames, + $this->_page->getUrl(), + $this->_page->getRequestData()); + return $this->_page->getRaw(); + } + if ($url = $this->_history->getUrl()) { + $this->_page = &$this->_fetch($url, $this->_history->getParameters()); + return $this->_page->getRaw(); + } + return false; + } + + /** + * Equivalent to hitting the back button on the + * browser. The browser history is unchanged on + * failure. The page content is refetched as there + * is no concept of content caching in SimpleTest. + * @return boolean True if history entry and + * fetch succeeded + * @access public + */ + function back() { + if (! $this->_history->back()) { + return false; + } + $content = $this->retry(); + if (! $content) { + $this->_history->forward(); + } + return $content; + } + + /** + * Equivalent to hitting the forward button on the + * browser. The browser history is unchanged on + * failure. The page content is refetched as there + * is no concept of content caching in SimpleTest. + * @return boolean True if history entry and + * fetch succeeded + * @access public + */ + function forward() { + if (! $this->_history->forward()) { + return false; + } + $content = $this->retry(); + if (! $content) { + $this->_history->back(); + } + return $content; + } + + /** + * Retries a request after setting the authentication + * for the current realm. + * @param string $username Username for realm. + * @param string $password Password for realm. + * @return boolean True if successful fetch. Note + * that authentication may still have + * failed. + * @access public + */ + function authenticate($username, $password) { + if (! $this->_page->getRealm()) { + return false; + } + $url = $this->_page->getUrl(); + if (! $url) { + return false; + } + $this->_user_agent->setIdentity( + $url->getHost(), + $this->_page->getRealm(), + $username, + $password); + return $this->retry(); + } + + /** + * Accessor for a breakdown of the frameset. + * @return array Hash tree of frames by name + * or index if no name. + * @access public + */ + function getFrames() { + return $this->_page->getFrames(); + } + + /** + * Accessor for current frame focus. Will be + * false if no frame has focus. + * @return integer/string/boolean Label if any, otherwise + * the position in the frameset + * or false if none. + * @access public + */ + function getFrameFocus() { + return $this->_page->getFrameFocus(); + } + + /** + * Sets the focus by index. The integer index starts from 1. + * @param integer $choice Chosen frame. + * @return boolean True if frame exists. + * @access public + */ + function setFrameFocusByIndex($choice) { + return $this->_page->setFrameFocusByIndex($choice); + } + + /** + * Sets the focus by name. + * @param string $name Chosen frame. + * @return boolean True if frame exists. + * @access public + */ + function setFrameFocus($name) { + return $this->_page->setFrameFocus($name); + } + + /** + * Clears the frame focus. All frames will be searched + * for content. + * @access public + */ + function clearFrameFocus() { + return $this->_page->clearFrameFocus(); + } + + /** + * Accessor for last error. + * @return string Error from last response. + * @access public + */ + function getTransportError() { + return $this->_page->getTransportError(); + } + + /** + * Accessor for current MIME type. + * @return string MIME type as string; e.g. 'text/html' + * @access public + */ + function getMimeType() { + return $this->_page->getMimeType(); + } + + /** + * Accessor for last response code. + * @return integer Last HTTP response code received. + * @access public + */ + function getResponseCode() { + return $this->_page->getResponseCode(); + } + + /** + * Accessor for last Authentication type. Only valid + * straight after a challenge (401). + * @return string Description of challenge type. + * @access public + */ + function getAuthentication() { + return $this->_page->getAuthentication(); + } + + /** + * Accessor for last Authentication realm. Only valid + * straight after a challenge (401). + * @return string Name of security realm. + * @access public + */ + function getRealm() { + return $this->_page->getRealm(); + } + + /** + * Accessor for current URL of page or frame if + * focused. + * @return string Location of current page or frame as + * a string. + */ + function getUrl() { + $url = $this->_page->getUrl(); + return $url ? $url->asString() : false; + } + + /** + * Accessor for base URL of page if set via BASE tag + * @return string base URL + */ + function getBaseUrl() { + $url = $this->_page->getBaseUrl(); + return $url ? $url->asString() : false; + } + + /** + * Accessor for raw bytes sent down the wire. + * @return string Original text sent. + * @access public + */ + function getRequest() { + return $this->_page->getRequest(); + } + + /** + * Accessor for raw header information. + * @return string Header block. + * @access public + */ + function getHeaders() { + return $this->_page->getHeaders(); + } + + /** + * Accessor for raw page information. + * @return string Original text content of web page. + * @access public + */ + function getContent() { + return $this->_page->getRaw(); + } + + /** + * Accessor for plain text version of the page. + * @return string Normalised text representation. + * @access public + */ + function getContentAsText() { + return $this->_page->getText(); + } + + /** + * Accessor for parsed title. + * @return string Title or false if no title is present. + * @access public + */ + function getTitle() { + return $this->_page->getTitle(); + } + + /** + * Accessor for a list of all links in current page. + * @return array List of urls with scheme of + * http or https and hostname. + * @access public + */ + function getUrls() { + return $this->_page->getUrls(); + } + + /** + * Sets all form fields with that name. + * @param string $label Name or label of field in forms. + * @param string $value New value of field. + * @return boolean True if field exists, otherwise false. + * @access public + */ + function setField($label, $value, $position=false) { + return $this->_page->setField(new SimpleByLabelOrName($label), $value, $position); + } + + /** + * Sets all form fields with that name. Will use label if + * one is available (not yet implemented). + * @param string $name Name of field in forms. + * @param string $value New value of field. + * @return boolean True if field exists, otherwise false. + * @access public + */ + function setFieldByName($name, $value, $position=false) { + return $this->_page->setField(new SimpleByName($name), $value, $position); + } + + /** + * Sets all form fields with that id attribute. + * @param string/integer $id Id of field in forms. + * @param string $value New value of field. + * @return boolean True if field exists, otherwise false. + * @access public + */ + function setFieldById($id, $value) { + return $this->_page->setField(new SimpleById($id), $value); + } + + /** + * Accessor for a form element value within the page. + * Finds the first match. + * @param string $label Field label. + * @return string/boolean A value if the field is + * present, false if unchecked + * and null if missing. + * @access public + */ + function getField($label) { + return $this->_page->getField(new SimpleByLabelOrName($label)); + } + + /** + * Accessor for a form element value within the page. + * Finds the first match. + * @param string $name Field name. + * @return string/boolean A string if the field is + * present, false if unchecked + * and null if missing. + * @access public + */ + function getFieldByName($name) { + return $this->_page->getField(new SimpleByName($name)); + } + + /** + * Accessor for a form element value within the page. + * @param string/integer $id Id of field in forms. + * @return string/boolean A string if the field is + * present, false if unchecked + * and null if missing. + * @access public + */ + function getFieldById($id) { + return $this->_page->getField(new SimpleById($id)); + } + + /** + * Clicks the submit button by label. The owning + * form will be submitted by this. + * @param string $label Button label. An unlabeled + * button can be triggered by 'Submit'. + * @param hash $additional Additional form data. + * @return string/boolean Page on success. + * @access public + */ + function clickSubmit($label = 'Submit', $additional = false) { + if (! ($form = &$this->_page->getFormBySubmit(new SimpleByLabel($label)))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submitButton(new SimpleByLabel($label), $additional)); + return ($success ? $this->getContent() : $success); + } + + /** + * Clicks the submit button by name attribute. The owning + * form will be submitted by this. + * @param string $name Button name. + * @param hash $additional Additional form data. + * @return string/boolean Page on success. + * @access public + */ + function clickSubmitByName($name, $additional = false) { + if (! ($form = &$this->_page->getFormBySubmit(new SimpleByName($name)))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submitButton(new SimpleByName($name), $additional)); + return ($success ? $this->getContent() : $success); + } + + /** + * Clicks the submit button by ID attribute of the button + * itself. The owning form will be submitted by this. + * @param string $id Button ID. + * @param hash $additional Additional form data. + * @return string/boolean Page on success. + * @access public + */ + function clickSubmitById($id, $additional = false) { + if (! ($form = &$this->_page->getFormBySubmit(new SimpleById($id)))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submitButton(new SimpleById($id), $additional)); + return ($success ? $this->getContent() : $success); + } + + /** + * Tests to see if a submit button exists with this + * label. + * @param string $label Button label. + * @return boolean True if present. + * @access public + */ + function isSubmit($label) { + return (boolean)$this->_page->getFormBySubmit(new SimpleByLabel($label)); + } + + /** + * Clicks the submit image by some kind of label. Usually + * the alt tag or the nearest equivalent. The owning + * form will be submitted by this. Clicking outside of + * the boundary of the coordinates will result in + * a failure. + * @param string $label ID attribute of button. + * @param integer $x X-coordinate of imaginary click. + * @param integer $y Y-coordinate of imaginary click. + * @param hash $additional Additional form data. + * @return string/boolean Page on success. + * @access public + */ + function clickImage($label, $x = 1, $y = 1, $additional = false) { + if (! ($form = &$this->_page->getFormByImage(new SimpleByLabel($label)))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submitImage(new SimpleByLabel($label), $x, $y, $additional)); + return ($success ? $this->getContent() : $success); + } + + /** + * Clicks the submit image by the name. Usually + * the alt tag or the nearest equivalent. The owning + * form will be submitted by this. Clicking outside of + * the boundary of the coordinates will result in + * a failure. + * @param string $name Name attribute of button. + * @param integer $x X-coordinate of imaginary click. + * @param integer $y Y-coordinate of imaginary click. + * @param hash $additional Additional form data. + * @return string/boolean Page on success. + * @access public + */ + function clickImageByName($name, $x = 1, $y = 1, $additional = false) { + if (! ($form = &$this->_page->getFormByImage(new SimpleByName($name)))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submitImage(new SimpleByName($name), $x, $y, $additional)); + return ($success ? $this->getContent() : $success); + } + + /** + * Clicks the submit image by ID attribute. The owning + * form will be submitted by this. Clicking outside of + * the boundary of the coordinates will result in + * a failure. + * @param integer/string $id ID attribute of button. + * @param integer $x X-coordinate of imaginary click. + * @param integer $y Y-coordinate of imaginary click. + * @param hash $additional Additional form data. + * @return string/boolean Page on success. + * @access public + */ + function clickImageById($id, $x = 1, $y = 1, $additional = false) { + if (! ($form = &$this->_page->getFormByImage(new SimpleById($id)))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submitImage(new SimpleById($id), $x, $y, $additional)); + return ($success ? $this->getContent() : $success); + } + + /** + * Tests to see if an image exists with this + * title or alt text. + * @param string $label Image text. + * @return boolean True if present. + * @access public + */ + function isImage($label) { + return (boolean)$this->_page->getFormByImage(new SimpleByLabel($label)); + } + + /** + * Submits a form by the ID. + * @param string $id The form ID. No submit button value + * will be sent. + * @return string/boolean Page on success. + * @access public + */ + function submitFormById($id) { + if (! ($form = &$this->_page->getFormById($id))) { + return false; + } + $success = $this->_load( + $form->getAction(), + $form->submit()); + return ($success ? $this->getContent() : $success); + } + + /** + * Finds a URL by label. Will find the first link + * found with this link text by default, or a later + * one if an index is given. The match ignores case and + * white space issues. + * @param string $label Text between the anchor tags. + * @param integer $index Link position counting from zero. + * @return string/boolean URL on success. + * @access public + */ + function getLink($label, $index = 0) { + $urls = $this->_page->getUrlsByLabel($label); + if (count($urls) == 0) { + return false; + } + if (count($urls) < $index + 1) { + return false; + } + return $urls[$index]; + } + + /** + * Follows a link by label. Will click the first link + * found with this link text by default, or a later + * one if an index is given. The match ignores case and + * white space issues. + * @param string $label Text between the anchor tags. + * @param integer $index Link position counting from zero. + * @return string/boolean Page on success. + * @access public + */ + function clickLink($label, $index = 0) { + $url = $this->getLink($label, $index); + if ($url === false) { + return false; + } + $this->_load($url, new SimpleGetEncoding()); + return $this->getContent(); + } + + /** + * Finds a link by id attribute. + * @param string $id ID attribute value. + * @return string/boolean URL on success. + * @access public + */ + function getLinkById($id) { + return $this->_page->getUrlById($id); + } + + /** + * Follows a link by id attribute. + * @param string $id ID attribute value. + * @return string/boolean Page on success. + * @access public + */ + function clickLinkById($id) { + if (! ($url = $this->getLinkById($id))) { + return false; + } + $this->_load($url, new SimpleGetEncoding()); + return $this->getContent(); + } + + /** + * Clicks a visible text item. Will first try buttons, + * then links and then images. + * @param string $label Visible text or alt text. + * @return string/boolean Raw page or false. + * @access public + */ + function click($label) { + $raw = $this->clickSubmit($label); + if (! $raw) { + $raw = $this->clickLink($label); + } + if (! $raw) { + $raw = $this->clickImage($label); + } + return $raw; + } + + /** + * Tests to see if a click target exists. + * @param string $label Visible text or alt text. + * @return boolean True if target present. + * @access public + */ + function isClickable($label) { + return $this->isSubmit($label) || ($this->getLink($label) !== false) || $this->isImage($label); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/collector.php b/plugins/www/testgen4web_simpletest/lib/simpletest/collector.php new file mode 100644 index 0000000..5b8255d --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/collector.php @@ -0,0 +1,122 @@ + + * @package SimpleTest + * @subpackage UnitTester + * @version $Id: collector.php 1723 2008-04-08 00:34:10Z lastcraft $ + */ + +/** + * The basic collector for {@link GroupTest} + * + * @see collect(), GroupTest::collect() + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleCollector { + + /** + * Strips off any kind of slash at the end so as to normalise the path. + * @param string $path Path to normalise. + * @return string Path without trailing slash. + */ + function _removeTrailingSlash($path) { + if (substr($path, -1) == DIRECTORY_SEPARATOR) { + return substr($path, 0, -1); + } elseif (substr($path, -1) == '/') { + return substr($path, 0, -1); + } else { + return $path; + } + } + + /** + * Scans the directory and adds what it can. + * @param object $test Group test with {@link GroupTest::addTestFile()} method. + * @param string $path Directory to scan. + * @see _attemptToAdd() + */ + function collect(&$test, $path) { + $path = $this->_removeTrailingSlash($path); + if ($handle = opendir($path)) { + while (($entry = readdir($handle)) !== false) { + if ($this->_isHidden($entry)) { + continue; + } + $this->_handle($test, $path . DIRECTORY_SEPARATOR . $entry); + } + closedir($handle); + } + } + + /** + * This method determines what should be done with a given file and adds + * it via {@link GroupTest::addTestFile()} if necessary. + * + * This method should be overriden to provide custom matching criteria, + * such as pattern matching, recursive matching, etc. For an example, see + * {@link SimplePatternCollector::_handle()}. + * + * @param object $test Group test with {@link GroupTest::addTestFile()} method. + * @param string $filename A filename as generated by {@link collect()} + * @see collect() + * @access protected + */ + function _handle(&$test, $file) { + if (is_dir($file)) { + return; + } + $test->addTestFile($file); + } + + /** + * Tests for hidden files so as to skip them. Currently + * only tests for Unix hidden files. + * @param string $filename Plain filename. + * @return boolean True if hidden file. + * @access private + */ + function _isHidden($filename) { + return strncmp($filename, '.', 1) == 0; + } +} + +/** + * An extension to {@link SimpleCollector} that only adds files matching a + * given pattern. + * + * @package SimpleTest + * @subpackage UnitTester + * @see SimpleCollector + */ +class SimplePatternCollector extends SimpleCollector { + var $_pattern; + + /** + * + * @param string $pattern Perl compatible regex to test name against + * See {@link http://us4.php.net/manual/en/reference.pcre.pattern.syntax.php PHP's PCRE} + * for full documentation of valid pattern.s + */ + function SimplePatternCollector($pattern = '/php$/i') { + $this->_pattern = $pattern; + } + + /** + * Attempts to add files that match a given pattern. + * + * @see SimpleCollector::_handle() + * @param object $test Group test with {@link GroupTest::addTestFile()} method. + * @param string $path Directory to scan. + * @access protected + */ + function _handle(&$test, $filename) { + if (preg_match($this->_pattern, $filename)) { + parent::_handle($test, $filename); + } + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/compatibility.php b/plugins/www/testgen4web_simpletest/lib/simpletest/compatibility.php new file mode 100644 index 0000000..4e0f78a --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/compatibility.php @@ -0,0 +1,173 @@ += 0) { + eval('$copy = clone $object;'); + return $copy; + } + return $object; + } + + /** + * Identity test. Drops back to equality + types for PHP5 + * objects as the === operator counts as the + * stronger reference constraint. + * @param mixed $first Test subject. + * @param mixed $second Comparison object. + * @return boolean True if identical. + * @access public + * @static + */ + function isIdentical($first, $second) { + if (version_compare(phpversion(), '5') >= 0) { + return SimpleTestCompatibility::_isIdenticalType($first, $second); + } + if ($first != $second) { + return false; + } + return ($first === $second); + } + + /** + * Recursive type test. + * @param mixed $first Test subject. + * @param mixed $second Comparison object. + * @return boolean True if same type. + * @access private + * @static + */ + function _isIdenticalType($first, $second) { + if (gettype($first) != gettype($second)) { + return false; + } + if (is_object($first) && is_object($second)) { + if (get_class($first) != get_class($second)) { + return false; + } + return SimpleTestCompatibility::_isArrayOfIdenticalTypes( + get_object_vars($first), + get_object_vars($second)); + } + if (is_array($first) && is_array($second)) { + return SimpleTestCompatibility::_isArrayOfIdenticalTypes($first, $second); + } + if ($first !== $second) { + return false; + } + return true; + } + + /** + * Recursive type test for each element of an array. + * @param mixed $first Test subject. + * @param mixed $second Comparison object. + * @return boolean True if identical. + * @access private + * @static + */ + function _isArrayOfIdenticalTypes($first, $second) { + if (array_keys($first) != array_keys($second)) { + return false; + } + foreach (array_keys($first) as $key) { + $is_identical = SimpleTestCompatibility::_isIdenticalType( + $first[$key], + $second[$key]); + if (! $is_identical) { + return false; + } + } + return true; + } + + /** + * Test for two variables being aliases. + * @param mixed $first Test subject. + * @param mixed $second Comparison object. + * @return boolean True if same. + * @access public + * @static + */ + function isReference(&$first, &$second) { + if (version_compare(phpversion(), '5', '>=') && is_object($first)) { + return ($first === $second); + } + if (is_object($first) && is_object($second)) { + $id = uniqid("test"); + $first->$id = true; + $is_ref = isset($second->$id); + unset($first->$id); + return $is_ref; + } + $temp = $first; + $first = uniqid("test"); + $is_ref = ($first === $second); + $first = $temp; + return $is_ref; + } + + /** + * Test to see if an object is a member of a + * class hiearchy. + * @param object $object Object to test. + * @param string $class Root name of hiearchy. + * @return boolean True if class in hiearchy. + * @access public + * @static + */ + function isA($object, $class) { + if (version_compare(phpversion(), '5') >= 0) { + if (! class_exists($class, false)) { + if (function_exists('interface_exists')) { + if (! interface_exists($class, false)) { + return false; + } + } + } + eval("\$is_a = \$object instanceof $class;"); + return $is_a; + } + if (function_exists('is_a')) { + return is_a($object, $class); + } + return ((strtolower($class) == get_class($object)) + or (is_subclass_of($object, $class))); + } + + /** + * Sets a socket timeout for each chunk. + * @param resource $handle Socket handle. + * @param integer $timeout Limit in seconds. + * @access public + * @static + */ + function setTimeout($handle, $timeout) { + if (function_exists('stream_set_timeout')) { + stream_set_timeout($handle, $timeout, 0); + } elseif (function_exists('socket_set_timeout')) { + socket_set_timeout($handle, $timeout, 0); + } elseif (function_exists('set_socket_timeout')) { + set_socket_timeout($handle, $timeout, 0); + } + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/cookies.php b/plugins/www/testgen4web_simpletest/lib/simpletest/cookies.php new file mode 100644 index 0000000..ed1c025 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/cookies.php @@ -0,0 +1,380 @@ +_host = false; + $this->_name = $name; + $this->_value = $value; + $this->_path = ($path ? $this->_fixPath($path) : "/"); + $this->_expiry = false; + if (is_string($expiry)) { + $this->_expiry = strtotime($expiry); + } elseif (is_integer($expiry)) { + $this->_expiry = $expiry; + } + $this->_is_secure = $is_secure; + } + + /** + * Sets the host. The cookie rules determine + * that the first two parts are taken for + * certain TLDs and three for others. If the + * new host does not match these rules then the + * call will fail. + * @param string $host New hostname. + * @return boolean True if hostname is valid. + * @access public + */ + function setHost($host) { + if ($host = $this->_truncateHost($host)) { + $this->_host = $host; + return true; + } + return false; + } + + /** + * Accessor for the truncated host to which this + * cookie applies. + * @return string Truncated hostname. + * @access public + */ + function getHost() { + return $this->_host; + } + + /** + * Test for a cookie being valid for a host name. + * @param string $host Host to test against. + * @return boolean True if the cookie would be valid + * here. + */ + function isValidHost($host) { + return ($this->_truncateHost($host) === $this->getHost()); + } + + /** + * Extracts just the domain part that determines a + * cookie's host validity. + * @param string $host Host name to truncate. + * @return string Domain or false on a bad host. + * @access private + */ + function _truncateHost($host) { + $tlds = SimpleUrl::getAllTopLevelDomains(); + if (preg_match('/[a-z\-]+\.(' . $tlds . ')$/i', $host, $matches)) { + return $matches[0]; + } elseif (preg_match('/[a-z\-]+\.[a-z\-]+\.[a-z\-]+$/i', $host, $matches)) { + return $matches[0]; + } + return false; + } + + /** + * Accessor for name. + * @return string Cookie key. + * @access public + */ + function getName() { + return $this->_name; + } + + /** + * Accessor for value. A deleted cookie will + * have an empty string for this. + * @return string Cookie value. + * @access public + */ + function getValue() { + return $this->_value; + } + + /** + * Accessor for path. + * @return string Valid cookie path. + * @access public + */ + function getPath() { + return $this->_path; + } + + /** + * Tests a path to see if the cookie applies + * there. The test path must be longer or + * equal to the cookie path. + * @param string $path Path to test against. + * @return boolean True if cookie valid here. + * @access public + */ + function isValidPath($path) { + return (strncmp( + $this->_fixPath($path), + $this->getPath(), + strlen($this->getPath())) == 0); + } + + /** + * Accessor for expiry. + * @return string Expiry string. + * @access public + */ + function getExpiry() { + if (! $this->_expiry) { + return false; + } + return gmdate("D, d M Y H:i:s", $this->_expiry) . " GMT"; + } + + /** + * Test to see if cookie is expired against + * the cookie format time or timestamp. + * Will give true for a session cookie. + * @param integer/string $now Time to test against. Result + * will be false if this time + * is later than the cookie expiry. + * Can be either a timestamp integer + * or a cookie format date. + * @access public + */ + function isExpired($now) { + if (! $this->_expiry) { + return true; + } + if (is_string($now)) { + $now = strtotime($now); + } + return ($this->_expiry < $now); + } + + /** + * Ages the cookie by the specified number of + * seconds. + * @param integer $interval In seconds. + * @public + */ + function agePrematurely($interval) { + if ($this->_expiry) { + $this->_expiry -= $interval; + } + } + + /** + * Accessor for the secure flag. + * @return boolean True if cookie needs SSL. + * @access public + */ + function isSecure() { + return $this->_is_secure; + } + + /** + * Adds a trailing and leading slash to the path + * if missing. + * @param string $path Path to fix. + * @access private + */ + function _fixPath($path) { + if (substr($path, 0, 1) != '/') { + $path = '/' . $path; + } + if (substr($path, -1, 1) != '/') { + $path .= '/'; + } + return $path; + } +} + +/** + * Repository for cookies. This stuff is a + * tiny bit browser dependent. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleCookieJar { + var $_cookies; + + /** + * Constructor. Jar starts empty. + * @access public + */ + function SimpleCookieJar() { + $this->_cookies = array(); + } + + /** + * Removes expired and temporary cookies as if + * the browser was closed and re-opened. + * @param string/integer $now Time to test expiry against. + * @access public + */ + function restartSession($date = false) { + $surviving_cookies = array(); + for ($i = 0; $i < count($this->_cookies); $i++) { + if (! $this->_cookies[$i]->getValue()) { + continue; + } + if (! $this->_cookies[$i]->getExpiry()) { + continue; + } + if ($date && $this->_cookies[$i]->isExpired($date)) { + continue; + } + $surviving_cookies[] = $this->_cookies[$i]; + } + $this->_cookies = $surviving_cookies; + } + + /** + * Ages all cookies in the cookie jar. + * @param integer $interval The old session is moved + * into the past by this number + * of seconds. Cookies now over + * age will be removed. + * @access public + */ + function agePrematurely($interval) { + for ($i = 0; $i < count($this->_cookies); $i++) { + $this->_cookies[$i]->agePrematurely($interval); + } + } + + /** + * Sets an additional cookie. If a cookie has + * the same name and path it is replaced. + * @param string $name Cookie key. + * @param string $value Value of cookie. + * @param string $host Host upon which the cookie is valid. + * @param string $path Cookie path if not host wide. + * @param string $expiry Expiry date. + * @access public + */ + function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { + $cookie = new SimpleCookie($name, $value, $path, $expiry); + if ($host) { + $cookie->setHost($host); + } + $this->_cookies[$this->_findFirstMatch($cookie)] = $cookie; + } + + /** + * Finds a matching cookie to write over or the + * first empty slot if none. + * @param SimpleCookie $cookie Cookie to write into jar. + * @return integer Available slot. + * @access private + */ + function _findFirstMatch($cookie) { + for ($i = 0; $i < count($this->_cookies); $i++) { + $is_match = $this->_isMatch( + $cookie, + $this->_cookies[$i]->getHost(), + $this->_cookies[$i]->getPath(), + $this->_cookies[$i]->getName()); + if ($is_match) { + return $i; + } + } + return count($this->_cookies); + } + + /** + * Reads the most specific cookie value from the + * browser cookies. Looks for the longest path that + * matches. + * @param string $host Host to search. + * @param string $path Applicable path. + * @param string $name Name of cookie to read. + * @return string False if not present, else the + * value as a string. + * @access public + */ + function getCookieValue($host, $path, $name) { + $longest_path = ''; + foreach ($this->_cookies as $cookie) { + if ($this->_isMatch($cookie, $host, $path, $name)) { + if (strlen($cookie->getPath()) > strlen($longest_path)) { + $value = $cookie->getValue(); + $longest_path = $cookie->getPath(); + } + } + } + return (isset($value) ? $value : false); + } + + /** + * Tests cookie for matching against search + * criteria. + * @param SimpleTest $cookie Cookie to test. + * @param string $host Host must match. + * @param string $path Cookie path must be shorter than + * this path. + * @param string $name Name must match. + * @return boolean True if matched. + * @access private + */ + function _isMatch($cookie, $host, $path, $name) { + if ($cookie->getName() != $name) { + return false; + } + if ($host && $cookie->getHost() && ! $cookie->isValidHost($host)) { + return false; + } + if (! $cookie->isValidPath($path)) { + return false; + } + return true; + } + + /** + * Uses a URL to sift relevant cookies by host and + * path. Results are list of strings of form "name=value". + * @param SimpleUrl $url Url to select by. + * @return array Valid name and value pairs. + * @access public + */ + function selectAsPairs($url) { + $pairs = array(); + foreach ($this->_cookies as $cookie) { + if ($this->_isMatch($cookie, $url->getHost(), $url->getPath(), $cookie->getName())) { + $pairs[] = $cookie->getName() . '=' . $cookie->getValue(); + } + } + return $pairs; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/default_reporter.php b/plugins/www/testgen4web_simpletest/lib/simpletest/default_reporter.php new file mode 100644 index 0000000..bd4c6a1 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/default_reporter.php @@ -0,0 +1,133 @@ + '_case', 'c' => '_case', + 'test' => '_test', 't' => '_test', + 'xml' => '_xml', 'x' => '_xml'); + var $_case = ''; + var $_test = ''; + var $_xml = false; + var $_no_skips = false; + + /** + * Parses raw command line arguments into object properties. + * @param string $arguments Raw commend line arguments. + */ + function SimpleCommandLineParser($arguments) { + if (! is_array($arguments)) { + return; + } + foreach ($arguments as $i => $argument) { + if (preg_match('/^--?(test|case|t|c)=(.+)$/', $argument, $matches)) { + $property = $this->_to_property[$matches[1]]; + $this->$property = $matches[2]; + } elseif (preg_match('/^--?(test|case|t|c)$/', $argument, $matches)) { + $property = $this->_to_property[$matches[1]]; + if (isset($arguments[$i + 1])) { + $this->$property = $arguments[$i + 1]; + } + } elseif (preg_match('/^--?(xml|x)$/', $argument)) { + $this->_xml = true; + } elseif (preg_match('/^--?(no-skip|no-skips|s)$/', $argument)) { + $this->_no_skips = true; + } + } + } + + /** + * Run only this test. + * @return string Test name to run. + * @access public + */ + function getTest() { + return $this->_test; + } + + /** + * Run only this test suite. + * @return string Test class name to run. + * @access public + */ + function getTestCase() { + return $this->_case; + } + + /** + * Output should be XML or not. + * @return boolean True if XML desired. + * @access public + */ + function isXml() { + return $this->_xml; + } + + /** + * Output should suppress skip messages. + * @return boolean True for no skips. + * @access public + */ + function noSkips() { + return $this->_no_skips; + } +} + +/** + * The default reporter used by SimpleTest's autorun + * feature. The actual reporters used are dependency + * injected and can be overridden. + * @package SimpleTest + * @subpackage UnitTester + */ +class DefaultReporter extends SimpleReporterDecorator { + + /** + * Assembles the appopriate reporter for the environment. + */ + function DefaultReporter() { + if (SimpleReporter::inCli()) { + global $argv; + $parser = new SimpleCommandLineParser($argv); + $interfaces = $parser->isXml() ? array('XmlReporter') : array('TextReporter'); + $reporter = &new SelectiveReporter( + SimpleTest::preferred($interfaces), + $parser->getTestCase(), + $parser->getTest()); + if ($parser->noSkips()) { + $reporter = &new NoSkipsReporter($reporter); + } + } else { + $reporter = &new SelectiveReporter( + SimpleTest::preferred('HtmlReporter'), + @$_GET['c'], + @$_GET['t']); + if (@$_GET['skips'] == 'no' || @$_GET['show-skips'] == 'no') { + $reporter = &new NoSkipsReporter($reporter); + } + } + $this->SimpleReporterDecorator($reporter); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/detached.php b/plugins/www/testgen4web_simpletest/lib/simpletest/detached.php new file mode 100644 index 0000000..e323d8c --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/detached.php @@ -0,0 +1,96 @@ +_command = $command; + $this->_dry_command = $dry_command ? $dry_command : $command; + $this->_size = false; + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_command; + } + + /** + * Runs the top level test for this class. Currently + * reads the data as a single chunk. I'll fix this + * once I have added iteration to the browser. + * @param SimpleReporter $reporter Target of test results. + * @returns boolean True if no failures. + * @access public + */ + function run(&$reporter) { + $shell = &new SimpleShell(); + $shell->execute($this->_command); + $parser = &$this->_createParser($reporter); + if (! $parser->parse($shell->getOutput())) { + trigger_error('Cannot parse incoming XML from [' . $this->_command . ']'); + return false; + } + return true; + } + + /** + * Accessor for the number of subtests. + * @return integer Number of test cases. + * @access public + */ + function getSize() { + if ($this->_size === false) { + $shell = &new SimpleShell(); + $shell->execute($this->_dry_command); + $reporter = &new SimpleReporter(); + $parser = &$this->_createParser($reporter); + if (! $parser->parse($shell->getOutput())) { + trigger_error('Cannot parse incoming XML from [' . $this->_dry_command . ']'); + return false; + } + $this->_size = $reporter->getTestCaseCount(); + } + return $this->_size; + } + + /** + * Creates the XML parser. + * @param SimpleReporter $reporter Target of test results. + * @return SimpleTestXmlListener XML reader. + * @access protected + */ + function &_createParser(&$reporter) { + return new SimpleTestXmlParser($reporter); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/dumper.php b/plugins/www/testgen4web_simpletest/lib/simpletest/dumper.php new file mode 100644 index 0000000..2d75985 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/dumper.php @@ -0,0 +1,360 @@ +getType($value); + switch($type) { + case "Null": + return "NULL"; + case "Boolean": + return "Boolean: " . ($value ? "true" : "false"); + case "Array": + return "Array: " . count($value) . " items"; + case "Object": + return "Object: of " . get_class($value); + case "String": + return "String: " . $this->clipString($value, 200); + default: + return "$type: $value"; + } + return "Unknown"; + } + + /** + * Gets the string representation of a type. + * @param mixed $value Variable to check against. + * @return string Type. + * @access public + */ + function getType($value) { + if (! isset($value)) { + return "Null"; + } elseif (is_bool($value)) { + return "Boolean"; + } elseif (is_string($value)) { + return "String"; + } elseif (is_integer($value)) { + return "Integer"; + } elseif (is_float($value)) { + return "Float"; + } elseif (is_array($value)) { + return "Array"; + } elseif (is_resource($value)) { + return "Resource"; + } elseif (is_object($value)) { + return "Object"; + } + return "Unknown"; + } + + /** + * Creates a human readable description of the + * difference between two variables. Uses a + * dynamic call. + * @param mixed $first First variable. + * @param mixed $second Value to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Description of difference. + * @access public + */ + function describeDifference($first, $second, $identical = false) { + if ($identical) { + if (! $this->_isTypeMatch($first, $second)) { + return "with type mismatch as [" . $this->describeValue($first) . + "] does not match [" . $this->describeValue($second) . "]"; + } + } + $type = $this->getType($first); + if ($type == "Unknown") { + return "with unknown type"; + } + $method = '_describe' . $type . 'Difference'; + return $this->$method($first, $second, $identical); + } + + /** + * Tests to see if types match. + * @param mixed $first First variable. + * @param mixed $second Value to compare with. + * @return boolean True if matches. + * @access private + */ + function _isTypeMatch($first, $second) { + return ($this->getType($first) == $this->getType($second)); + } + + /** + * Clips a string to a maximum length. + * @param string $value String to truncate. + * @param integer $size Minimum string size to show. + * @param integer $position Centre of string section. + * @return string Shortened version. + * @access public + */ + function clipString($value, $size, $position = 0) { + $length = strlen($value); + if ($length <= $size) { + return $value; + } + $position = min($position, $length); + $start = ($size/2 > $position ? 0 : $position - $size/2); + if ($start + $size > $length) { + $start = $length - $size; + } + $value = substr($value, $start, $size); + return ($start > 0 ? "..." : "") . $value . ($start + $size < $length ? "..." : ""); + } + + /** + * Creates a human readable description of the + * difference between two variables. The minimal + * version. + * @param null $first First value. + * @param mixed $second Value to compare with. + * @return string Human readable description. + * @access private + */ + function _describeGenericDifference($first, $second) { + return "as [" . $this->describeValue($first) . + "] does not match [" . + $this->describeValue($second) . "]"; + } + + /** + * Creates a human readable description of the + * difference between a null and another variable. + * @param null $first First null. + * @param mixed $second Null to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeNullDifference($first, $second, $identical) { + return $this->_describeGenericDifference($first, $second); + } + + /** + * Creates a human readable description of the + * difference between a boolean and another variable. + * @param boolean $first First boolean. + * @param mixed $second Boolean to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeBooleanDifference($first, $second, $identical) { + return $this->_describeGenericDifference($first, $second); + } + + /** + * Creates a human readable description of the + * difference between a string and another variable. + * @param string $first First string. + * @param mixed $second String to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeStringDifference($first, $second, $identical) { + if (is_object($second) || is_array($second)) { + return $this->_describeGenericDifference($first, $second); + } + $position = $this->_stringDiffersAt($first, $second); + $message = "at character $position"; + $message .= " with [" . + $this->clipString($first, 200, $position) . "] and [" . + $this->clipString($second, 200, $position) . "]"; + return $message; + } + + /** + * Creates a human readable description of the + * difference between an integer and another variable. + * @param integer $first First number. + * @param mixed $second Number to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeIntegerDifference($first, $second, $identical) { + if (is_object($second) || is_array($second)) { + return $this->_describeGenericDifference($first, $second); + } + return "because [" . $this->describeValue($first) . + "] differs from [" . + $this->describeValue($second) . "] by " . + abs($first - $second); + } + + /** + * Creates a human readable description of the + * difference between two floating point numbers. + * @param float $first First float. + * @param mixed $second Float to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeFloatDifference($first, $second, $identical) { + if (is_object($second) || is_array($second)) { + return $this->_describeGenericDifference($first, $second); + } + return "because [" . $this->describeValue($first) . + "] differs from [" . + $this->describeValue($second) . "] by " . + abs($first - $second); + } + + /** + * Creates a human readable description of the + * difference between two arrays. + * @param array $first First array. + * @param mixed $second Array to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeArrayDifference($first, $second, $identical) { + if (! is_array($second)) { + return $this->_describeGenericDifference($first, $second); + } + if (! $this->_isMatchingKeys($first, $second, $identical)) { + return "as key list [" . + implode(", ", array_keys($first)) . "] does not match key list [" . + implode(", ", array_keys($second)) . "]"; + } + foreach (array_keys($first) as $key) { + if ($identical && ($first[$key] === $second[$key])) { + continue; + } + if (! $identical && ($first[$key] == $second[$key])) { + continue; + } + return "with member [$key] " . $this->describeDifference( + $first[$key], + $second[$key], + $identical); + } + return ""; + } + + /** + * Compares two arrays to see if their key lists match. + * For an identical match, the ordering and types of the keys + * is significant. + * @param array $first First array. + * @param array $second Array to compare with. + * @param boolean $identical If true then type anomolies count. + * @return boolean True if matching. + * @access private + */ + function _isMatchingKeys($first, $second, $identical) { + $first_keys = array_keys($first); + $second_keys = array_keys($second); + if ($identical) { + return ($first_keys === $second_keys); + } + sort($first_keys); + sort($second_keys); + return ($first_keys == $second_keys); + } + + /** + * Creates a human readable description of the + * difference between a resource and another variable. + * @param resource $first First resource. + * @param mixed $second Resource to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeResourceDifference($first, $second, $identical) { + return $this->_describeGenericDifference($first, $second); + } + + /** + * Creates a human readable description of the + * difference between two objects. + * @param object $first First object. + * @param mixed $second Object to compare with. + * @param boolean $identical If true then type anomolies count. + * @return string Human readable description. + * @access private + */ + function _describeObjectDifference($first, $second, $identical) { + if (! is_object($second)) { + return $this->_describeGenericDifference($first, $second); + } + return $this->_describeArrayDifference( + get_object_vars($first), + get_object_vars($second), + $identical); + } + + /** + * Find the first character position that differs + * in two strings by binary chop. + * @param string $first First string. + * @param string $second String to compare with. + * @return integer Position of first differing + * character. + * @access private + */ + function _stringDiffersAt($first, $second) { + if (! $first || ! $second) { + return 0; + } + if (strlen($first) < strlen($second)) { + list($first, $second) = array($second, $first); + } + $position = 0; + $step = strlen($first); + while ($step > 1) { + $step = (integer)(($step + 1) / 2); + if (strncmp($first, $second, $position + $step) == 0) { + $position += $step; + } + } + return $position; + } + + /** + * Sends a formatted dump of a variable to a string. + * @param mixed $variable Variable to display. + * @return string Output from print_r(). + * @access public + * @static + */ + function dump($variable) { + ob_start(); + print_r($variable); + $formatted = ob_get_contents(); + ob_end_clean(); + return $formatted; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/eclipse.php b/plugins/www/testgen4web_simpletest/lib/simpletest/eclipse.php new file mode 100644 index 0000000..0f1a4fc --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/eclipse.php @@ -0,0 +1,307 @@ +_listener = &$listener; + $this->SimpleScorer(); + $this->_case = ""; + $this->_group = ""; + $this->_method = ""; + $this->_cc = $cc; + $this->_error = false; + $this->_fail = false; + } + + /** + * Means to display human readable object comparisons. + * @return SimpleDumper Visual comparer. + */ + function getDumper() { + return new SimpleDumper(); + } + + /** + * Localhost connection from Eclipse. + * @param integer $port Port to connect to Eclipse. + * @param string $host Normally localhost. + * @return SimpleSocket Connection to Eclipse. + */ + function &createListener($port, $host="127.0.0.1"){ + $tmplistener = &new SimpleSocket($host, $port, 5); + return $tmplistener; + } + + /** + * Wraps the test in an output buffer. + * @param SimpleInvoker $invoker Current test runner. + * @return EclipseInvoker Decorator with output buffering. + * @access public + */ + function &createInvoker(&$invoker){ + $eclinvoker = &new EclipseInvoker($invoker, $this->_listener); + return $eclinvoker; + } + + /** + * C style escaping. + * @param string $raw String with backslashes, quotes and whitespace. + * @return string Replaced with C backslashed tokens. + */ + function escapeVal($raw){ + $needle = array("\\","\"","/","\b","\f","\n","\r","\t"); + $replace = array('\\\\','\"','\/','\b','\f','\n','\r','\t'); + return str_replace($needle, $replace, $raw); + } + + /** + * Stash the first passing item. Clicking the test + * item goes to first pass. + * @param string $message Test message, but we only wnat the first. + * @access public + */ + function paintPass($message){ + if (! $this->_pass){ + $this->_message = $this->escapeVal($message); + } + $this->_pass = true; + } + + /** + * Stash the first failing item. Clicking the test + * item goes to first fail. + * @param string $message Test message, but we only wnat the first. + * @access public + */ + function paintFail($message){ + //only get the first failure or error + if (! $this->_fail && ! $this->_error){ + $this->_fail = true; + $this->_message = $this->escapeVal($message); + $this->_listener->write('{status:"fail",message:"'.$this->_message.'",group:"'.$this->_group.'",case:"'.$this->_case.'",method:"'.$this->_method.'"}'); + } + } + + /** + * Stash the first error. Clicking the test + * item goes to first error. + * @param string $message Test message, but we only wnat the first. + * @access public + */ + function paintError($message){ + if (! $this->_fail && ! $this->_error){ + $this->_error = true; + $this->_message = $this->escapeVal($message); + $this->_listener->write('{status:"error",message:"'.$this->_message.'",group:"'.$this->_group.'",case:"'.$this->_case.'",method:"'.$this->_method.'"}'); + } + } + + + /** + * Stash the first exception. Clicking the test + * item goes to first message. + * @param string $message Test message, but we only wnat the first. + * @access public + */ + function paintException($exception){ + if (! $this->_fail && ! $this->_error){ + $this->_error = true; + $message = 'Unexpected exception of type[' . get_class($exception) . + '] with message [' . $exception->getMessage() . '] in [' . + $exception->getFile() .' line '. $exception->getLine() . ']'; + $this->_message = $this->escapeVal($message); + $this->_listener->write( + '{status:"error",message:"' . $this->_message . '",group:"' . + $this->_group . '",case:"' . $this->_case . '",method:"' . $this->_method + . '"}'); + } + } + + + /** + * We don't display any special header. + * @param string $test_name First test top level + * to start. + * @access public + */ + function paintHeader($test_name) { + } + + /** + * We don't display any special footer. + * @param string $test_name The top level test. + * @access public + */ + function paintFooter($test_name) { + } + + /** + * Paints nothing at the start of a test method, but stash + * the method name for later. + * @param string $test_name Name of test that is starting. + * @access public + */ + function paintMethodStart($method) { + $this->_pass = false; + $this->_fail = false; + $this->_error = false; + $this->_method = $this->escapeVal($method); + } + + /** + * Only send one message if the test passes, after that + * suppress the message. + * @param string $test_name Name of test that is ending. + * @access public + */ + function paintMethodEnd($method){ + if ($this->_fail || $this->_error || ! $this->_pass){ + } else { + $this->_listener->write( + '{status:"pass",message:"' . $this->_message . '",group:"' . + $this->_group . '",case:"' . $this->_case . '",method:"' . + $this->_method . '"}'); + } + } + + /** + * Stashes the test case name for the later failure message. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseStart($case){ + $this->_case = $this->escapeVal($case); + } + + /** + * Drops the name. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseEnd($case){ + $this->_case = ""; + } + + /** + * Stashes the name of the test suite. Starts test coverage + * if enabled. + * @param string $group Name of test or other label. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($group, $size){ + $this->_group = $this->escapeVal($group); + if ($this->_cc){ + if (extension_loaded('xdebug')){ + xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); + } + } + } + + /** + * Paints coverage report if enabled. + * @param string $group Name of test or other label. + * @access public + */ + function paintGroupEnd($group){ + $this->_group = ""; + $cc = ""; + if ($this->_cc){ + if (extension_loaded('xdebug')){ + $arrfiles = xdebug_get_code_coverage(); + xdebug_stop_code_coverage(); + $thisdir = dirname(__FILE__); + $thisdirlen = strlen($thisdir); + foreach ($arrfiles as $index=>$file){ + if (substr($index, 0, $thisdirlen)===$thisdir){ + continue; + } + $lcnt = 0; + $ccnt = 0; + foreach ($file as $line){ + if ($line == -2){ + continue; + } + $lcnt++; + if ($line==1){ + $ccnt++; + } + } + if ($lcnt > 0){ + $cc .= round(($ccnt/$lcnt) * 100, 2) . '%'; + }else{ + $cc .= "0.00%"; + } + $cc.= "\t". $index . "\n"; + } + } + } + $this->_listener->write('{status:"coverage",message:"' . + EclipseReporter::escapeVal($cc) . '"}'); + } +} + +/** + * Invoker decorator for Eclipse. Captures output until + * the end of the test. + * @package SimpleTest + * @subpackage Eclipse + */ +class EclipseInvoker extends SimpleInvokerDecorator{ + function EclipseInvoker(&$invoker, &$listener) { + $this->_listener = &$listener; + $this->SimpleInvokerDecorator($invoker); + } + + /** + * Starts output buffering. + * @param string $method Test method to call. + * @access public + */ + function before($method){ + ob_start(); + $this->_invoker->before($method); + } + + /** + * Stops output buffering and send the captured output + * to the listener. + * @param string $method Test method to call. + * @access public + */ + function after($method) { + $this->_invoker->after($method); + $output = ob_get_contents(); + ob_end_clean(); + if ($output !== ""){ + $result = $this->_listener->write('{status:"info",message:"' . + EclipseReporter::escapeVal($output) . '"}'); + } + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/encoding.php b/plugins/www/testgen4web_simpletest/lib/simpletest/encoding.php new file mode 100644 index 0000000..112fe33 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/encoding.php @@ -0,0 +1,552 @@ +_key = $key; + $this->_value = $value; + } + + /** + * The pair as a single string. + * @return string Encoded pair. + * @access public + */ + function asRequest() { + return urlencode($this->_key) . '=' . urlencode($this->_value); + } + + /** + * The MIME part as a string. + * @return string MIME part encoding. + * @access public + */ + function asMime() { + $part = 'Content-Disposition: form-data; '; + $part .= "name=\"" . $this->_key . "\"\r\n"; + $part .= "\r\n" . $this->_value; + return $part; + } + + /** + * Is this the value we are looking for? + * @param string $key Identifier. + * @return boolean True if matched. + * @access public + */ + function isKey($key) { + return $key == $this->_key; + } + + /** + * Is this the value we are looking for? + * @return string Identifier. + * @access public + */ + function getKey() { + return $this->_key; + } + + /** + * Is this the value we are looking for? + * @return string Content. + * @access public + */ + function getValue() { + return $this->_value; + } +} + +/** + * Single post parameter. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleAttachment { + var $_key; + var $_content; + var $_filename; + + /** + * Stashes the data for rendering later. + * @param string $key Key to add value to. + * @param string $content Raw data. + * @param hash $filename Original filename. + */ + function SimpleAttachment($key, $content, $filename) { + $this->_key = $key; + $this->_content = $content; + $this->_filename = $filename; + } + + /** + * The pair as a single string. + * @return string Encoded pair. + * @access public + */ + function asRequest() { + return ''; + } + + /** + * The MIME part as a string. + * @return string MIME part encoding. + * @access public + */ + function asMime() { + $part = 'Content-Disposition: form-data; '; + $part .= 'name="' . $this->_key . '"; '; + $part .= 'filename="' . $this->_filename . '"'; + $part .= "\r\nContent-Type: " . $this->_deduceMimeType(); + $part .= "\r\n\r\n" . $this->_content; + return $part; + } + + /** + * Attempts to figure out the MIME type from the + * file extension and the content. + * @return string MIME type. + * @access private + */ + function _deduceMimeType() { + if ($this->_isOnlyAscii($this->_content)) { + return 'text/plain'; + } + return 'application/octet-stream'; + } + + /** + * Tests each character is in the range 0-127. + * @param string $ascii String to test. + * @access private + */ + function _isOnlyAscii($ascii) { + for ($i = 0, $length = strlen($ascii); $i < $length; $i++) { + if (ord($ascii[$i]) > 127) { + return false; + } + } + return true; + } + + /** + * Is this the value we are looking for? + * @param string $key Identifier. + * @return boolean True if matched. + * @access public + */ + function isKey($key) { + return $key == $this->_key; + } + + /** + * Is this the value we are looking for? + * @return string Identifier. + * @access public + */ + function getKey() { + return $this->_key; + } + + /** + * Is this the value we are looking for? + * @return string Content. + * @access public + */ + function getValue() { + return $this->_filename; + } +} + +/** + * Bundle of GET/POST parameters. Can include + * repeated parameters. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleEncoding { + var $_request; + + /** + * Starts empty. + * @param array $query Hash of parameters. + * Multiple values are + * as lists on a single key. + * @access public + */ + function SimpleEncoding($query = false) { + if (! $query) { + $query = array(); + } + $this->clear(); + $this->merge($query); + } + + /** + * Empties the request of parameters. + * @access public + */ + function clear() { + $this->_request = array(); + } + + /** + * Adds a parameter to the query. + * @param string $key Key to add value to. + * @param string/array $value New data. + * @access public + */ + function add($key, $value) { + if ($value === false) { + return; + } + if (is_array($value)) { + foreach ($value as $item) { + $this->_addPair($key, $item); + } + } else { + $this->_addPair($key, $value); + } + } + + /** + * Adds a new value into the request. + * @param string $key Key to add value to. + * @param string/array $value New data. + * @access private + */ + function _addPair($key, $value) { + $this->_request[] = new SimpleEncodedPair($key, $value); + } + + /** + * Adds a MIME part to the query. Does nothing for a + * form encoded packet. + * @param string $key Key to add value to. + * @param string $content Raw data. + * @param hash $filename Original filename. + * @access public + */ + function attach($key, $content, $filename) { + $this->_request[] = new SimpleAttachment($key, $content, $filename); + } + + /** + * Adds a set of parameters to this query. + * @param array/SimpleQueryString $query Multiple values are + * as lists on a single key. + * @access public + */ + function merge($query) { + if (is_object($query)) { + $this->_request = array_merge($this->_request, $query->getAll()); + } elseif (is_array($query)) { + foreach ($query as $key => $value) { + $this->add($key, $value); + } + } + } + + /** + * Accessor for single value. + * @return string/array False if missing, string + * if present and array if + * multiple entries. + * @access public + */ + function getValue($key) { + $values = array(); + foreach ($this->_request as $pair) { + if ($pair->isKey($key)) { + $values[] = $pair->getValue(); + } + } + if (count($values) == 0) { + return false; + } elseif (count($values) == 1) { + return $values[0]; + } else { + return $values; + } + } + + /** + * Accessor for listing of pairs. + * @return array All pair objects. + * @access public + */ + function getAll() { + return $this->_request; + } + + /** + * Renders the query string as a URL encoded + * request part. + * @return string Part of URL. + * @access protected + */ + function _encode() { + $statements = array(); + foreach ($this->_request as $pair) { + if ($statement = $pair->asRequest()) { + $statements[] = $statement; + } + } + return implode('&', $statements); + } +} + +/** + * Bundle of GET parameters. Can include + * repeated parameters. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleGetEncoding extends SimpleEncoding { + + /** + * Starts empty. + * @param array $query Hash of parameters. + * Multiple values are + * as lists on a single key. + * @access public + */ + function SimpleGetEncoding($query = false) { + $this->SimpleEncoding($query); + } + + /** + * HTTP request method. + * @return string Always GET. + * @access public + */ + function getMethod() { + return 'GET'; + } + + /** + * Writes no extra headers. + * @param SimpleSocket $socket Socket to write to. + * @access public + */ + function writeHeadersTo(&$socket) { + } + + /** + * No data is sent to the socket as the data is encoded into + * the URL. + * @param SimpleSocket $socket Socket to write to. + * @access public + */ + function writeTo(&$socket) { + } + + /** + * Renders the query string as a URL encoded + * request part for attaching to a URL. + * @return string Part of URL. + * @access public + */ + function asUrlRequest() { + return $this->_encode(); + } +} + +/** + * Bundle of URL parameters for a HEAD request. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleHeadEncoding extends SimpleGetEncoding { + + /** + * Starts empty. + * @param array $query Hash of parameters. + * Multiple values are + * as lists on a single key. + * @access public + */ + function SimpleHeadEncoding($query = false) { + $this->SimpleGetEncoding($query); + } + + /** + * HTTP request method. + * @return string Always HEAD. + * @access public + */ + function getMethod() { + return 'HEAD'; + } +} + +/** + * Bundle of POST parameters. Can include + * repeated parameters. + * @package SimpleTest + * @subpackage WebTester + */ +class SimplePostEncoding extends SimpleEncoding { + + /** + * Starts empty. + * @param array $query Hash of parameters. + * Multiple values are + * as lists on a single key. + * @access public + */ + function SimplePostEncoding($query = false) { + if (is_array($query) and $this->hasMoreThanOneLevel($query)) { + $query = $this->rewriteArrayWithMultipleLevels($query); + } + $this->SimpleEncoding($query); + } + + function hasMoreThanOneLevel($query) { + foreach ($query as $key => $value) { + if (is_array($value)) { + return true; + } + } + return false; + } + + function rewriteArrayWithMultipleLevels($query) { + $query_ = array(); + foreach ($query as $key => $value) { + if (is_array($value)) { + foreach ($value as $sub_key => $sub_value) { + $query_[$key."[".$sub_key."]"] = $sub_value; + } + } else { + $query_[$key] = $value; + } + } + if ($this->hasMoreThanOneLevel($query_)) { + $query_ = $this->rewriteArrayWithMultipleLevels($query_); + } + + return $query_; + } + + + /** + * HTTP request method. + * @return string Always POST. + * @access public + */ + function getMethod() { + return 'POST'; + } + + /** + * Dispatches the form headers down the socket. + * @param SimpleSocket $socket Socket to write to. + * @access public + */ + function writeHeadersTo(&$socket) { + $socket->write("Content-Length: " . (integer)strlen($this->_encode()) . "\r\n"); + $socket->write("Content-Type: application/x-www-form-urlencoded\r\n"); + } + + /** + * Dispatches the form data down the socket. + * @param SimpleSocket $socket Socket to write to. + * @access public + */ + function writeTo(&$socket) { + $socket->write($this->_encode()); + } + + /** + * Renders the query string as a URL encoded + * request part for attaching to a URL. + * @return string Part of URL. + * @access public + */ + function asUrlRequest() { + return ''; + } +} + +/** + * Bundle of POST parameters in the multipart + * format. Can include file uploads. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleMultipartEncoding extends SimplePostEncoding { + var $_boundary; + + /** + * Starts empty. + * @param array $query Hash of parameters. + * Multiple values are + * as lists on a single key. + * @access public + */ + function SimpleMultipartEncoding($query = false, $boundary = false) { + $this->SimplePostEncoding($query); + $this->_boundary = ($boundary === false ? uniqid('st') : $boundary); + } + + /** + * Dispatches the form headers down the socket. + * @param SimpleSocket $socket Socket to write to. + * @access public + */ + function writeHeadersTo(&$socket) { + $socket->write("Content-Length: " . (integer)strlen($this->_encode()) . "\r\n"); + $socket->write("Content-Type: multipart/form-data, boundary=" . $this->_boundary . "\r\n"); + } + + /** + * Dispatches the form data down the socket. + * @param SimpleSocket $socket Socket to write to. + * @access public + */ + function writeTo(&$socket) { + $socket->write($this->_encode()); + } + + /** + * Renders the query string as a URL encoded + * request part. + * @return string Part of URL. + * @access public + */ + function _encode() { + $stream = ''; + foreach ($this->_request as $pair) { + $stream .= "--" . $this->_boundary . "\r\n"; + $stream .= $pair->asMime() . "\r\n"; + } + $stream .= "--" . $this->_boundary . "--\r\n"; + return $stream; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/errors.php b/plugins/www/testgen4web_simpletest/lib/simpletest/errors.php new file mode 100644 index 0000000..5a07885 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/errors.php @@ -0,0 +1,288 @@ +SimpleInvokerDecorator($invoker); + } + + /** + * Invokes a test method and dispatches any + * untrapped errors. Called back from + * the visiting runner. + * @param string $method Test method to call. + * @access public + */ + function invoke($method) { + $queue = &$this->_createErrorQueue(); + set_error_handler('SimpleTestErrorHandler'); + parent::invoke($method); + restore_error_handler(); + $queue->tally(); + } + + /** + * Wires up the error queue for a single test. + * @return SimpleErrorQueue Queue connected to the test. + * @access private + */ + function &_createErrorQueue() { + $context = &SimpleTest::getContext(); + $test = &$this->getTestCase(); + $queue = &$context->get('SimpleErrorQueue'); + $queue->setTestCase($test); + return $queue; + } +} + +/** + * Error queue used to record trapped + * errors. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleErrorQueue { + var $_queue; + var $_expectation_queue; + var $_test; + var $_using_expect_style = false; + + /** + * Starts with an empty queue. + */ + function SimpleErrorQueue() { + $this->clear(); + } + + /** + * Discards the contents of the error queue. + * @access public + */ + function clear() { + $this->_queue = array(); + $this->_expectation_queue = array(); + } + + /** + * Sets the currently running test case. + * @param SimpleTestCase $test Test case to send messages to. + * @access public + */ + function setTestCase(&$test) { + $this->_test = &$test; + } + + /** + * Sets up an expectation of an error. If this is + * not fulfilled at the end of the test, a failure + * will occour. If the error does happen, then this + * will cancel it out and send a pass message. + * @param SimpleExpectation $expected Expected error match. + * @param string $message Message to display. + * @access public + */ + function expectError($expected, $message) { + $this->_using_expect_style = true; + array_push($this->_expectation_queue, array($expected, $message)); + } + + /** + * Adds an error to the front of the queue. + * @param integer $severity PHP error code. + * @param string $content Text of error. + * @param string $filename File error occoured in. + * @param integer $line Line number of error. + * @access public + */ + function add($severity, $content, $filename, $line) { + $content = str_replace('%', '%%', $content); + if ($this->_using_expect_style) { + $this->_testLatestError($severity, $content, $filename, $line); + } else { + array_push( + $this->_queue, + array($severity, $content, $filename, $line)); + } + } + + /** + * Any errors still in the queue are sent to the test + * case. Any unfulfilled expectations trigger failures. + * @access public + */ + function tally() { + while (list($severity, $message, $file, $line) = $this->extract()) { + $severity = $this->getSeverityAsString($severity); + $this->_test->error($severity, $message, $file, $line); + } + while (list($expected, $message) = $this->_extractExpectation()) { + $this->_test->assert($expected, false, "%s -> Expected error not caught"); + } + } + + /** + * Tests the error against the most recent expected + * error. + * @param integer $severity PHP error code. + * @param string $content Text of error. + * @param string $filename File error occoured in. + * @param integer $line Line number of error. + * @access private + */ + function _testLatestError($severity, $content, $filename, $line) { + if ($expectation = $this->_extractExpectation()) { + list($expected, $message) = $expectation; + $this->_test->assert($expected, $content, sprintf( + $message, + "%s -> PHP error [$content] severity [" . + $this->getSeverityAsString($severity) . + "] in [$filename] line [$line]")); + } else { + $this->_test->error($severity, $content, $filename, $line); + } + } + + /** + * Pulls the earliest error from the queue. + * @return mixed False if none, or a list of error + * information. Elements are: severity + * as the PHP error code, the error message, + * the file with the error, the line number + * and a list of PHP super global arrays. + * @access public + */ + function extract() { + if (count($this->_queue)) { + return array_shift($this->_queue); + } + return false; + } + + /** + * Pulls the earliest expectation from the queue. + * @return SimpleExpectation False if none. + * @access private + */ + function _extractExpectation() { + if (count($this->_expectation_queue)) { + return array_shift($this->_expectation_queue); + } + return false; + } + + /** + * @deprecated + */ + function assertNoErrors($message) { + return $this->_test->assert( + new TrueExpectation(), + count($this->_queue) == 0, + sprintf($message, 'Should be no errors')); + } + + /** + * @deprecated + */ + function assertError($expected, $message) { + if (count($this->_queue) == 0) { + $this->_test->fail(sprintf($message, 'Expected error not found')); + return false; + } + list($severity, $content, $file, $line) = $this->extract(); + $severity = $this->getSeverityAsString($severity); + return $this->_test->assert( + $expected, + $content, + sprintf($message, "Expected PHP error [$content] severity [$severity] in [$file] line [$line]")); + } + + /** + * Converts an error code into it's string + * representation. + * @param $severity PHP integer error code. + * @return String version of error code. + * @access public + * @static + */ + function getSeverityAsString($severity) { + static $map = array( + E_STRICT => 'E_STRICT', + E_ERROR => 'E_ERROR', + E_WARNING => 'E_WARNING', + E_PARSE => 'E_PARSE', + E_NOTICE => 'E_NOTICE', + E_CORE_ERROR => 'E_CORE_ERROR', + E_CORE_WARNING => 'E_CORE_WARNING', + E_COMPILE_ERROR => 'E_COMPILE_ERROR', + E_COMPILE_WARNING => 'E_COMPILE_WARNING', + E_USER_ERROR => 'E_USER_ERROR', + E_USER_WARNING => 'E_USER_WARNING', + E_USER_NOTICE => 'E_USER_NOTICE'); + if (defined('E_RECOVERABLE_ERROR')) { + $map[E_RECOVERABLE_ERROR] = 'E_RECOVERABLE_ERROR'; + } + if (defined('E_DEPRECATED')) { + $map[E_DEPRECATED] = 'E_DEPRECATED'; + } + return $map[$severity]; + } +} + +/** + * Error handler that simply stashes any errors into the global + * error queue. Simulates the existing behaviour with respect to + * logging errors, but this feature may be removed in future. + * @param $severity PHP error code. + * @param $message Text of error. + * @param $filename File error occoured in. + * @param $line Line number of error. + * @param $super_globals Hash of PHP super global arrays. + * @static + * @access public + */ +function SimpleTestErrorHandler($severity, $message, $filename = null, $line = null, $super_globals = null, $mask = null) { + $severity = $severity & error_reporting(); + if ($severity) { + restore_error_handler(); + if (ini_get('log_errors')) { + $label = SimpleErrorQueue::getSeverityAsString($severity); + error_log("$label: $message in $filename on line $line"); + } + $context = &SimpleTest::getContext(); + $queue = &$context->get('SimpleErrorQueue'); + $queue->add($severity, $message, $filename, $line); + set_error_handler('SimpleTestErrorHandler'); + } + return true; +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/exceptions.php b/plugins/www/testgen4web_simpletest/lib/simpletest/exceptions.php new file mode 100644 index 0000000..c19a04e --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/exceptions.php @@ -0,0 +1,198 @@ +SimpleInvokerDecorator($invoker); + } + + /** + * Invokes a test method whilst trapping expected + * exceptions. Any left over unthrown exceptions + * are then reported as failures. + * @param string $method Test method to call. + */ + function invoke($method) { + $trap = SimpleTest::getContext()->get('SimpleExceptionTrap'); + $trap->clear(); + try { + $has_thrown = false; + parent::invoke($method); + } catch (Exception $exception) { + $has_thrown = true; + if (! $trap->isExpected($this->getTestCase(), $exception)) { + $this->getTestCase()->exception($exception); + } + $trap->clear(); + } + if ($message = $trap->getOutstanding()) { + $this->getTestCase()->fail($message); + } + if ($has_thrown) { + try { + parent::getTestCase()->tearDown(); + } catch (Exception $e) { } + } + } +} + +/** + * Tests exceptions either by type or the exact + * exception. This could be improved to accept + * a pattern expectation to test the error + * message, but that will have to come later. + * @package SimpleTest + * @subpackage UnitTester + */ +class ExceptionExpectation extends SimpleExpectation { + private $expected; + + /** + * Sets up the conditions to test against. + * If the expected value is a string, then + * it will act as a test of the class name. + * An exception as the comparison will + * trigger an identical match. Writing this + * down now makes it look doubly dumb. I hope + * come up with a better scheme later. + * @param mixed $expected A class name or an actual + * exception to compare with. + * @param string $message Message to display. + */ + function __construct($expected, $message = '%s') { + $this->expected = $expected; + parent::__construct($message); + } + + /** + * Carry out the test. + * @param Exception $compare Value to check. + * @return boolean True if matched. + */ + function test($compare) { + if (is_string($this->expected)) { + return ($compare instanceof $this->expected); + } + if (get_class($compare) != get_class($this->expected)) { + return false; + } + return $compare->getMessage() == $this->expected->getMessage(); + } + + /** + * Create the message to display describing the test. + * @param Exception $compare Exception to match. + * @return string Final message. + */ + function testMessage($compare) { + if (is_string($this->expected)) { + return "Exception [" . $this->describeException($compare) . + "] should be type [" . $this->expected . "]"; + } + return "Exception [" . $this->describeException($compare) . + "] should match [" . + $this->describeException($this->expected) . "]"; + } + + /** + * Summary of an Exception object. + * @param Exception $compare Exception to describe. + * @return string Text description. + */ + protected function describeException($exception) { + return get_class($exception) . ": " . $exception->getMessage(); + } +} + +/** + * Stores expected exceptions for when they + * get thrown. Saves the irritating try...catch + * block. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleExceptionTrap { + private $expected; + private $message; + + /** + * Clears down the queue ready for action. + */ + function __construct() { + $this->clear(); + } + + /** + * Sets up an expectation of an exception. + * This has the effect of intercepting an + * exception that matches. + * @param SimpleExpectation $expected Expected exception to match. + * @param string $message Message to display. + * @access public + */ + function expectException($expected = false, $message = '%s') { + if ($expected === false) { + $expected = new AnythingExpectation(); + } + if (! SimpleExpectation::isExpectation($expected)) { + $expected = new ExceptionExpectation($expected); + } + $this->expected = $expected; + $this->message = $message; + } + + /** + * Compares the expected exception with any + * in the queue. Issues a pass or fail and + * returns the state of the test. + * @param SimpleTestCase $test Test case to send messages to. + * @param Exception $exception Exception to compare. + * @return boolean False on no match. + */ + function isExpected($test, $exception) { + if ($this->expected) { + return $test->assert($this->expected, $exception, $this->message); + } + return false; + } + + /** + * Tests for any left over exception. + * @return string/false The failure message or false if none. + */ + function getOutstanding() { + return sprintf($this->message, 'Failed to trap exception'); + } + + /** + * Discards the contents of the error queue. + */ + function clear() { + $this->expected = false; + $this->message = false; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/expectation.php b/plugins/www/testgen4web_simpletest/lib/simpletest/expectation.php new file mode 100644 index 0000000..194afd5 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/expectation.php @@ -0,0 +1,895 @@ +_message = $message; + } + + /** + * Tests the expectation. True if correct. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + * @abstract + */ + function test($compare) { + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + * @abstract + */ + function testMessage($compare) { + } + + /** + * Overlays the generated message onto the stored user + * message. An additional message can be interjected. + * @param mixed $compare Comparison value. + * @param SimpleDumper $dumper For formatting the results. + * @return string Description of success + * or failure. + * @access public + */ + function overlayMessage($compare, $dumper) { + $this->_dumper = $dumper; + return sprintf($this->_message, $this->testMessage($compare)); + } + + /** + * Accessor for the dumper. + * @return SimpleDumper Current value dumper. + * @access protected + */ + function &_getDumper() { + if (! $this->_dumper) { + $dumper = &new SimpleDumper(); + return $dumper; + } + return $this->_dumper; + } + + /** + * Test to see if a value is an expectation object. + * A useful utility method. + * @param mixed $expectation Hopefully an Epectation + * class. + * @return boolean True if descended from + * this class. + * @access public + * @static + */ + function isExpectation($expectation) { + return is_object($expectation) && + SimpleTestCompatibility::isA($expectation, 'SimpleExpectation'); + } +} + +/** + * A wildcard expectation always matches. + * @package SimpleTest + * @subpackage MockObjects + */ +class AnythingExpectation extends SimpleExpectation { + + /** + * Tests the expectation. Always true. + * @param mixed $compare Ignored. + * @return boolean True. + * @access public + */ + function test($compare) { + return true; + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + return 'Anything always matches [' . $dumper->describeValue($compare) . ']'; + } +} + +/** + * An expectation that never matches. + * @package SimpleTest + * @subpackage MockObjects + */ +class FailedExpectation extends SimpleExpectation { + + /** + * Tests the expectation. Always false. + * @param mixed $compare Ignored. + * @return boolean True. + * @access public + */ + function test($compare) { + return false; + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + return 'Failed expectation never matches [' . $dumper->describeValue($compare) . ']'; + } +} + +/** + * An expectation that passes on boolean true. + * @package SimpleTest + * @subpackage MockObjects + */ +class TrueExpectation extends SimpleExpectation { + + /** + * Tests the expectation. + * @param mixed $compare Should be true. + * @return boolean True on match. + * @access public + */ + function test($compare) { + return (boolean)$compare; + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + return 'Expected true, got [' . $dumper->describeValue($compare) . ']'; + } +} + +/** + * An expectation that passes on boolean false. + * @package SimpleTest + * @subpackage MockObjects + */ +class FalseExpectation extends SimpleExpectation { + + /** + * Tests the expectation. + * @param mixed $compare Should be false. + * @return boolean True on match. + * @access public + */ + function test($compare) { + return ! (boolean)$compare; + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + return 'Expected false, got [' . $dumper->describeValue($compare) . ']'; + } +} + +/** + * Test for equality. + * @package SimpleTest + * @subpackage UnitTester + */ +class EqualExpectation extends SimpleExpectation { + var $_value; + + /** + * Sets the value to compare against. + * @param mixed $value Test value to match. + * @param string $message Customised message on failure. + * @access public + */ + function EqualExpectation($value, $message = '%s') { + $this->SimpleExpectation($message); + $this->_value = $value; + } + + /** + * Tests the expectation. True if it matches the + * held value. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return (($this->_value == $compare) && ($compare == $this->_value)); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + return "Equal expectation [" . $this->_dumper->describeValue($this->_value) . "]"; + } else { + return "Equal expectation fails " . + $this->_dumper->describeDifference($this->_value, $compare); + } + } + + /** + * Accessor for comparison value. + * @return mixed Held value to compare with. + * @access protected + */ + function _getValue() { + return $this->_value; + } +} + +/** + * Test for inequality. + * @package SimpleTest + * @subpackage UnitTester + */ +class NotEqualExpectation extends EqualExpectation { + + /** + * Sets the value to compare against. + * @param mixed $value Test value to match. + * @param string $message Customised message on failure. + * @access public + */ + function NotEqualExpectation($value, $message = '%s') { + $this->EqualExpectation($value, $message); + } + + /** + * Tests the expectation. True if it differs from the + * held value. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return ! parent::test($compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + if ($this->test($compare)) { + return "Not equal expectation passes " . + $dumper->describeDifference($this->_getValue(), $compare); + } else { + return "Not equal expectation fails [" . + $dumper->describeValue($this->_getValue()) . + "] matches"; + } + } +} + +/** + * Test for being within a range. + * @package SimpleTest + * @subpackage UnitTester + */ +class WithinMarginExpectation extends SimpleExpectation { + var $_upper; + var $_lower; + + /** + * Sets the value to compare against and the fuzziness of + * the match. Used for comparing floating point values. + * @param mixed $value Test value to match. + * @param mixed $margin Fuzziness of match. + * @param string $message Customised message on failure. + * @access public + */ + function WithinMarginExpectation($value, $margin, $message = '%s') { + $this->SimpleExpectation($message); + $this->_upper = $value + $margin; + $this->_lower = $value - $margin; + } + + /** + * Tests the expectation. True if it matches the + * held value. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return (($compare <= $this->_upper) && ($compare >= $this->_lower)); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + return $this->_withinMessage($compare); + } else { + return $this->_outsideMessage($compare); + } + } + + /** + * Creates a the message for being within the range. + * @param mixed $compare Value being tested. + * @access private + */ + function _withinMessage($compare) { + return "Within expectation [" . $this->_dumper->describeValue($this->_lower) . "] and [" . + $this->_dumper->describeValue($this->_upper) . "]"; + } + + /** + * Creates a the message for being within the range. + * @param mixed $compare Value being tested. + * @access private + */ + function _outsideMessage($compare) { + if ($compare > $this->_upper) { + return "Outside expectation " . + $this->_dumper->describeDifference($compare, $this->_upper); + } else { + return "Outside expectation " . + $this->_dumper->describeDifference($compare, $this->_lower); + } + } +} + +/** + * Test for being outside of a range. + * @package SimpleTest + * @subpackage UnitTester + */ +class OutsideMarginExpectation extends WithinMarginExpectation { + + /** + * Sets the value to compare against and the fuzziness of + * the match. Used for comparing floating point values. + * @param mixed $value Test value to not match. + * @param mixed $margin Fuzziness of match. + * @param string $message Customised message on failure. + * @access public + */ + function OutsideMarginExpectation($value, $margin, $message = '%s') { + $this->WithinMarginExpectation($value, $margin, $message); + } + + /** + * Tests the expectation. True if it matches the + * held value. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return ! parent::test($compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if (! $this->test($compare)) { + return $this->_withinMessage($compare); + } else { + return $this->_outsideMessage($compare); + } + } +} + +/** + * Test for reference. + * @package SimpleTest + * @subpackage UnitTester + */ +class ReferenceExpectation extends SimpleExpectation { + var $_value; + + /** + * Sets the reference value to compare against. + * @param mixed $value Test reference to match. + * @param string $message Customised message on failure. + * @access public + */ + function ReferenceExpectation(&$value, $message = '%s') { + $this->SimpleExpectation($message); + $this->_value =& $value; + } + + /** + * Tests the expectation. True if it exactly + * references the held value. + * @param mixed $compare Comparison reference. + * @return boolean True if correct. + * @access public + */ + function test(&$compare) { + return SimpleTestCompatibility::isReference($this->_value, $compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + return "Reference expectation [" . $this->_dumper->describeValue($this->_value) . "]"; + } else { + return "Reference expectation fails " . + $this->_dumper->describeDifference($this->_value, $compare); + } + } + + function _getValue() { + return $this->_value; + } +} + +/** + * Test for identity. + * @package SimpleTest + * @subpackage UnitTester + */ +class IdenticalExpectation extends EqualExpectation { + + /** + * Sets the value to compare against. + * @param mixed $value Test value to match. + * @param string $message Customised message on failure. + * @access public + */ + function IdenticalExpectation($value, $message = '%s') { + $this->EqualExpectation($value, $message); + } + + /** + * Tests the expectation. True if it exactly + * matches the held value. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return SimpleTestCompatibility::isIdentical($this->_getValue(), $compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + if ($this->test($compare)) { + return "Identical expectation [" . $dumper->describeValue($this->_getValue()) . "]"; + } else { + return "Identical expectation [" . $dumper->describeValue($this->_getValue()) . + "] fails with [" . + $dumper->describeValue($compare) . "] " . + $dumper->describeDifference($this->_getValue(), $compare, TYPE_MATTERS); + } + } +} + +/** + * Test for non-identity. + * @package SimpleTest + * @subpackage UnitTester + */ +class NotIdenticalExpectation extends IdenticalExpectation { + + /** + * Sets the value to compare against. + * @param mixed $value Test value to match. + * @param string $message Customised message on failure. + * @access public + */ + function NotIdenticalExpectation($value, $message = '%s') { + $this->IdenticalExpectation($value, $message); + } + + /** + * Tests the expectation. True if it differs from the + * held value. + * @param mixed $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return ! parent::test($compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + if ($this->test($compare)) { + return "Not identical expectation passes " . + $dumper->describeDifference($this->_getValue(), $compare, TYPE_MATTERS); + } else { + return "Not identical expectation [" . $dumper->describeValue($this->_getValue()) . "] matches"; + } + } +} + +/** + * Test for a pattern using Perl regex rules. + * @package SimpleTest + * @subpackage UnitTester + */ +class PatternExpectation extends SimpleExpectation { + var $_pattern; + + /** + * Sets the value to compare against. + * @param string $pattern Pattern to search for. + * @param string $message Customised message on failure. + * @access public + */ + function PatternExpectation($pattern, $message = '%s') { + $this->SimpleExpectation($message); + $this->_pattern = $pattern; + } + + /** + * Accessor for the pattern. + * @return string Perl regex as string. + * @access protected + */ + function _getPattern() { + return $this->_pattern; + } + + /** + * Tests the expectation. True if the Perl regex + * matches the comparison value. + * @param string $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return (boolean)preg_match($this->_getPattern(), $compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + return $this->_describePatternMatch($this->_getPattern(), $compare); + } else { + $dumper = &$this->_getDumper(); + return "Pattern [" . $this->_getPattern() . + "] not detected in [" . + $dumper->describeValue($compare) . "]"; + } + } + + /** + * Describes a pattern match including the string + * found and it's position. + * @param string $pattern Regex to match against. + * @param string $subject Subject to search. + * @access protected + */ + function _describePatternMatch($pattern, $subject) { + preg_match($pattern, $subject, $matches); + $position = strpos($subject, $matches[0]); + $dumper = $this->_getDumper(); + return "Pattern [$pattern] detected at character [$position] in [" . + $dumper->describeValue($subject) . "] as [" . + $matches[0] . "] in region [" . + $dumper->clipString($subject, 100, $position) . "]"; + } +} + +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class WantedPatternExpectation extends PatternExpectation { +} + +/** + * Fail if a pattern is detected within the + * comparison. + * @package SimpleTest + * @subpackage UnitTester + */ +class NoPatternExpectation extends PatternExpectation { + + /** + * Sets the reject pattern + * @param string $pattern Pattern to search for. + * @param string $message Customised message on failure. + * @access public + */ + function NoPatternExpectation($pattern, $message = '%s') { + $this->PatternExpectation($pattern, $message); + } + + /** + * Tests the expectation. False if the Perl regex + * matches the comparison value. + * @param string $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return ! parent::test($compare); + } + + /** + * Returns a human readable test message. + * @param string $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + $dumper = &$this->_getDumper(); + return "Pattern [" . $this->_getPattern() . + "] not detected in [" . + $dumper->describeValue($compare) . "]"; + } else { + return $this->_describePatternMatch($this->_getPattern(), $compare); + } + } +} + +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class UnwantedPatternExpectation extends NoPatternExpectation { +} + +/** + * Tests either type or class name if it's an object. + * @package SimpleTest + * @subpackage UnitTester + */ +class IsAExpectation extends SimpleExpectation { + var $_type; + + /** + * Sets the type to compare with. + * @param string $type Type or class name. + * @param string $message Customised message on failure. + * @access public + */ + function IsAExpectation($type, $message = '%s') { + $this->SimpleExpectation($message); + $this->_type = $type; + } + + /** + * Accessor for type to check against. + * @return string Type or class name. + * @access protected + */ + function _getType() { + return $this->_type; + } + + /** + * Tests the expectation. True if the type or + * class matches the string value. + * @param string $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + if (is_object($compare)) { + return SimpleTestCompatibility::isA($compare, $this->_type); + } else { + return (strtolower(gettype($compare)) == $this->_canonicalType($this->_type)); + } + } + + /** + * Coerces type name into a gettype() match. + * @param string $type User type. + * @return string Simpler type. + * @access private + */ + function _canonicalType($type) { + $type = strtolower($type); + $map = array( + 'bool' => 'boolean', + 'float' => 'double', + 'real' => 'double', + 'int' => 'integer'); + if (isset($map[$type])) { + $type = $map[$type]; + } + return $type; + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + return "Value [" . $dumper->describeValue($compare) . + "] should be type [" . $this->_type . "]"; + } +} + +/** + * Tests either type or class name if it's an object. + * Will succeed if the type does not match. + * @package SimpleTest + * @subpackage UnitTester + */ +class NotAExpectation extends IsAExpectation { + var $_type; + + /** + * Sets the type to compare with. + * @param string $type Type or class name. + * @param string $message Customised message on failure. + * @access public + */ + function NotAExpectation($type, $message = '%s') { + $this->IsAExpectation($type, $message); + } + + /** + * Tests the expectation. False if the type or + * class matches the string value. + * @param string $compare Comparison value. + * @return boolean True if different. + * @access public + */ + function test($compare) { + return ! parent::test($compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + return "Value [" . $dumper->describeValue($compare) . + "] should not be type [" . $this->_getType() . "]"; + } +} + +/** + * Tests for existance of a method in an object + * @package SimpleTest + * @subpackage UnitTester + */ +class MethodExistsExpectation extends SimpleExpectation { + var $_method; + + /** + * Sets the value to compare against. + * @param string $method Method to check. + * @param string $message Customised message on failure. + * @access public + * @return void + */ + function MethodExistsExpectation($method, $message = '%s') { + $this->SimpleExpectation($message); + $this->_method = &$method; + } + + /** + * Tests the expectation. True if the method exists in the test object. + * @param string $compare Comparison method name. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return (boolean)(is_object($compare) && method_exists($compare, $this->_method)); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + if (! is_object($compare)) { + return 'No method on non-object [' . $dumper->describeValue($compare) . ']'; + } + $method = $this->_method; + return "Object [" . $dumper->describeValue($compare) . + "] should contain method [$method]"; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/pear_test_case.php b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/pear_test_case.php new file mode 100644 index 0000000..f5e5a7b --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/pear_test_case.php @@ -0,0 +1,198 @@ +SimpleTestCase($label); + $this->_loosely_typed = false; + } + + /** + * Will test straight equality if set to loose + * typing, or identity if not. + * @param $first First value. + * @param $second Comparison value. + * @param $message Message to display. + * @public + */ + function assertEquals($first, $second, $message = "%s", $delta = 0) { + if ($this->_loosely_typed) { + $expectation = &new EqualExpectation($first); + } else { + $expectation = &new IdenticalExpectation($first); + } + $this->assert($expectation, $second, $message); + } + + /** + * Passes if the value tested is not null. + * @param $value Value to test against. + * @param $message Message to display. + * @public + */ + function assertNotNull($value, $message = "%s") { + parent::assert(new TrueExpectation(), isset($value), $message); + } + + /** + * Passes if the value tested is null. + * @param $value Value to test against. + * @param $message Message to display. + * @public + */ + function assertNull($value, $message = "%s") { + parent::assert(new TrueExpectation(), !isset($value), $message); + } + + /** + * In PHP5 the identity test tests for the same + * object. This is a reference test in PHP4. + * @param $first First object handle. + * @param $second Hopefully the same handle. + * @param $message Message to display. + * @public + */ + function assertSame(&$first, &$second, $message = "%s") { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + "[" . $dumper->describeValue($first) . + "] and [" . $dumper->describeValue($second) . + "] should reference the same object"); + return $this->assert( + new TrueExpectation(), + SimpleTestCompatibility::isReference($first, $second), + $message); + } + + /** + * In PHP5 the identity test tests for the same + * object. This is a reference test in PHP4. + * @param $first First object handle. + * @param $second Hopefully a different handle. + * @param $message Message to display. + * @public + */ + function assertNotSame(&$first, &$second, $message = "%s") { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + "[" . $dumper->describeValue($first) . + "] and [" . $dumper->describeValue($second) . + "] should not be the same object"); + return $this->assert( + new falseExpectation(), + SimpleTestCompatibility::isReference($first, $second), + $message); + } + + /** + * Sends pass if the test condition resolves true, + * a fail otherwise. + * @param $condition Condition to test true. + * @param $message Message to display. + * @public + */ + function assertTrue($condition, $message = "%s") { + parent::assert(new TrueExpectation(), $condition, $message); + } + + /** + * Sends pass if the test condition resolves false, + * a fail otherwise. + * @param $condition Condition to test false. + * @param $message Message to display. + * @public + */ + function assertFalse($condition, $message = "%s") { + parent::assert(new FalseExpectation(), $condition, $message); + } + + /** + * Tests a regex match. Needs refactoring. + * @param $pattern Regex to match. + * @param $subject String to search in. + * @param $message Message to display. + * @public + */ + function assertRegExp($pattern, $subject, $message = "%s") { + $this->assert(new PatternExpectation($pattern), $subject, $message); + } + + /** + * Tests the type of a value. + * @param $value Value to take type of. + * @param $type Hoped for type. + * @param $message Message to display. + * @public + */ + function assertType($value, $type, $message = "%s") { + parent::assert(new TrueExpectation(), gettype($value) == strtolower($type), $message); + } + + /** + * Sets equality operation to act as a simple equal + * comparison only, allowing a broader range of + * matches. + * @param $loosely_typed True for broader comparison. + * @public + */ + function setLooselyTyped($loosely_typed) { + $this->_loosely_typed = $loosely_typed; + } + + /** + * For progress indication during + * a test amongst other things. + * @return Usually one. + * @public + */ + function countTestCases() { + return $this->getSize(); + } + + /** + * Accessor for name, normally just the class + * name. + * @public + */ + function getName() { + return $this->getLabel(); + } + + /** + * Does nothing. For compatibility only. + * @param $name Dummy + * @public + */ + function setName($name) { + } + } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/phpunit_test_case.php b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/phpunit_test_case.php new file mode 100644 index 0000000..e038a49 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/phpunit_test_case.php @@ -0,0 +1,96 @@ +SimpleTestCase($label); + } + + /** + * Sends pass if the test condition resolves true, + * a fail otherwise. + * @param $condition Condition to test true. + * @param $message Message to display. + * @public + */ + function assert($condition, $message = false) { + parent::assert(new TrueExpectation(), $condition, $message); + } + + /** + * Will test straight equality if set to loose + * typing, or identity if not. + * @param $first First value. + * @param $second Comparison value. + * @param $message Message to display. + * @public + */ + function assertEquals($first, $second, $message = false) { + parent::assert(new EqualExpectation($first), $second, $message); + } + + /** + * Simple string equality. + * @param $first First value. + * @param $second Comparison value. + * @param $message Message to display. + * @public + */ + function assertEqualsMultilineStrings($first, $second, $message = false) { + parent::assert(new EqualExpectation($first), $second, $message); + } + + /** + * Tests a regex match. + * @param $pattern Regex to match. + * @param $subject String to search in. + * @param $message Message to display. + * @public + */ + function assertRegexp($pattern, $subject, $message = false) { + parent::assert(new PatternExpectation($pattern), $subject, $message); + } + + /** + * Sends an error which we interpret as a fail + * with a different message for compatibility. + * @param $message Message to display. + * @public + */ + function error($message) { + parent::fail("Error triggered [$message]"); + } + + /** + * Accessor for name. + * @public + */ + function name() { + return $this->getLabel(); + } + } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox.php b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox.php new file mode 100644 index 0000000..7db7c87 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox.php @@ -0,0 +1,42 @@ +_test_case_pattern = empty($test_case_pattern) ? '/^(.*)$/' : $test_case_pattern; + } + + function paintCaseStart($test_name) { + preg_match($this->_test_case_pattern, $test_name, $matches); + if (!empty($matches[1])) { + echo $matches[1] . "\n"; + } else { + echo $test_name . "\n"; + } + } + + function paintCaseEnd() { + echo "\n"; + } + + function paintMethodStart($test_name) { + if (!preg_match('/^test(.*)$/i', $test_name, $matches)) { + return; + } + $test_name = $matches[1]; + + $test_name = preg_replace('/([A-Z])([A-Z])/', '$1 $2', $test_name); + echo '- ' . strtolower(preg_replace('/([a-zA-Z])([A-Z0-9])/', '$1 $2', $test_name)); + } + + function paintMethodEnd() { + echo "\n"; + } + + function paintFail() { + echo " [FAILED]"; + } +} diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox/test.php b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox/test.php new file mode 100644 index 0000000..82c5b7d --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/extensions/testdox/test.php @@ -0,0 +1,108 @@ +assertIsA($dox, 'SimpleScorer'); + $this->assertIsA($dox, 'SimpleReporter'); + } + + function testOutputsNameOfTestCase() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintCaseStart('TestOfTestDoxReporter'); + $buffer = ob_get_clean(); + $this->assertWantedPattern('/^TestDoxReporter/', $buffer); + } + + function testOutputOfTestCaseNameFilteredByConstructParameter() { + $dox = new TestDoxReporter('/^(.*)Test$/'); + ob_start(); + $dox->paintCaseStart('SomeGreatWidgetTest'); + $buffer = ob_get_clean(); + $this->assertWantedPattern('/^SomeGreatWidget/', $buffer); + } + + function testIfTest_case_patternIsEmptyAssumeEverythingMatches() { + $dox = new TestDoxReporter(''); + ob_start(); + $dox->paintCaseStart('TestOfTestDoxReporter'); + $buffer = ob_get_clean(); + $this->assertWantedPattern('/^TestOfTestDoxReporter/', $buffer); + } + + function testEmptyLineInsertedWhenCaseEnds() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintCaseEnd('TestOfTestDoxReporter'); + $buffer = ob_get_clean(); + $this->assertEqual("\n", $buffer); + } + + function testPaintsTestMethodInTestDoxFormat() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintMethodStart('testSomeGreatTestCase'); + $buffer = ob_get_clean(); + $this->assertEqual("- some great test case", $buffer); + unset($buffer); + + $random = rand(100, 200); + ob_start(); + $dox->paintMethodStart("testRandomNumberIs{$random}"); + $buffer = ob_get_clean(); + $this->assertEqual("- random number is {$random}", $buffer); + } + + function testDoesNotOutputAnythingOnNoneTestMethods() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintMethodStart('nonMatchingMethod'); + $buffer = ob_get_clean(); + $this->assertEqual('', $buffer); + } + + function testPaintMethodAddLineBreak() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintMethodEnd('someMethod'); + $buffer = ob_get_clean(); + $this->assertEqual("\n", $buffer); + $this->assertNoErrors(); + } + + function testProperlySpacesSingleLettersInMethodName() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintMethodStart('testAVerySimpleAgainAVerySimpleMethod'); + $buffer = ob_get_clean(); + $this->assertEqual('- a very simple again a very simple method', $buffer); + } + + function testOnFailureThisPrintsFailureNotice() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintFail(); + $buffer = ob_get_clean(); + $this->assertEqual(' [FAILED]', $buffer); + } + + function testWhenMatchingMethodNamesTestPrefixIsCaseInsensitive() { + $dox = new TestDoxReporter(); + ob_start(); + $dox->paintMethodStart('TESTSupportsAllUppercaseTestPrefixEvenThoughIDoNotKnowWhyYouWouldDoThat'); + $buffer = ob_get_clean(); + $this->assertEqual( + '- supports all uppercase test prefix even though i do not know why you would do that', + $buffer + ); + } +} + diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/form.php b/plugins/www/testgen4web_simpletest/lib/simpletest/form.php new file mode 100644 index 0000000..cbef663 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/form.php @@ -0,0 +1,355 @@ +_method = $tag->getAttribute('method'); + $this->_action = $this->_createAction($tag->getAttribute('action'), $page); + $this->_encoding = $this->_setEncodingClass($tag); + $this->_default_target = false; + $this->_id = $tag->getAttribute('id'); + $this->_buttons = array(); + $this->_images = array(); + $this->_widgets = array(); + $this->_radios = array(); + $this->_checkboxes = array(); + } + + /** + * Creates the request packet to be sent by the form. + * @param SimpleTag $tag Form tag to read. + * @return string Packet class. + * @access private + */ + function _setEncodingClass($tag) { + if (strtolower($tag->getAttribute('method')) == 'post') { + if (strtolower($tag->getAttribute('enctype')) == 'multipart/form-data') { + return 'SimpleMultipartEncoding'; + } + return 'SimplePostEncoding'; + } + return 'SimpleGetEncoding'; + } + + /** + * Sets the frame target within a frameset. + * @param string $frame Name of frame. + * @access public + */ + function setDefaultTarget($frame) { + $this->_default_target = $frame; + } + + /** + * Accessor for method of form submission. + * @return string Either get or post. + * @access public + */ + function getMethod() { + return ($this->_method ? strtolower($this->_method) : 'get'); + } + + /** + * Combined action attribute with current location + * to get an absolute form target. + * @param string $action Action attribute from form tag. + * @param SimpleUrl $base Page location. + * @return SimpleUrl Absolute form target. + */ + function _createAction($action, &$page) { + if (($action === '') || ($action === false)) { + return $page->expandUrl($page->getUrl()); + } + return $page->expandUrl(new SimpleUrl($action));; + } + + /** + * Absolute URL of the target. + * @return SimpleUrl URL target. + * @access public + */ + function getAction() { + $url = $this->_action; + if ($this->_default_target && ! $url->getTarget()) { + $url->setTarget($this->_default_target); + } + return $url; + } + + /** + * Creates the encoding for the current values in the + * form. + * @return SimpleFormEncoding Request to submit. + * @access private + */ + function _encode() { + $class = $this->_encoding; + $encoding = new $class(); + for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) { + $this->_widgets[$i]->write($encoding); + } + return $encoding; + } + + /** + * ID field of form for unique identification. + * @return string Unique tag ID. + * @access public + */ + function getId() { + return $this->_id; + } + + /** + * Adds a tag contents to the form. + * @param SimpleWidget $tag Input tag to add. + * @access public + */ + function addWidget(&$tag) { + if (strtolower($tag->getAttribute('type')) == 'submit') { + $this->_buttons[] = &$tag; + } elseif (strtolower($tag->getAttribute('type')) == 'image') { + $this->_images[] = &$tag; + } elseif ($tag->getName()) { + $this->_setWidget($tag); + } + } + + /** + * Sets the widget into the form, grouping radio + * buttons if any. + * @param SimpleWidget $tag Incoming form control. + * @access private + */ + function _setWidget(&$tag) { + if (strtolower($tag->getAttribute('type')) == 'radio') { + $this->_addRadioButton($tag); + } elseif (strtolower($tag->getAttribute('type')) == 'checkbox') { + $this->_addCheckbox($tag); + } else { + $this->_widgets[] = &$tag; + } + } + + /** + * Adds a radio button, building a group if necessary. + * @param SimpleRadioButtonTag $tag Incoming form control. + * @access private + */ + function _addRadioButton(&$tag) { + if (! isset($this->_radios[$tag->getName()])) { + $this->_widgets[] = &new SimpleRadioGroup(); + $this->_radios[$tag->getName()] = count($this->_widgets) - 1; + } + $this->_widgets[$this->_radios[$tag->getName()]]->addWidget($tag); + } + + /** + * Adds a checkbox, making it a group on a repeated name. + * @param SimpleCheckboxTag $tag Incoming form control. + * @access private + */ + function _addCheckbox(&$tag) { + if (! isset($this->_checkboxes[$tag->getName()])) { + $this->_widgets[] = &$tag; + $this->_checkboxes[$tag->getName()] = count($this->_widgets) - 1; + } else { + $index = $this->_checkboxes[$tag->getName()]; + if (! SimpleTestCompatibility::isA($this->_widgets[$index], 'SimpleCheckboxGroup')) { + $previous = &$this->_widgets[$index]; + $this->_widgets[$index] = &new SimpleCheckboxGroup(); + $this->_widgets[$index]->addWidget($previous); + } + $this->_widgets[$index]->addWidget($tag); + } + } + + /** + * Extracts current value from form. + * @param SimpleSelector $selector Criteria to apply. + * @return string/array Value(s) as string or null + * if not set. + * @access public + */ + function getValue($selector) { + for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) { + if ($selector->isMatch($this->_widgets[$i])) { + return $this->_widgets[$i]->getValue(); + } + } + foreach ($this->_buttons as $button) { + if ($selector->isMatch($button)) { + return $button->getValue(); + } + } + return null; + } + + /** + * Sets a widget value within the form. + * @param SimpleSelector $selector Criteria to apply. + * @param string $value Value to input into the widget. + * @return boolean True if value is legal, false + * otherwise. If the field is not + * present, nothing will be set. + * @access public + */ + function setField($selector, $value, $position=false) { + $success = false; + $_position = 0; + for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) { + if ($selector->isMatch($this->_widgets[$i])) { + $_position++; + if ($position === false or $_position === (int)$position) { + if ($this->_widgets[$i]->setValue($value)) { + $success = true; + } + } + } + } + return $success; + } + + /** + * Used by the page object to set widgets labels to + * external label tags. + * @param SimpleSelector $selector Criteria to apply. + * @access public + */ + function attachLabelBySelector($selector, $label) { + for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) { + if ($selector->isMatch($this->_widgets[$i])) { + if (method_exists($this->_widgets[$i], 'setLabel')) { + $this->_widgets[$i]->setLabel($label); + return; + } + } + } + } + + /** + * Test to see if a form has a submit button. + * @param SimpleSelector $selector Criteria to apply. + * @return boolean True if present. + * @access public + */ + function hasSubmit($selector) { + foreach ($this->_buttons as $button) { + if ($selector->isMatch($button)) { + return true; + } + } + return false; + } + + /** + * Test to see if a form has an image control. + * @param SimpleSelector $selector Criteria to apply. + * @return boolean True if present. + * @access public + */ + function hasImage($selector) { + foreach ($this->_images as $image) { + if ($selector->isMatch($image)) { + return true; + } + } + return false; + } + + /** + * Gets the submit values for a selected button. + * @param SimpleSelector $selector Criteria to apply. + * @param hash $additional Additional data for the form. + * @return SimpleEncoding Submitted values or false + * if there is no such button + * in the form. + * @access public + */ + function submitButton($selector, $additional = false) { + $additional = $additional ? $additional : array(); + foreach ($this->_buttons as $button) { + if ($selector->isMatch($button)) { + $encoding = $this->_encode(); + $button->write($encoding); + if ($additional) { + $encoding->merge($additional); + } + return $encoding; + } + } + return false; + } + + /** + * Gets the submit values for an image. + * @param SimpleSelector $selector Criteria to apply. + * @param integer $x X-coordinate of click. + * @param integer $y Y-coordinate of click. + * @param hash $additional Additional data for the form. + * @return SimpleEncoding Submitted values or false + * if there is no such button in the + * form. + * @access public + */ + function submitImage($selector, $x, $y, $additional = false) { + $additional = $additional ? $additional : array(); + foreach ($this->_images as $image) { + if ($selector->isMatch($image)) { + $encoding = $this->_encode(); + $image->write($encoding, $x, $y); + if ($additional) { + $encoding->merge($additional); + } + return $encoding; + } + } + return false; + } + + /** + * Simply submits the form without the submit button + * value. Used when there is only one button or it + * is unimportant. + * @return hash Submitted values. + * @access public + */ + function submit() { + return $this->_encode(); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/frames.php b/plugins/www/testgen4web_simpletest/lib/simpletest/frames.php new file mode 100644 index 0000000..ec098df --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/frames.php @@ -0,0 +1,596 @@ +_frameset = &$page; + $this->_frames = array(); + $this->_focus = false; + $this->_names = array(); + } + + /** + * Adds a parsed page to the frameset. + * @param SimplePage $page Frame page. + * @param string $name Name of frame in frameset. + * @access public + */ + function addFrame(&$page, $name = false) { + $this->_frames[] = &$page; + if ($name) { + $this->_names[$name] = count($this->_frames) - 1; + } + } + + /** + * Replaces existing frame with another. If the + * frame is nested, then the call is passed down + * one level. + * @param array $path Path of frame in frameset. + * @param SimplePage $page Frame source. + * @access public + */ + function setFrame($path, &$page) { + $name = array_shift($path); + if (isset($this->_names[$name])) { + $index = $this->_names[$name]; + } else { + $index = $name - 1; + } + if (count($path) == 0) { + $this->_frames[$index] = &$page; + return; + } + $this->_frames[$index]->setFrame($path, $page); + } + + /** + * Accessor for current frame focus. Will be + * false if no frame has focus. Will have the nested + * frame focus if any. + * @return array Labels or indexes of nested frames. + * @access public + */ + function getFrameFocus() { + if ($this->_focus === false) { + return array(); + } + return array_merge( + array($this->_getPublicNameFromIndex($this->_focus)), + $this->_frames[$this->_focus]->getFrameFocus()); + } + + /** + * Turns an internal array index into the frames list + * into a public name, or if none, then a one offset + * index. + * @param integer $subject Internal index. + * @return integer/string Public name. + * @access private + */ + function _getPublicNameFromIndex($subject) { + foreach ($this->_names as $name => $index) { + if ($subject == $index) { + return $name; + } + } + return $subject + 1; + } + + /** + * Sets the focus by index. The integer index starts from 1. + * If already focused and the target frame also has frames, + * then the nested frame will be focused. + * @param integer $choice Chosen frame. + * @return boolean True if frame exists. + * @access public + */ + function setFrameFocusByIndex($choice) { + if (is_integer($this->_focus)) { + if ($this->_frames[$this->_focus]->hasFrames()) { + return $this->_frames[$this->_focus]->setFrameFocusByIndex($choice); + } + } + if (($choice < 1) || ($choice > count($this->_frames))) { + return false; + } + $this->_focus = $choice - 1; + return true; + } + + /** + * Sets the focus by name. If already focused and the + * target frame also has frames, then the nested frame + * will be focused. + * @param string $name Chosen frame. + * @return boolean True if frame exists. + * @access public + */ + function setFrameFocus($name) { + if (is_integer($this->_focus)) { + if ($this->_frames[$this->_focus]->hasFrames()) { + return $this->_frames[$this->_focus]->setFrameFocus($name); + } + } + if (in_array($name, array_keys($this->_names))) { + $this->_focus = $this->_names[$name]; + return true; + } + return false; + } + + /** + * Clears the frame focus. + * @access public + */ + function clearFrameFocus() { + $this->_focus = false; + $this->_clearNestedFramesFocus(); + } + + /** + * Clears the frame focus for any nested frames. + * @access private + */ + function _clearNestedFramesFocus() { + for ($i = 0; $i < count($this->_frames); $i++) { + $this->_frames[$i]->clearFrameFocus(); + } + } + + /** + * Test for the presence of a frameset. + * @return boolean Always true. + * @access public + */ + function hasFrames() { + return true; + } + + /** + * Accessor for frames information. + * @return array/string Recursive hash of frame URL strings. + * The key is either a numerical + * index or the name attribute. + * @access public + */ + function getFrames() { + $report = array(); + for ($i = 0; $i < count($this->_frames); $i++) { + $report[$this->_getPublicNameFromIndex($i)] = + $this->_frames[$i]->getFrames(); + } + return $report; + } + + /** + * Accessor for raw text of either all the pages or + * the frame in focus. + * @return string Raw unparsed content. + * @access public + */ + function getRaw() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getRaw(); + } + $raw = ''; + for ($i = 0; $i < count($this->_frames); $i++) { + $raw .= $this->_frames[$i]->getRaw(); + } + return $raw; + } + + /** + * Accessor for plain text of either all the pages or + * the frame in focus. + * @return string Plain text content. + * @access public + */ + function getText() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getText(); + } + $raw = ''; + for ($i = 0; $i < count($this->_frames); $i++) { + $raw .= ' ' . $this->_frames[$i]->getText(); + } + return trim($raw); + } + + /** + * Accessor for last error. + * @return string Error from last response. + * @access public + */ + function getTransportError() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getTransportError(); + } + return $this->_frameset->getTransportError(); + } + + /** + * Request method used to fetch this frame. + * @return string GET, POST or HEAD. + * @access public + */ + function getMethod() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getMethod(); + } + return $this->_frameset->getMethod(); + } + + /** + * Original resource name. + * @return SimpleUrl Current url. + * @access public + */ + function getUrl() { + if (is_integer($this->_focus)) { + $url = $this->_frames[$this->_focus]->getUrl(); + $url->setTarget($this->_getPublicNameFromIndex($this->_focus)); + } else { + $url = $this->_frameset->getUrl(); + } + return $url; + } + + /** + * Page base URL. + * @return SimpleUrl Current url. + * @access public + */ + function getBaseUrl() { + if (is_integer($this->_focus)) { + $url = $this->_frames[$this->_focus]->getBaseUrl(); + } else { + $url = $this->_frameset->getBaseUrl(); + } + return $url; + } + + /** + * Expands expandomatic URLs into fully qualified + * URLs for the frameset page. + * @param SimpleUrl $url Relative URL. + * @return SimpleUrl Absolute URL. + * @access public + */ + function expandUrl($url) { + return $this->_frameset->expandUrl($url); + } + + /** + * Original request data. + * @return mixed Sent content. + * @access public + */ + function getRequestData() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getRequestData(); + } + return $this->_frameset->getRequestData(); + } + + /** + * Accessor for current MIME type. + * @return string MIME type as string; e.g. 'text/html' + * @access public + */ + function getMimeType() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getMimeType(); + } + return $this->_frameset->getMimeType(); + } + + /** + * Accessor for last response code. + * @return integer Last HTTP response code received. + * @access public + */ + function getResponseCode() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getResponseCode(); + } + return $this->_frameset->getResponseCode(); + } + + /** + * Accessor for last Authentication type. Only valid + * straight after a challenge (401). + * @return string Description of challenge type. + * @access public + */ + function getAuthentication() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getAuthentication(); + } + return $this->_frameset->getAuthentication(); + } + + /** + * Accessor for last Authentication realm. Only valid + * straight after a challenge (401). + * @return string Name of security realm. + * @access public + */ + function getRealm() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getRealm(); + } + return $this->_frameset->getRealm(); + } + + /** + * Accessor for outgoing header information. + * @return string Header block. + * @access public + */ + function getRequest() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getRequest(); + } + return $this->_frameset->getRequest(); + } + + /** + * Accessor for raw header information. + * @return string Header block. + * @access public + */ + function getHeaders() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getHeaders(); + } + return $this->_frameset->getHeaders(); + } + + /** + * Accessor for parsed title. + * @return string Title or false if no title is present. + * @access public + */ + function getTitle() { + return $this->_frameset->getTitle(); + } + + /** + * Accessor for a list of all fixed links. + * @return array List of urls as strings. + * @access public + */ + function getUrls() { + if (is_integer($this->_focus)) { + return $this->_frames[$this->_focus]->getUrls(); + } + $urls = array(); + foreach ($this->_frames as $frame) { + $urls = array_merge($urls, $frame->getUrls()); + } + return array_values(array_unique($urls)); + } + + /** + * Accessor for URLs by the link label. Label will match + * regardess of whitespace issues and case. + * @param string $label Text of link. + * @return array List of links with that label. + * @access public + */ + function getUrlsByLabel($label) { + if (is_integer($this->_focus)) { + return $this->_tagUrlsWithFrame( + $this->_frames[$this->_focus]->getUrlsByLabel($label), + $this->_focus); + } + $urls = array(); + foreach ($this->_frames as $index => $frame) { + $urls = array_merge( + $urls, + $this->_tagUrlsWithFrame( + $frame->getUrlsByLabel($label), + $index)); + } + return $urls; + } + + /** + * Accessor for a URL by the id attribute. If in a frameset + * then the first link found with that ID attribute is + * returned only. Focus on a frame if you want one from + * a specific part of the frameset. + * @param string $id Id attribute of link. + * @return string URL with that id. + * @access public + */ + function getUrlById($id) { + foreach ($this->_frames as $index => $frame) { + if ($url = $frame->getUrlById($id)) { + if (! $url->gettarget()) { + $url->setTarget($this->_getPublicNameFromIndex($index)); + } + return $url; + } + } + return false; + } + + /** + * Attaches the intended frame index to a list of URLs. + * @param array $urls List of SimpleUrls. + * @param string $frame Name of frame or index. + * @return array List of tagged URLs. + * @access private + */ + function _tagUrlsWithFrame($urls, $frame) { + $tagged = array(); + foreach ($urls as $url) { + if (! $url->getTarget()) { + $url->setTarget($this->_getPublicNameFromIndex($frame)); + } + $tagged[] = $url; + } + return $tagged; + } + + /** + * Finds a held form by button label. Will only + * search correctly built forms. + * @param SimpleSelector $selector Button finder. + * @return SimpleForm Form object containing + * the button. + * @access public + */ + function &getFormBySubmit($selector) { + $form = &$this->_findForm('getFormBySubmit', $selector); + return $form; + } + + /** + * Finds a held form by image using a selector. + * Will only search correctly built forms. The first + * form found either within the focused frame, or + * across frames, will be the one returned. + * @param SimpleSelector $selector Image finder. + * @return SimpleForm Form object containing + * the image. + * @access public + */ + function &getFormByImage($selector) { + $form = &$this->_findForm('getFormByImage', $selector); + return $form; + } + + /** + * Finds a held form by the form ID. A way of + * identifying a specific form when we have control + * of the HTML code. The first form found + * either within the focused frame, or across frames, + * will be the one returned. + * @param string $id Form label. + * @return SimpleForm Form object containing the matching ID. + * @access public + */ + function &getFormById($id) { + $form = &$this->_findForm('getFormById', $id); + return $form; + } + + /** + * General form finder. Will search all the frames or + * just the one in focus. + * @param string $method Method to use to find in a page. + * @param string $attribute Label, name or ID. + * @return SimpleForm Form object containing the matching ID. + * @access private + */ + function &_findForm($method, $attribute) { + if (is_integer($this->_focus)) { + $form = &$this->_findFormInFrame( + $this->_frames[$this->_focus], + $this->_focus, + $method, + $attribute); + return $form; + } + for ($i = 0; $i < count($this->_frames); $i++) { + $form = &$this->_findFormInFrame( + $this->_frames[$i], + $i, + $method, + $attribute); + if ($form) { + return $form; + } + } + $null = null; + return $null; + } + + /** + * Finds a form in a page using a form finding method. Will + * also tag the form with the frame name it belongs in. + * @param SimplePage $page Page content of frame. + * @param integer $index Internal frame representation. + * @param string $method Method to use to find in a page. + * @param string $attribute Label, name or ID. + * @return SimpleForm Form object containing the matching ID. + * @access private + */ + function &_findFormInFrame(&$page, $index, $method, $attribute) { + $form = &$this->_frames[$index]->$method($attribute); + if (isset($form)) { + $form->setDefaultTarget($this->_getPublicNameFromIndex($index)); + } + return $form; + } + + /** + * Sets a field on each form in which the field is + * available. + * @param SimpleSelector $selector Field finder. + * @param string $value Value to set field to. + * @return boolean True if value is valid. + * @access public + */ + function setField($selector, $value) { + if (is_integer($this->_focus)) { + $this->_frames[$this->_focus]->setField($selector, $value); + } else { + for ($i = 0; $i < count($this->_frames); $i++) { + $this->_frames[$i]->setField($selector, $value); + } + } + } + + /** + * Accessor for a form element value within a page. + * @param SimpleSelector $selector Field finder. + * @return string/boolean A string if the field is + * present, false if unchecked + * and null if missing. + * @access public + */ + function getField($selector) { + for ($i = 0; $i < count($this->_frames); $i++) { + $value = $this->_frames[$i]->getField($selector); + if (isset($value)) { + return $value; + } + } + return null; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/http.php b/plugins/www/testgen4web_simpletest/lib/simpletest/http.php new file mode 100644 index 0000000..e6c6e89 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/http.php @@ -0,0 +1,624 @@ +_url = $url; + } + + /** + * Resource name. + * @return SimpleUrl Current url. + * @access protected + */ + function getUrl() { + return $this->_url; + } + + /** + * Creates the first line which is the actual request. + * @param string $method HTTP request method, usually GET. + * @return string Request line content. + * @access protected + */ + function _getRequestLine($method) { + return $method . ' ' . $this->_url->getPath() . + $this->_url->getEncodedRequest() . ' HTTP/1.0'; + } + + /** + * Creates the host part of the request. + * @return string Host line content. + * @access protected + */ + function _getHostLine() { + $line = 'Host: ' . $this->_url->getHost(); + if ($this->_url->getPort()) { + $line .= ':' . $this->_url->getPort(); + } + return $line; + } + + /** + * Opens a socket to the route. + * @param string $method HTTP request method, usually GET. + * @param integer $timeout Connection timeout. + * @return SimpleSocket New socket. + * @access public + */ + function &createConnection($method, $timeout) { + $default_port = ('https' == $this->_url->getScheme()) ? 443 : 80; + $socket = &$this->_createSocket( + $this->_url->getScheme() ? $this->_url->getScheme() : 'http', + $this->_url->getHost(), + $this->_url->getPort() ? $this->_url->getPort() : $default_port, + $timeout); + if (! $socket->isError()) { + $socket->write($this->_getRequestLine($method) . "\r\n"); + $socket->write($this->_getHostLine() . "\r\n"); + $socket->write("Connection: close\r\n"); + } + return $socket; + } + + /** + * Factory for socket. + * @param string $scheme Protocol to use. + * @param string $host Hostname to connect to. + * @param integer $port Remote port. + * @param integer $timeout Connection timeout. + * @return SimpleSocket/SimpleSecureSocket New socket. + * @access protected + */ + function &_createSocket($scheme, $host, $port, $timeout) { + if (in_array($scheme, array('https'))) { + $socket = &new SimpleSecureSocket($host, $port, $timeout); + } else { + $socket = &new SimpleSocket($host, $port, $timeout); + } + return $socket; + } +} + +/** + * Creates HTTP headers for the end point of + * a HTTP request via a proxy server. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleProxyRoute extends SimpleRoute { + var $_proxy; + var $_username; + var $_password; + + /** + * Stashes the proxy address. + * @param SimpleUrl $url URL as object. + * @param string $proxy Proxy URL. + * @param string $username Username for autentication. + * @param string $password Password for autentication. + * @access public + */ + function SimpleProxyRoute($url, $proxy, $username = false, $password = false) { + $this->SimpleRoute($url); + $this->_proxy = $proxy; + $this->_username = $username; + $this->_password = $password; + } + + /** + * Creates the first line which is the actual request. + * @param string $method HTTP request method, usually GET. + * @param SimpleUrl $url URL as object. + * @return string Request line content. + * @access protected + */ + function _getRequestLine($method) { + $url = $this->getUrl(); + $scheme = $url->getScheme() ? $url->getScheme() : 'http'; + $port = $url->getPort() ? ':' . $url->getPort() : ''; + return $method . ' ' . $scheme . '://' . $url->getHost() . $port . + $url->getPath() . $url->getEncodedRequest() . ' HTTP/1.0'; + } + + /** + * Creates the host part of the request. + * @param SimpleUrl $url URL as object. + * @return string Host line content. + * @access protected + */ + function _getHostLine() { + $host = 'Host: ' . $this->_proxy->getHost(); + $port = $this->_proxy->getPort() ? $this->_proxy->getPort() : 8080; + return "$host:$port"; + } + + /** + * Opens a socket to the route. + * @param string $method HTTP request method, usually GET. + * @param integer $timeout Connection timeout. + * @return SimpleSocket New socket. + * @access public + */ + function &createConnection($method, $timeout) { + $socket = &$this->_createSocket( + $this->_proxy->getScheme() ? $this->_proxy->getScheme() : 'http', + $this->_proxy->getHost(), + $this->_proxy->getPort() ? $this->_proxy->getPort() : 8080, + $timeout); + if ($socket->isError()) { + return $socket; + } + $socket->write($this->_getRequestLine($method) . "\r\n"); + $socket->write($this->_getHostLine() . "\r\n"); + if ($this->_username && $this->_password) { + $socket->write('Proxy-Authorization: Basic ' . + base64_encode($this->_username . ':' . $this->_password) . + "\r\n"); + } + $socket->write("Connection: close\r\n"); + return $socket; + } +} + +/** + * HTTP request for a web page. Factory for + * HttpResponse object. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleHttpRequest { + var $_route; + var $_encoding; + var $_headers; + var $_cookies; + + /** + * Builds the socket request from the different pieces. + * These include proxy information, URL, cookies, headers, + * request method and choice of encoding. + * @param SimpleRoute $route Request route. + * @param SimpleFormEncoding $encoding Content to send with + * request. + * @access public + */ + function SimpleHttpRequest(&$route, $encoding) { + $this->_route = &$route; + $this->_encoding = $encoding; + $this->_headers = array(); + $this->_cookies = array(); + } + + /** + * Dispatches the content to the route's socket. + * @param integer $timeout Connection timeout. + * @return SimpleHttpResponse A response which may only have + * an error, but hopefully has a + * complete web page. + * @access public + */ + function &fetch($timeout) { + $socket = &$this->_route->createConnection($this->_encoding->getMethod(), $timeout); + if (! $socket->isError()) { + $this->_dispatchRequest($socket, $this->_encoding); + } + $response = &$this->_createResponse($socket); + return $response; + } + + /** + * Sends the headers. + * @param SimpleSocket $socket Open socket. + * @param string $method HTTP request method, + * usually GET. + * @param SimpleFormEncoding $encoding Content to send with request. + * @access private + */ + function _dispatchRequest(&$socket, $encoding) { + foreach ($this->_headers as $header_line) { + $socket->write($header_line . "\r\n"); + } + if (count($this->_cookies) > 0) { + $socket->write("Cookie: " . implode(";", $this->_cookies) . "\r\n"); + } + $encoding->writeHeadersTo($socket); + $socket->write("\r\n"); + $encoding->writeTo($socket); + } + + /** + * Adds a header line to the request. + * @param string $header_line Text of full header line. + * @access public + */ + function addHeaderLine($header_line) { + $this->_headers[] = $header_line; + } + + /** + * Reads all the relevant cookies from the + * cookie jar. + * @param SimpleCookieJar $jar Jar to read + * @param SimpleUrl $url Url to use for scope. + * @access public + */ + function readCookiesFromJar($jar, $url) { + $this->_cookies = $jar->selectAsPairs($url); + } + + /** + * Wraps the socket in a response parser. + * @param SimpleSocket $socket Responding socket. + * @return SimpleHttpResponse Parsed response object. + * @access protected + */ + function &_createResponse(&$socket) { + $response = &new SimpleHttpResponse( + $socket, + $this->_route->getUrl(), + $this->_encoding); + return $response; + } +} + +/** + * Collection of header lines in the response. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleHttpHeaders { + var $_raw_headers; + var $_response_code; + var $_http_version; + var $_mime_type; + var $_location; + var $_cookies; + var $_authentication; + var $_realm; + + /** + * Parses the incoming header block. + * @param string $headers Header block. + * @access public + */ + function SimpleHttpHeaders($headers) { + $this->_raw_headers = $headers; + $this->_response_code = false; + $this->_http_version = false; + $this->_mime_type = ''; + $this->_location = false; + $this->_cookies = array(); + $this->_authentication = false; + $this->_realm = false; + foreach (split("\r\n", $headers) as $header_line) { + $this->_parseHeaderLine($header_line); + } + } + + /** + * Accessor for parsed HTTP protocol version. + * @return integer HTTP error code. + * @access public + */ + function getHttpVersion() { + return $this->_http_version; + } + + /** + * Accessor for raw header block. + * @return string All headers as raw string. + * @access public + */ + function getRaw() { + return $this->_raw_headers; + } + + /** + * Accessor for parsed HTTP error code. + * @return integer HTTP error code. + * @access public + */ + function getResponseCode() { + return (integer)$this->_response_code; + } + + /** + * Returns the redirected URL or false if + * no redirection. + * @return string URL or false for none. + * @access public + */ + function getLocation() { + return $this->_location; + } + + /** + * Test to see if the response is a valid redirect. + * @return boolean True if valid redirect. + * @access public + */ + function isRedirect() { + return in_array($this->_response_code, array(301, 302, 303, 307)) && + (boolean)$this->getLocation(); + } + + /** + * Test to see if the response is an authentication + * challenge. + * @return boolean True if challenge. + * @access public + */ + function isChallenge() { + return ($this->_response_code == 401) && + (boolean)$this->_authentication && + (boolean)$this->_realm; + } + + /** + * Accessor for MIME type header information. + * @return string MIME type. + * @access public + */ + function getMimeType() { + return $this->_mime_type; + } + + /** + * Accessor for authentication type. + * @return string Type. + * @access public + */ + function getAuthentication() { + return $this->_authentication; + } + + /** + * Accessor for security realm. + * @return string Realm. + * @access public + */ + function getRealm() { + return $this->_realm; + } + + /** + * Writes new cookies to the cookie jar. + * @param SimpleCookieJar $jar Jar to write to. + * @param SimpleUrl $url Host and path to write under. + * @access public + */ + function writeCookiesToJar(&$jar, $url) { + foreach ($this->_cookies as $cookie) { + $jar->setCookie( + $cookie->getName(), + $cookie->getValue(), + $url->getHost(), + $cookie->getPath(), + $cookie->getExpiry()); + } + } + + /** + * Called on each header line to accumulate the held + * data within the class. + * @param string $header_line One line of header. + * @access protected + */ + function _parseHeaderLine($header_line) { + if (preg_match('/HTTP\/(\d+\.\d+)\s+(\d+)/i', $header_line, $matches)) { + $this->_http_version = $matches[1]; + $this->_response_code = $matches[2]; + } + if (preg_match('/Content-type:\s*(.*)/i', $header_line, $matches)) { + $this->_mime_type = trim($matches[1]); + } + if (preg_match('/Location:\s*(.*)/i', $header_line, $matches)) { + $this->_location = trim($matches[1]); + } + if (preg_match('/Set-cookie:(.*)/i', $header_line, $matches)) { + $this->_cookies[] = $this->_parseCookie($matches[1]); + } + if (preg_match('/WWW-Authenticate:\s+(\S+)\s+realm=\"(.*?)\"/i', $header_line, $matches)) { + $this->_authentication = $matches[1]; + $this->_realm = trim($matches[2]); + } + } + + /** + * Parse the Set-cookie content. + * @param string $cookie_line Text after "Set-cookie:" + * @return SimpleCookie New cookie object. + * @access private + */ + function _parseCookie($cookie_line) { + $parts = split(";", $cookie_line); + $cookie = array(); + preg_match('/\s*(.*?)\s*=(.*)/', array_shift($parts), $cookie); + foreach ($parts as $part) { + if (preg_match('/\s*(.*?)\s*=(.*)/', $part, $matches)) { + $cookie[$matches[1]] = trim($matches[2]); + } + } + return new SimpleCookie( + $cookie[1], + trim($cookie[2]), + isset($cookie["path"]) ? $cookie["path"] : "", + isset($cookie["expires"]) ? $cookie["expires"] : false); + } +} + +/** + * Basic HTTP response. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleHttpResponse extends SimpleStickyError { + var $_url; + var $_encoding; + var $_sent; + var $_content; + var $_headers; + + /** + * Constructor. Reads and parses the incoming + * content and headers. + * @param SimpleSocket $socket Network connection to fetch + * response text from. + * @param SimpleUrl $url Resource name. + * @param mixed $encoding Record of content sent. + * @access public + */ + function SimpleHttpResponse(&$socket, $url, $encoding) { + $this->SimpleStickyError(); + $this->_url = $url; + $this->_encoding = $encoding; + $this->_sent = $socket->getSent(); + $this->_content = false; + $raw = $this->_readAll($socket); + if ($socket->isError()) { + $this->_setError('Error reading socket [' . $socket->getError() . ']'); + return; + } + $this->_parse($raw); + } + + /** + * Splits up the headers and the rest of the content. + * @param string $raw Content to parse. + * @access private + */ + function _parse($raw) { + if (! $raw) { + $this->_setError('Nothing fetched'); + $this->_headers = &new SimpleHttpHeaders(''); + } elseif (! strstr($raw, "\r\n\r\n")) { + $this->_setError('Could not split headers from content'); + $this->_headers = &new SimpleHttpHeaders($raw); + } else { + list($headers, $this->_content) = split("\r\n\r\n", $raw, 2); + $this->_headers = &new SimpleHttpHeaders($headers); + } + } + + /** + * Original request method. + * @return string GET, POST or HEAD. + * @access public + */ + function getMethod() { + return $this->_encoding->getMethod(); + } + + /** + * Resource name. + * @return SimpleUrl Current url. + * @access public + */ + function getUrl() { + return $this->_url; + } + + /** + * Original request data. + * @return mixed Sent content. + * @access public + */ + function getRequestData() { + return $this->_encoding; + } + + /** + * Raw request that was sent down the wire. + * @return string Bytes actually sent. + * @access public + */ + function getSent() { + return $this->_sent; + } + + /** + * Accessor for the content after the last + * header line. + * @return string All content. + * @access public + */ + function getContent() { + return $this->_content; + } + + /** + * Accessor for header block. The response is the + * combination of this and the content. + * @return SimpleHeaders Wrapped header block. + * @access public + */ + function getHeaders() { + return $this->_headers; + } + + /** + * Accessor for any new cookies. + * @return array List of new cookies. + * @access public + */ + function getNewCookies() { + return $this->_headers->getNewCookies(); + } + + /** + * Reads the whole of the socket output into a + * single string. + * @param SimpleSocket $socket Unread socket. + * @return string Raw output if successful + * else false. + * @access private + */ + function _readAll(&$socket) { + $all = ''; + while (! $this->_isLastPacket($next = $socket->read())) { + $all .= $next; + } + return $all; + } + + /** + * Test to see if the packet from the socket is the + * last one. + * @param string $packet Chunk to interpret. + * @return boolean True if empty or EOF. + * @access private + */ + function _isLastPacket($packet) { + if (is_string($packet)) { + return $packet === ''; + } + return ! $packet; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/invoker.php b/plugins/www/testgen4web_simpletest/lib/simpletest/invoker.php new file mode 100644 index 0000000..e273001 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/invoker.php @@ -0,0 +1,139 @@ +_test_case = &$test_case; + } + + /** + * Accessor for test case being run. + * @return SimpleTestCase Test case. + * @access public + */ + function &getTestCase() { + return $this->_test_case; + } + + /** + * Runs test level set up. Used for changing + * the mechanics of base test cases. + * @param string $method Test method to call. + * @access public + */ + function before($method) { + $this->_test_case->before($method); + } + + /** + * Invokes a test method and buffered with setUp() + * and tearDown() calls. + * @param string $method Test method to call. + * @access public + */ + function invoke($method) { + $this->_test_case->setUp(); + $this->_test_case->$method(); + $this->_test_case->tearDown(); + } + + /** + * Runs test level clean up. Used for changing + * the mechanics of base test cases. + * @param string $method Test method to call. + * @access public + */ + function after($method) { + $this->_test_case->after($method); + } +} + +/** + * Do nothing decorator. Just passes the invocation + * straight through. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleInvokerDecorator { + var $_invoker; + + /** + * Stores the invoker to wrap. + * @param SimpleInvoker $invoker Test method runner. + */ + function SimpleInvokerDecorator(&$invoker) { + $this->_invoker = &$invoker; + } + + /** + * Accessor for test case being run. + * @return SimpleTestCase Test case. + * @access public + */ + function &getTestCase() { + return $this->_invoker->getTestCase(); + } + + /** + * Runs test level set up. Used for changing + * the mechanics of base test cases. + * @param string $method Test method to call. + * @access public + */ + function before($method) { + $this->_invoker->before($method); + } + + /** + * Invokes a test method and buffered with setUp() + * and tearDown() calls. + * @param string $method Test method to call. + * @access public + */ + function invoke($method) { + $this->_invoker->invoke($method); + } + + /** + * Runs test level clean up. Used for changing + * the mechanics of base test cases. + * @param string $method Test method to call. + * @access public + */ + function after($method) { + $this->_invoker->after($method); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/mock_objects.php b/plugins/www/testgen4web_simpletest/lib/simpletest/mock_objects.php new file mode 100644 index 0000000..5ef1575 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/mock_objects.php @@ -0,0 +1,1581 @@ += 0) { + require_once(dirname(__FILE__) . '/reflection_php5.php'); +} else { + require_once(dirname(__FILE__) . '/reflection_php4.php'); +} +/**#@-*/ + +/** + * Default character simpletest will substitute for any value + */ +if (! defined('MOCK_ANYTHING')) { + define('MOCK_ANYTHING', '*'); +} + +/** + * Parameter comparison assertion. + * @package SimpleTest + * @subpackage MockObjects + */ +class ParametersExpectation extends SimpleExpectation { + var $_expected; + + /** + * Sets the expected parameter list. + * @param array $parameters Array of parameters including + * those that are wildcarded. + * If the value is not an array + * then it is considered to match any. + * @param string $message Customised message on failure. + * @access public + */ + function ParametersExpectation($expected = false, $message = '%s') { + $this->SimpleExpectation($message); + $this->_expected = $expected; + } + + /** + * Tests the assertion. True if correct. + * @param array $parameters Comparison values. + * @return boolean True if correct. + * @access public + */ + function test($parameters) { + if (! is_array($this->_expected)) { + return true; + } + if (count($this->_expected) != count($parameters)) { + return false; + } + for ($i = 0; $i < count($this->_expected); $i++) { + if (! $this->_testParameter($parameters[$i], $this->_expected[$i])) { + return false; + } + } + return true; + } + + /** + * Tests an individual parameter. + * @param mixed $parameter Value to test. + * @param mixed $expected Comparison value. + * @return boolean True if expectation + * fulfilled. + * @access private + */ + function _testParameter($parameter, $expected) { + $comparison = $this->_coerceToExpectation($expected); + return $comparison->test($parameter); + } + + /** + * Returns a human readable test message. + * @param array $comparison Incoming parameter list. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($parameters) { + if ($this->test($parameters)) { + return "Expectation of " . count($this->_expected) . + " arguments of [" . $this->_renderArguments($this->_expected) . + "] is correct"; + } else { + return $this->_describeDifference($this->_expected, $parameters); + } + } + + /** + * Message to display if expectation differs from + * the parameters actually received. + * @param array $expected Expected parameters as list. + * @param array $parameters Actual parameters received. + * @return string Description of difference. + * @access private + */ + function _describeDifference($expected, $parameters) { + if (count($expected) != count($parameters)) { + return "Expected " . count($expected) . + " arguments of [" . $this->_renderArguments($expected) . + "] but got " . count($parameters) . + " arguments of [" . $this->_renderArguments($parameters) . "]"; + } + $messages = array(); + for ($i = 0; $i < count($expected); $i++) { + $comparison = $this->_coerceToExpectation($expected[$i]); + if (! $comparison->test($parameters[$i])) { + $messages[] = "parameter " . ($i + 1) . " with [" . + $comparison->overlayMessage($parameters[$i], $this->_getDumper()) . "]"; + } + } + return "Parameter expectation differs at " . implode(" and ", $messages); + } + + /** + * Creates an identical expectation if the + * object/value is not already some type + * of expectation. + * @param mixed $expected Expected value. + * @return SimpleExpectation Expectation object. + * @access private + */ + function _coerceToExpectation($expected) { + if (SimpleExpectation::isExpectation($expected)) { + return $expected; + } + return new IdenticalExpectation($expected); + } + + /** + * Renders the argument list as a string for + * messages. + * @param array $args Incoming arguments. + * @return string Simple description of type and value. + * @access private + */ + function _renderArguments($args) { + $descriptions = array(); + if (is_array($args)) { + foreach ($args as $arg) { + $dumper = &new SimpleDumper(); + $descriptions[] = $dumper->describeValue($arg); + } + } + return implode(', ', $descriptions); + } +} + +/** + * Confirms that the number of calls on a method is as expected. + * @package SimpleTest + * @subpackage MockObjects + */ +class CallCountExpectation extends SimpleExpectation { + var $_method; + var $_count; + + /** + * Stashes the method and expected count for later + * reporting. + * @param string $method Name of method to confirm against. + * @param integer $count Expected number of calls. + * @param string $message Custom error message. + */ + function CallCountExpectation($method, $count, $message = '%s') { + $this->_method = $method; + $this->_count = $count; + $this->SimpleExpectation($message); + } + + /** + * Tests the assertion. True if correct. + * @param integer $compare Measured call count. + * @return boolean True if expected. + * @access public + */ + function test($compare) { + return ($this->_count == $compare); + } + + /** + * Reports the comparison. + * @param integer $compare Measured call count. + * @return string Message to show. + * @access public + */ + function testMessage($compare) { + return 'Expected call count for [' . $this->_method . + '] was [' . $this->_count . + '] got [' . $compare . ']'; + } +} + +/** + * Confirms that the number of calls on a method is as expected. + * @package SimpleTest + * @subpackage MockObjects + */ +class MinimumCallCountExpectation extends SimpleExpectation { + var $_method; + var $_count; + + /** + * Stashes the method and expected count for later + * reporting. + * @param string $method Name of method to confirm against. + * @param integer $count Minimum number of calls. + * @param string $message Custom error message. + */ + function MinimumCallCountExpectation($method, $count, $message = '%s') { + $this->_method = $method; + $this->_count = $count; + $this->SimpleExpectation($message); + } + + /** + * Tests the assertion. True if correct. + * @param integer $compare Measured call count. + * @return boolean True if enough. + * @access public + */ + function test($compare) { + return ($this->_count <= $compare); + } + + /** + * Reports the comparison. + * @param integer $compare Measured call count. + * @return string Message to show. + * @access public + */ + function testMessage($compare) { + return 'Minimum call count for [' . $this->_method . + '] was [' . $this->_count . + '] got [' . $compare . ']'; + } +} + +/** + * Confirms that the number of calls on a method is as expected. + * @package SimpleTest + * @subpackage MockObjects + */ +class MaximumCallCountExpectation extends SimpleExpectation { + var $_method; + var $_count; + + /** + * Stashes the method and expected count for later + * reporting. + * @param string $method Name of method to confirm against. + * @param integer $count Minimum number of calls. + * @param string $message Custom error message. + */ + function MaximumCallCountExpectation($method, $count, $message = '%s') { + $this->_method = $method; + $this->_count = $count; + $this->SimpleExpectation($message); + } + + /** + * Tests the assertion. True if correct. + * @param integer $compare Measured call count. + * @return boolean True if not over. + * @access public + */ + function test($compare) { + return ($this->_count >= $compare); + } + + /** + * Reports the comparison. + * @param integer $compare Measured call count. + * @return string Message to show. + * @access public + */ + function testMessage($compare) { + return 'Maximum call count for [' . $this->_method . + '] was [' . $this->_count . + '] got [' . $compare . ']'; + } +} + +/** + * Retrieves method actions by searching the + * parameter lists until an expected match is found. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleSignatureMap { + var $_map; + + /** + * Creates an empty call map. + * @access public + */ + function SimpleSignatureMap() { + $this->_map = array(); + } + + /** + * Stashes a reference against a method call. + * @param array $parameters Array of arguments (including wildcards). + * @param mixed $action Reference placed in the map. + * @access public + */ + function add($parameters, &$action) { + $place = count($this->_map); + $this->_map[$place] = array(); + $this->_map[$place]['params'] = new ParametersExpectation($parameters); + $this->_map[$place]['content'] = &$action; + } + + /** + * Searches the call list for a matching parameter + * set. Returned by reference. + * @param array $parameters Parameters to search by + * without wildcards. + * @return object Object held in the first matching + * slot, otherwise null. + * @access public + */ + function &findFirstAction($parameters) { + $slot = $this->_findFirstSlot($parameters); + if (isset($slot) && isset($slot['content'])) { + return $slot['content']; + } + $null = null; + return $null; + } + + /** + * Searches the call list for a matching parameter + * set. True if successful. + * @param array $parameters Parameters to search by + * without wildcards. + * @return boolean True if a match is present. + * @access public + */ + function isMatch($parameters) { + return ($this->_findFirstSlot($parameters) != null); + } + + /** + * Compares the incoming parameters with the + * internal expectation. Uses the incoming $test + * to dispatch the test message. + * @param SimpleTestCase $test Test to dispatch to. + * @param array $parameters The actual calling arguments. + * @param string $message The message to overlay. + * @access public + */ + function test(&$test, $parameters, $message) { + } + + /** + * Searches the map for a matching item. + * @param array $parameters Parameters to search by + * without wildcards. + * @return array Reference to slot or null. + * @access private + */ + function &_findFirstSlot($parameters) { + $count = count($this->_map); + for ($i = 0; $i < $count; $i++) { + if ($this->_map[$i]["params"]->test($parameters)) { + return $this->_map[$i]; + } + } + $null = null; + return $null; + } +} + +/** + * Allows setting of actions against call signatures either + * at a specific time, or always. Specific time settings + * trump lasting ones, otherwise the most recently added + * will mask an earlier match. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleCallSchedule { + var $_wildcard = MOCK_ANYTHING; + var $_always; + var $_at; + + /** + * Sets up an empty response schedule. + * Creates an empty call map. + */ + function SimpleCallSchedule() { + $this->_always = array(); + $this->_at = array(); + } + + /** + * Stores an action against a signature that + * will always fire unless masked by a time + * specific one. + * @param string $method Method name. + * @param array $args Calling parameters. + * @param SimpleAction $action Actually simpleByValue, etc. + * @access public + */ + function register($method, $args, &$action) { + $args = $this->_replaceWildcards($args); + $method = strtolower($method); + if (! isset($this->_always[$method])) { + $this->_always[$method] = new SimpleSignatureMap(); + } + $this->_always[$method]->add($args, $action); + } + + /** + * Stores an action against a signature that + * will fire at a specific time in the future. + * @param integer $step delay of calls to this method, + * 0 is next. + * @param string $method Method name. + * @param array $args Calling parameters. + * @param SimpleAction $action Actually SimpleByValue, etc. + * @access public + */ + function registerAt($step, $method, $args, &$action) { + $args = $this->_replaceWildcards($args); + $method = strtolower($method); + if (! isset($this->_at[$method])) { + $this->_at[$method] = array(); + } + if (! isset($this->_at[$method][$step])) { + $this->_at[$method][$step] = new SimpleSignatureMap(); + } + $this->_at[$method][$step]->add($args, $action); + } + + function expectArguments($method, $args, $message) { + $args = $this->_replaceWildcards($args); + $message .= Mock::getExpectationLine(); + $this->_expected_args[strtolower($method)] = + new ParametersExpectation($args, $message); + + } + + /** + * Actually carry out the action stored previously, + * if the parameters match. + * @param integer $step Time of call. + * @param string $method Method name. + * @param array $args The parameters making up the + * rest of the call. + * @return mixed The result of the action. + * @access public. + */ + function &respond($step, $method, $args) { + $method = strtolower($method); + if (isset($this->_at[$method][$step])) { + if ($this->_at[$method][$step]->isMatch($args)) { + $action = &$this->_at[$method][$step]->findFirstAction($args); + if (isset($action)) { + return $action->act(); + } + } + } + if (isset($this->_always[$method])) { + $action = &$this->_always[$method]->findFirstAction($args); + if (isset($action)) { + return $action->act(); + } + } + $null = null; + return $null; + } + + /** + * Replaces wildcard matches with wildcard + * expectations in the argument list. + * @param array $args Raw argument list. + * @return array Argument list with + * expectations. + * @access private + */ + function _replaceWildcards($args) { + if ($args === false) { + return false; + } + for ($i = 0; $i < count($args); $i++) { + if ($args[$i] === $this->_wildcard) { + $args[$i] = new AnythingExpectation(); + } + } + return $args; + } +} + +/** + * A type of SimpleMethodAction. + * Stashes a reference for returning later. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleByReference { + var $_reference; + + /** + * Stashes it for later. + * @param mixed $reference Actual PHP4 style reference. + * @access public + */ + function SimpleByReference(&$reference) { + $this->_reference = &$reference; + } + + /** + * Returns the reference stored earlier. + * @return mixed Whatever was stashed. + * @access public + */ + function &act() { + return $this->_reference; + } +} + +/** + * A type of SimpleMethodAction. + * Stashes a value for returning later. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleByValue { + var $_value; + + /** + * Stashes it for later. + * @param mixed $value You need to clone objects + * if you want copy semantics + * for these. + * @access public + */ + function SimpleByValue($value) { + $this->_value = $value; + } + + /** + * Returns the value stored earlier. + * @return mixed Whatever was stashed. + * @access public + */ + function &act() { + $dummy = $this->_value; + return $dummy; + } +} + +/** + * A type of SimpleMethodAction. + * Stashes an exception for throwing later. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleThrower { + var $_exception; + + /** + * Stashes it for later. + * @param Exception $exception The exception object to throw. + * @access public + */ + function SimpleThrower($exception) { + $this->_exception = $exception; + } + + /** + * Throws the exceptins stashed earlier. + * @access public + */ + function act() { + eval('throw $this->_exception;'); + } +} + +/** + * A type of SimpleMethodAction. + * Stashes an error for emitting later. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleErrorThrower { + var $_error; + var $_severity; + + /** + * Stashes an error to throw later. + * @param string $error Error message. + * @param integer $severity PHP error constant, e.g E_USER_ERROR. + * @access public + */ + function SimpleErrorThrower($error, $severity) { + $this->_error = $error; + $this->_severity = $severity; + } + + /** + * Triggers the stashed error. + * @return null The usual PHP4.4 shenanigans are needed here. + * @access public + */ + function &act() { + trigger_error($this->_error, $this->_severity); + $null = null; + return $null; + } +} + +/** + * A base class or delegate that extends an + * empty collection of methods that can have their + * return values set and expectations made of the + * calls upon them. The mock will assert the + * expectations against it's attached test case in + * addition to the server stub behaviour or returning + * preprogrammed responses. + * @package SimpleTest + * @subpackage MockObjects + */ +class SimpleMock { + var $_actions; + var $_wildcard = MOCK_ANYTHING; + var $_is_strict = true; + var $_call_counts; + var $_expected_counts; + var $_max_counts; + var $_expected_args; + var $_expected_args_at; + + /** + * Creates an empty action list and expectation list. + * All call counts are set to zero. + * @access public + */ + function SimpleMock() { + $this->_actions = &new SimpleCallSchedule(); + $this->_expectations = &new SimpleCallSchedule(); + $this->_call_counts = array(); + $this->_expected_counts = array(); + $this->_max_counts = array(); + $this->_expected_args = array(); + $this->_expected_args_at = array(); + $test = &$this->_getCurrentTestCase(); + $test->tell($this); + } + + /** + * Disables a name check when setting expectations. + * This hack is needed for the partial mocks. + * @access public + */ + function disableExpectationNameChecks() { + $this->_is_strict = false; + } + + /** + * Finds currently running test. + * @return SimpeTestCase Current test case. + * @access protected + */ + function &_getCurrentTestCase() { + $context = &SimpleTest::getContext(); + return $context->getTest(); + } + + /** + * Die if bad arguments array is passed. + * @param mixed $args The arguments value to be checked. + * @param string $task Description of task attempt. + * @return boolean Valid arguments + * @access private + */ + function _checkArgumentsIsArray($args, $task) { + if (! is_array($args)) { + trigger_error( + "Cannot $task as \$args parameter is not an array", + E_USER_ERROR); + } + } + + /** + * Triggers a PHP error if the method is not part + * of this object. + * @param string $method Name of method. + * @param string $task Description of task attempt. + * @access protected + */ + function _dieOnNoMethod($method, $task) { + if ($this->_is_strict && ! method_exists($this, $method)) { + trigger_error( + "Cannot $task as no ${method}() in class " . get_class($this), + E_USER_ERROR); + } + } + + /** + * Replaces wildcard matches with wildcard + * expectations in the argument list. + * @param array $args Raw argument list. + * @return array Argument list with + * expectations. + * @access private + */ + function _replaceWildcards($args) { + if ($args === false) { + return false; + } + for ($i = 0; $i < count($args); $i++) { + if ($args[$i] === $this->_wildcard) { + $args[$i] = new AnythingExpectation(); + } + } + return $args; + } + + /** + * Adds one to the call count of a method. + * @param string $method Method called. + * @param array $args Arguments as an array. + * @access protected + */ + function _addCall($method, $args) { + if (! isset($this->_call_counts[$method])) { + $this->_call_counts[$method] = 0; + } + $this->_call_counts[$method]++; + } + + /** + * Fetches the call count of a method so far. + * @param string $method Method name called. + * @return integer Number of calls so far. + * @access public + */ + function getCallCount($method) { + $this->_dieOnNoMethod($method, "get call count"); + $method = strtolower($method); + if (! isset($this->_call_counts[$method])) { + return 0; + } + return $this->_call_counts[$method]; + } + + /** + * Sets a return for a parameter list that will + * be passed by value for all calls to this method. + * @param string $method Method name. + * @param mixed $value Result of call passed by value. + * @param array $args List of parameters to match + * including wildcards. + * @access public + */ + function setReturnValue($method, $value, $args = false) { + $this->_dieOnNoMethod($method, "set return value"); + $this->_actions->register($method, $args, new SimpleByValue($value)); + } + + /** + * Sets a return for a parameter list that will + * be passed by value only when the required call count + * is reached. + * @param integer $timing Number of calls in the future + * to which the result applies. If + * not set then all calls will return + * the value. + * @param string $method Method name. + * @param mixed $value Result of call passed by value. + * @param array $args List of parameters to match + * including wildcards. + * @access public + */ + function setReturnValueAt($timing, $method, $value, $args = false) { + $this->_dieOnNoMethod($method, "set return value sequence"); + $this->_actions->registerAt($timing, $method, $args, new SimpleByValue($value)); + } + + /** + * Sets a return for a parameter list that will + * be passed by reference for all calls. + * @param string $method Method name. + * @param mixed $reference Result of the call will be this object. + * @param array $args List of parameters to match + * including wildcards. + * @access public + */ + function setReturnReference($method, &$reference, $args = false) { + $this->_dieOnNoMethod($method, "set return reference"); + $this->_actions->register($method, $args, new SimpleByReference($reference)); + } + + /** + * Sets a return for a parameter list that will + * be passed by value only when the required call count + * is reached. + * @param integer $timing Number of calls in the future + * to which the result applies. If + * not set then all calls will return + * the value. + * @param string $method Method name. + * @param mixed $reference Result of the call will be this object. + * @param array $args List of parameters to match + * including wildcards. + * @access public + */ + function setReturnReferenceAt($timing, $method, &$reference, $args = false) { + $this->_dieOnNoMethod($method, "set return reference sequence"); + $this->_actions->registerAt($timing, $method, $args, new SimpleByReference($reference)); + } + + /** + * Sets up an expected call with a set of + * expected parameters in that call. All + * calls will be compared to these expectations + * regardless of when the call is made. + * @param string $method Method call to test. + * @param array $args Expected parameters for the call + * including wildcards. + * @param string $message Overridden message. + * @access public + */ + function expect($method, $args, $message = '%s') { + $this->_dieOnNoMethod($method, 'set expected arguments'); + $this->_checkArgumentsIsArray($args, 'set expected arguments'); + $this->_expectations->expectArguments($method, $args, $message); + $args = $this->_replaceWildcards($args); + $message .= Mock::getExpectationLine(); + $this->_expected_args[strtolower($method)] = + new ParametersExpectation($args, $message); + } + + /** + * @deprecated + */ + function expectArguments($method, $args, $message = '%s') { + return $this->expect($method, $args, $message); + } + + /** + * Sets up an expected call with a set of + * expected parameters in that call. The + * expected call count will be adjusted if it + * is set too low to reach this call. + * @param integer $timing Number of calls in the future at + * which to test. Next call is 0. + * @param string $method Method call to test. + * @param array $args Expected parameters for the call + * including wildcards. + * @param string $message Overridden message. + * @access public + */ + function expectAt($timing, $method, $args, $message = '%s') { + $this->_dieOnNoMethod($method, 'set expected arguments at time'); + $this->_checkArgumentsIsArray($args, 'set expected arguments at time'); + $args = $this->_replaceWildcards($args); + if (! isset($this->_expected_args_at[$timing])) { + $this->_expected_args_at[$timing] = array(); + } + $method = strtolower($method); + $message .= Mock::getExpectationLine(); + $this->_expected_args_at[$timing][$method] = + new ParametersExpectation($args, $message); + } + + /** + * @deprecated + */ + function expectArgumentsAt($timing, $method, $args, $message = '%s') { + return $this->expectAt($timing, $method, $args, $message); + } + + /** + * Sets an expectation for the number of times + * a method will be called. The tally method + * is used to check this. + * @param string $method Method call to test. + * @param integer $count Number of times it should + * have been called at tally. + * @param string $message Overridden message. + * @access public + */ + function expectCallCount($method, $count, $message = '%s') { + $this->_dieOnNoMethod($method, 'set expected call count'); + $message .= Mock::getExpectationLine(); + $this->_expected_counts[strtolower($method)] = + new CallCountExpectation($method, $count, $message); + } + + /** + * Sets the number of times a method may be called + * before a test failure is triggered. + * @param string $method Method call to test. + * @param integer $count Most number of times it should + * have been called. + * @param string $message Overridden message. + * @access public + */ + function expectMaximumCallCount($method, $count, $message = '%s') { + $this->_dieOnNoMethod($method, 'set maximum call count'); + $message .= Mock::getExpectationLine(); + $this->_max_counts[strtolower($method)] = + new MaximumCallCountExpectation($method, $count, $message); + } + + /** + * Sets the number of times to call a method to prevent + * a failure on the tally. + * @param string $method Method call to test. + * @param integer $count Least number of times it should + * have been called. + * @param string $message Overridden message. + * @access public + */ + function expectMinimumCallCount($method, $count, $message = '%s') { + $this->_dieOnNoMethod($method, 'set minimum call count'); + $message .= Mock::getExpectationLine(); + $this->_expected_counts[strtolower($method)] = + new MinimumCallCountExpectation($method, $count, $message); + } + + /** + * Convenience method for barring a method + * call. + * @param string $method Method call to ban. + * @param string $message Overridden message. + * @access public + */ + function expectNever($method, $message = '%s') { + $this->expectMaximumCallCount($method, 0, $message); + } + + /** + * Convenience method for a single method + * call. + * @param string $method Method call to track. + * @param array $args Expected argument list or + * false for any arguments. + * @param string $message Overridden message. + * @access public + */ + function expectOnce($method, $args = false, $message = '%s') { + $this->expectCallCount($method, 1, $message); + if ($args !== false) { + $this->expect($method, $args, $message); + } + } + + /** + * Convenience method for requiring a method + * call. + * @param string $method Method call to track. + * @param array $args Expected argument list or + * false for any arguments. + * @param string $message Overridden message. + * @access public + */ + function expectAtLeastOnce($method, $args = false, $message = '%s') { + $this->expectMinimumCallCount($method, 1, $message); + if ($args !== false) { + $this->expect($method, $args, $message); + } + } + + /** + * Sets up a trigger to throw an exception upon the + * method call. + * @param string $method Method name to throw on. + */ + function throwOn($method, $exception = false, $args = false) { + $this->_dieOnNoMethod($method, "throw on"); + $this->_actions->register($method, $args, + new SimpleThrower($exception ? $exception : new Exception())); + } + + /** + * Sets up a trigger to throw an exception upon the + * method call. + */ + function throwAt($timing, $method, $exception = false, $args = false) { + $this->_dieOnNoMethod($method, "throw at"); + $this->_actions->registerAt($timing, $method, $args, + new SimpleThrower($exception ? $exception : new Exception())); + } + + /** + * Sets up a trigger to throw an error upon the + * method call. + */ + function errorOn($method, $error = 'A mock error', $args = false, $severity = E_USER_ERROR) { + $this->_dieOnNoMethod($method, "error on"); + $this->_actions->register($method, $args, new SimpleErrorThrower($error, $severity)); + } + + /** + * Sets up a trigger to throw an error upon the + * method call. + */ + function errorAt($timing, $method, $error = 'A mock error', $args = false, $severity = E_USER_ERROR) { + $this->_dieOnNoMethod($method, "error at"); + $this->_actions->registerAt($timing, $method, $args, new SimpleErrorThrower($error, $severity)); + } + + /** + * @deprecated + */ + function tally() { + } + + /** + * Receives event from unit test that the current + * test method has finished. Totals up the call + * counts and triggers a test assertion if a test + * is present for expected call counts. + * @param string $test_method Current method name. + * @param SimpleTestCase $test Test to send message to. + * @access public + */ + function atTestEnd($test_method, &$test) { + foreach ($this->_expected_counts as $method => $expectation) { + $test->assert($expectation, $this->getCallCount($method)); + } + foreach ($this->_max_counts as $method => $expectation) { + if ($expectation->test($this->getCallCount($method))) { + $test->assert($expectation, $this->getCallCount($method)); + } + } + } + + /** + * Returns the expected value for the method name + * and checks expectations. Will generate any + * test assertions as a result of expectations + * if there is a test present. + * @param string $method Name of method to simulate. + * @param array $args Arguments as an array. + * @return mixed Stored return. + * @access private + */ + function &_invoke($method, $args) { + $method = strtolower($method); + $step = $this->getCallCount($method); + $this->_addCall($method, $args); + $this->_checkExpectations($method, $args, $step); + $result = &$this->_emulateCall($method, $args, $step); + return $result; + } + + /** + * Finds the return value matching the incoming + * arguments. If there is no matching value found + * then an error is triggered. + * @param string $method Method name. + * @param array $args Calling arguments. + * @param integer $step Current position in the + * call history. + * @return mixed Stored return or other action. + * @access protected + */ + function &_emulateCall($method, $args, $step) { + return $this->_actions->respond($step, $method, $args); + } + + /** + * Tests the arguments against expectations. + * @param string $method Method to check. + * @param array $args Argument list to match. + * @param integer $timing The position of this call + * in the call history. + * @access private + */ + function _checkExpectations($method, $args, $timing) { + $test = &$this->_getCurrentTestCase(); + if (isset($this->_max_counts[$method])) { + if (! $this->_max_counts[$method]->test($timing + 1)) { + $test->assert($this->_max_counts[$method], $timing + 1); + } + } + if (isset($this->_expected_args_at[$timing][$method])) { + $test->assert( + $this->_expected_args_at[$timing][$method], + $args, + "Mock method [$method] at [$timing] -> %s"); + } elseif (isset($this->_expected_args[$method])) { + $test->assert( + $this->_expected_args[$method], + $args, + "Mock method [$method] -> %s"); + } + } +} + +/** + * Static methods only service class for code generation of + * mock objects. + * @package SimpleTest + * @subpackage MockObjects + */ +class Mock { + + /** + * Factory for mock object classes. + * @access public + */ + function Mock() { + trigger_error('Mock factory methods are static.'); + } + + /** + * Clones a class' interface and creates a mock version + * that can have return values and expectations set. + * @param string $class Class to clone. + * @param string $mock_class New class name. Default is + * the old name with "Mock" + * prepended. + * @param array $methods Additional methods to add beyond + * those in the cloned class. Use this + * to emulate the dynamic addition of + * methods in the cloned class or when + * the class hasn't been written yet. + * @static + * @access public + */ + function generate($class, $mock_class = false, $methods = false) { + $generator = new MockGenerator($class, $mock_class); + return $generator->generateSubclass($methods); + } + + /** + * Generates a version of a class with selected + * methods mocked only. Inherits the old class + * and chains the mock methods of an aggregated + * mock object. + * @param string $class Class to clone. + * @param string $mock_class New class name. + * @param array $methods Methods to be overridden + * with mock versions. + * @static + * @access public + */ + function generatePartial($class, $mock_class, $methods) { + $generator = new MockGenerator($class, $mock_class); + return $generator->generatePartial($methods); + } + + /** + * Uses a stack trace to find the line of an assertion. + * @access public + * @static + */ + function getExpectationLine() { + $trace = new SimpleStackTrace(array('expect')); + return $trace->traceMethod(); + } +} + +/** + * @package SimpleTest + * @subpackage MockObjects + * @deprecated + */ +class Stub extends Mock { +} + +/** + * Service class for code generation of mock objects. + * @package SimpleTest + * @subpackage MockObjects + */ +class MockGenerator { + var $_class; + var $_mock_class; + var $_mock_base; + var $_reflection; + + /** + * Builds initial reflection object. + * @param string $class Class to be mocked. + * @param string $mock_class New class with identical interface, + * but no behaviour. + */ + function MockGenerator($class, $mock_class) { + $this->_class = $class; + $this->_mock_class = $mock_class; + if (! $this->_mock_class) { + $this->_mock_class = 'Mock' . $this->_class; + } + $this->_mock_base = SimpleTest::getMockBaseClass(); + $this->_reflection = new SimpleReflection($this->_class); + } + + /** + * Clones a class' interface and creates a mock version + * that can have return values and expectations set. + * @param array $methods Additional methods to add beyond + * those in th cloned class. Use this + * to emulate the dynamic addition of + * methods in the cloned class or when + * the class hasn't been written yet. + * @access public + */ + function generate($methods) { + if (! $this->_reflection->classOrInterfaceExists()) { + return false; + } + $mock_reflection = new SimpleReflection($this->_mock_class); + if ($mock_reflection->classExistsSansAutoload()) { + return false; + } + $code = $this->_createClassCode($methods ? $methods : array()); + return eval("$code return \$code;"); + } + + /** + * Subclasses a class and overrides every method with a mock one + * that can have return values and expectations set. Chains + * to an aggregated SimpleMock. + * @param array $methods Additional methods to add beyond + * those in the cloned class. Use this + * to emulate the dynamic addition of + * methods in the cloned class or when + * the class hasn't been written yet. + * @access public + */ + function generateSubclass($methods) { + if (! $this->_reflection->classOrInterfaceExists()) { + return false; + } + $mock_reflection = new SimpleReflection($this->_mock_class); + if ($mock_reflection->classExistsSansAutoload()) { + return false; + } + if ($this->_reflection->isInterface() || $this->_reflection->hasFinal()) { + $code = $this->_createClassCode($methods ? $methods : array()); + return eval("$code return \$code;"); + } else { + $code = $this->_createSubclassCode($methods ? $methods : array()); + return eval("$code return \$code;"); + } + } + + /** + * Generates a version of a class with selected + * methods mocked only. Inherits the old class + * and chains the mock methods of an aggregated + * mock object. + * @param array $methods Methods to be overridden + * with mock versions. + * @access public + */ + function generatePartial($methods) { + if (! $this->_reflection->classExists($this->_class)) { + return false; + } + $mock_reflection = new SimpleReflection($this->_mock_class); + if ($mock_reflection->classExistsSansAutoload()) { + trigger_error('Partial mock class [' . $this->_mock_class . '] already exists'); + return false; + } + $code = $this->_extendClassCode($methods); + return eval("$code return \$code;"); + } + + /** + * The new mock class code as a string. + * @param array $methods Additional methods. + * @return string Code for new mock class. + * @access private + */ + function _createClassCode($methods) { + $implements = ''; + $interfaces = $this->_reflection->getInterfaces(); + if (function_exists('spl_classes')) { + $interfaces = array_diff($interfaces, array('Traversable')); + } + if (count($interfaces) > 0) { + $implements = 'implements ' . implode(', ', $interfaces); + } + $code = "class " . $this->_mock_class . " extends " . $this->_mock_base . " $implements {\n"; + $code .= " function " . $this->_mock_class . "() {\n"; + $code .= " \$this->" . $this->_mock_base . "();\n"; + $code .= " }\n"; + if (in_array('__construct', $this->_reflection->getMethods())) { + $code .= " " . $this->_reflection->getSignature('__construct') . " {\n"; + $code .= " \$this->" . $this->_mock_base . "();\n"; + $code .= " }\n"; + } + $code .= $this->_createHandlerCode($methods); + $code .= "}\n"; + return $code; + } + + /** + * The new mock class code as a string. The mock will + * be a subclass of the original mocked class. + * @param array $methods Additional methods. + * @return string Code for new mock class. + * @access private + */ + function _createSubclassCode($methods) { + $code = "class " . $this->_mock_class . " extends " . $this->_class . " {\n"; + $code .= " var \$_mock;\n"; + $code .= $this->_addMethodList(array_merge($methods, $this->_reflection->getMethods())); + $code .= "\n"; + $code .= " function " . $this->_mock_class . "() {\n"; + $code .= " \$this->_mock = &new " . $this->_mock_base . "();\n"; + $code .= " \$this->_mock->disableExpectationNameChecks();\n"; + $code .= " }\n"; + $code .= $this->_chainMockReturns(); + $code .= $this->_chainMockExpectations(); + $code .= $this->_chainThrowMethods(); + $code .= $this->_overrideMethods($this->_reflection->getMethods()); + $code .= $this->_createNewMethodCode($methods); + $code .= "}\n"; + return $code; + } + + /** + * The extension class code as a string. The class + * composites a mock object and chains mocked methods + * to it. + * @param array $methods Mocked methods. + * @return string Code for a new class. + * @access private + */ + function _extendClassCode($methods) { + $code = "class " . $this->_mock_class . " extends " . $this->_class . " {\n"; + $code .= " var \$_mock;\n"; + $code .= $this->_addMethodList($methods); + $code .= "\n"; + $code .= " function " . $this->_mock_class . "() {\n"; + $code .= " \$this->_mock = &new " . $this->_mock_base . "();\n"; + $code .= " \$this->_mock->disableExpectationNameChecks();\n"; + $code .= " }\n"; + $code .= $this->_chainMockReturns(); + $code .= $this->_chainMockExpectations(); + $code .= $this->_chainThrowMethods(); + $code .= $this->_overrideMethods($methods); + $code .= "}\n"; + return $code; + } + + /** + * Creates code within a class to generate replaced + * methods. All methods call the _invoke() handler + * with the method name and the arguments in an + * array. + * @param array $methods Additional methods. + * @access private + */ + function _createHandlerCode($methods) { + $code = ''; + $methods = array_merge($methods, $this->_reflection->getMethods()); + foreach ($methods as $method) { + if ($this->_isConstructor($method)) { + continue; + } + $mock_reflection = new SimpleReflection($this->_mock_base); + if (in_array($method, $mock_reflection->getMethods())) { + continue; + } + $code .= " " . $this->_reflection->getSignature($method) . " {\n"; + $code .= " \$args = func_get_args();\n"; + $code .= " \$result = &\$this->_invoke(\"$method\", \$args);\n"; + $code .= " return \$result;\n"; + $code .= " }\n"; + } + return $code; + } + + /** + * Creates code within a class to generate a new + * methods. All methods call the _invoke() handler + * on the internal mock with the method name and + * the arguments in an array. + * @param array $methods Additional methods. + * @access private + */ + function _createNewMethodCode($methods) { + $code = ''; + foreach ($methods as $method) { + if ($this->_isConstructor($method)) { + continue; + } + $mock_reflection = new SimpleReflection($this->_mock_base); + if (in_array($method, $mock_reflection->getMethods())) { + continue; + } + $code .= " " . $this->_reflection->getSignature($method) . " {\n"; + $code .= " \$args = func_get_args();\n"; + $code .= " \$result = &\$this->_mock->_invoke(\"$method\", \$args);\n"; + $code .= " return \$result;\n"; + $code .= " }\n"; + } + return $code; + } + + /** + * Tests to see if a special PHP method is about to + * be stubbed by mistake. + * @param string $method Method name. + * @return boolean True if special. + * @access private + */ + function _isConstructor($method) { + return in_array( + strtolower($method), + array('__construct', '__destruct')); + } + + /** + * Creates a list of mocked methods for error checking. + * @param array $methods Mocked methods. + * @return string Code for a method list. + * @access private + */ + function _addMethodList($methods) { + return " var \$_mocked_methods = array('" . + implode("', '", array_map('strtolower', $methods)) . + "');\n"; + } + + /** + * Creates code to abandon the expectation if not mocked. + * @param string $alias Parameter name of method name. + * @return string Code for bail out. + * @access private + */ + function _bailOutIfNotMocked($alias) { + $code = " if (! in_array(strtolower($alias), \$this->_mocked_methods)) {\n"; + $code .= " trigger_error(\"Method [$alias] is not mocked\");\n"; + $code .= " \$null = null;\n"; + $code .= " return \$null;\n"; + $code .= " }\n"; + return $code; + } + + /** + * Creates source code for chaining to the composited + * mock object. + * @return string Code for mock set up. + * @access private + */ + function _chainMockReturns() { + $code = " function setReturnValue(\$method, \$value, \$args = false) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->setReturnValue(\$method, \$value, \$args);\n"; + $code .= " }\n"; + $code .= " function setReturnValueAt(\$timing, \$method, \$value, \$args = false) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->setReturnValueAt(\$timing, \$method, \$value, \$args);\n"; + $code .= " }\n"; + $code .= " function setReturnReference(\$method, &\$ref, \$args = false) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->setReturnReference(\$method, \$ref, \$args);\n"; + $code .= " }\n"; + $code .= " function setReturnReferenceAt(\$timing, \$method, &\$ref, \$args = false) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->setReturnReferenceAt(\$timing, \$method, \$ref, \$args);\n"; + $code .= " }\n"; + return $code; + } + + /** + * Creates source code for chaining to an aggregated + * mock object. + * @return string Code for expectations. + * @access private + */ + function _chainMockExpectations() { + $code = " function expect(\$method, \$args = false, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expect(\$method, \$args, \$msg);\n"; + $code .= " }\n"; + $code .= " function expectArguments(\$method, \$args = false, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectArguments(\$method, \$args, \$msg);\n"; + $code .= " }\n"; + $code .= " function expectAt(\$timing, \$method, \$args = false, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args, \$msg);\n"; + $code .= " }\n"; + $code .= " function expectArgumentsAt(\$timing, \$method, \$args = false, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args, \$msg);\n"; + $code .= " }\n"; + $code .= " function expectCallCount(\$method, \$count) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectCallCount(\$method, \$count, \$msg = '%s');\n"; + $code .= " }\n"; + $code .= " function expectMaximumCallCount(\$method, \$count, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectMaximumCallCount(\$method, \$count, \$msg = '%s');\n"; + $code .= " }\n"; + $code .= " function expectMinimumCallCount(\$method, \$count, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectMinimumCallCount(\$method, \$count, \$msg = '%s');\n"; + $code .= " }\n"; + $code .= " function expectNever(\$method) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectNever(\$method);\n"; + $code .= " }\n"; + $code .= " function expectOnce(\$method, \$args = false, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectOnce(\$method, \$args, \$msg);\n"; + $code .= " }\n"; + $code .= " function expectAtLeastOnce(\$method, \$args = false, \$msg = '%s') {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->expectAtLeastOnce(\$method, \$args, \$msg);\n"; + $code .= " }\n"; + $code .= " function tally() {\n"; + $code .= " }\n"; + return $code; + } + + /** + * Adds code for chaining the throw methods. + * @return string Code for chains. + * @access private + */ + function _chainThrowMethods() { + $code = " function throwOn(\$method, \$exception = false, \$args = false) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->throwOn(\$method, \$exception, \$args);\n"; + $code .= " }\n"; + $code .= " function throwAt(\$timing, \$method, \$exception = false, \$args = false) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->throwAt(\$timing, \$method, \$exception, \$args);\n"; + $code .= " }\n"; + $code .= " function errorOn(\$method, \$error = 'A mock error', \$args = false, \$severity = E_USER_ERROR) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->errorOn(\$method, \$error, \$args, \$severity);\n"; + $code .= " }\n"; + $code .= " function errorAt(\$timing, \$method, \$error = 'A mock error', \$args = false, \$severity = E_USER_ERROR) {\n"; + $code .= $this->_bailOutIfNotMocked("\$method"); + $code .= " \$this->_mock->errorAt(\$timing, \$method, \$error, \$args, \$severity);\n"; + $code .= " }\n"; + return $code; + } + + /** + * Creates source code to override a list of methods + * with mock versions. + * @param array $methods Methods to be overridden + * with mock versions. + * @return string Code for overridden chains. + * @access private + */ + function _overrideMethods($methods) { + $code = ""; + foreach ($methods as $method) { + if ($this->_isConstructor($method)) { + continue; + } + $code .= " " . $this->_reflection->getSignature($method) . " {\n"; + $code .= " \$args = func_get_args();\n"; + $code .= " \$result = &\$this->_mock->_invoke(\"$method\", \$args);\n"; + $code .= " return \$result;\n"; + $code .= " }\n"; + } + return $code; + } +} +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/page.php b/plugins/www/testgen4web_simpletest/lib/simpletest/page.php new file mode 100644 index 0000000..08e5649 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/page.php @@ -0,0 +1,983 @@ + 'SimpleAnchorTag', + 'title' => 'SimpleTitleTag', + 'base' => 'SimpleBaseTag', + 'button' => 'SimpleButtonTag', + 'textarea' => 'SimpleTextAreaTag', + 'option' => 'SimpleOptionTag', + 'label' => 'SimpleLabelTag', + 'form' => 'SimpleFormTag', + 'frame' => 'SimpleFrameTag'); + $attributes = $this->_keysToLowerCase($attributes); + if (array_key_exists($name, $map)) { + $tag_class = $map[$name]; + return new $tag_class($attributes); + } elseif ($name == 'select') { + return $this->_createSelectionTag($attributes); + } elseif ($name == 'input') { + return $this->_createInputTag($attributes); + } + return new SimpleTag($name, $attributes); + } + + /** + * Factory for selection fields. + * @param hash $attributes Element attributes. + * @return SimpleTag Tag object. + * @access protected + */ + function _createSelectionTag($attributes) { + if (isset($attributes['multiple'])) { + return new MultipleSelectionTag($attributes); + } + return new SimpleSelectionTag($attributes); + } + + /** + * Factory for input tags. + * @param hash $attributes Element attributes. + * @return SimpleTag Tag object. + * @access protected + */ + function _createInputTag($attributes) { + if (! isset($attributes['type'])) { + return new SimpleTextTag($attributes); + } + $type = strtolower(trim($attributes['type'])); + $map = array( + 'submit' => 'SimpleSubmitTag', + 'image' => 'SimpleImageSubmitTag', + 'checkbox' => 'SimpleCheckboxTag', + 'radio' => 'SimpleRadioButtonTag', + 'text' => 'SimpleTextTag', + 'hidden' => 'SimpleTextTag', + 'password' => 'SimpleTextTag', + 'file' => 'SimpleUploadTag'); + if (array_key_exists($type, $map)) { + $tag_class = $map[$type]; + return new $tag_class($attributes); + } + return false; + } + + /** + * Make the keys lower case for case insensitive look-ups. + * @param hash $map Hash to convert. + * @return hash Unchanged values, but keys lower case. + * @access private + */ + function _keysToLowerCase($map) { + $lower = array(); + foreach ($map as $key => $value) { + $lower[strtolower($key)] = $value; + } + return $lower; + } +} + +/** + * SAX event handler. Maintains a list of + * open tags and dispatches them as they close. + * @package SimpleTest + * @subpackage WebTester + */ +class SimplePageBuilder extends SimpleSaxListener { + var $_tags; + var $_page; + var $_private_content_tag; + + /** + * Sets the builder up empty. + * @access public + */ + function SimplePageBuilder() { + $this->SimpleSaxListener(); + } + + /** + * Frees up any references so as to allow the PHP garbage + * collection from unset() to work. + * @access public + */ + function free() { + unset($this->_tags); + unset($this->_page); + unset($this->_private_content_tags); + } + + /** + * Reads the raw content and send events + * into the page to be built. + * @param $response SimpleHttpResponse Fetched response. + * @return SimplePage Newly parsed page. + * @access public + */ + function &parse($response) { + $this->_tags = array(); + $this->_page = &$this->_createPage($response); + $parser = &$this->_createParser($this); + $parser->parse($response->getContent()); + $this->_page->acceptPageEnd(); + return $this->_page; + } + + /** + * Creates an empty page. + * @return SimplePage New unparsed page. + * @access protected + */ + function &_createPage($response) { + $page = &new SimplePage($response); + return $page; + } + + /** + * Creates the parser used with the builder. + * @param $listener SimpleSaxListener Target of parser. + * @return SimpleSaxParser Parser to generate + * events for the builder. + * @access protected + */ + function &_createParser(&$listener) { + $parser = &new SimpleHtmlSaxParser($listener); + return $parser; + } + + /** + * Start of element event. Opens a new tag. + * @param string $name Element name. + * @param hash $attributes Attributes without content + * are marked as true. + * @return boolean False on parse error. + * @access public + */ + function startElement($name, $attributes) { + $factory = &new SimpleTagBuilder(); + $tag = $factory->createTag($name, $attributes); + if (! $tag) { + return true; + } + if ($tag->getTagName() == 'label') { + $this->_page->acceptLabelStart($tag); + $this->_openTag($tag); + return true; + } + if ($tag->getTagName() == 'form') { + $this->_page->acceptFormStart($tag); + return true; + } + if ($tag->getTagName() == 'frameset') { + $this->_page->acceptFramesetStart($tag); + return true; + } + if ($tag->getTagName() == 'frame') { + $this->_page->acceptFrame($tag); + return true; + } + if ($tag->isPrivateContent() && ! isset($this->_private_content_tag)) { + $this->_private_content_tag = &$tag; + } + if ($tag->expectEndTag()) { + $this->_openTag($tag); + return true; + } + $this->_page->acceptTag($tag); + return true; + } + + /** + * End of element event. + * @param string $name Element name. + * @return boolean False on parse error. + * @access public + */ + function endElement($name) { + if ($name == 'label') { + $this->_page->acceptLabelEnd(); + return true; + } + if ($name == 'form') { + $this->_page->acceptFormEnd(); + return true; + } + if ($name == 'frameset') { + $this->_page->acceptFramesetEnd(); + return true; + } + if ($this->_hasNamedTagOnOpenTagStack($name)) { + $tag = array_pop($this->_tags[$name]); + if ($tag->isPrivateContent() && $this->_private_content_tag->getTagName() == $name) { + unset($this->_private_content_tag); + } + $this->_addContentTagToOpenTags($tag); + $this->_page->acceptTag($tag); + return true; + } + return true; + } + + /** + * Test to see if there are any open tags awaiting + * closure that match the tag name. + * @param string $name Element name. + * @return boolean True if any are still open. + * @access private + */ + function _hasNamedTagOnOpenTagStack($name) { + return isset($this->_tags[$name]) && (count($this->_tags[$name]) > 0); + } + + /** + * Unparsed, but relevant data. The data is added + * to every open tag. + * @param string $text May include unparsed tags. + * @return boolean False on parse error. + * @access public + */ + function addContent($text) { + if (isset($this->_private_content_tag)) { + $this->_private_content_tag->addContent($text); + } else { + $this->_addContentToAllOpenTags($text); + } + return true; + } + + /** + * Any content fills all currently open tags unless it + * is part of an option tag. + * @param string $text May include unparsed tags. + * @access private + */ + function _addContentToAllOpenTags($text) { + foreach (array_keys($this->_tags) as $name) { + for ($i = 0, $count = count($this->_tags[$name]); $i < $count; $i++) { + $this->_tags[$name][$i]->addContent($text); + } + } + } + + /** + * Parsed data in tag form. The parsed tag is added + * to every open tag. Used for adding options to select + * fields only. + * @param SimpleTag $tag Option tags only. + * @access private + */ + function _addContentTagToOpenTags(&$tag) { + if ($tag->getTagName() != 'option') { + return; + } + foreach (array_keys($this->_tags) as $name) { + for ($i = 0, $count = count($this->_tags[$name]); $i < $count; $i++) { + $this->_tags[$name][$i]->addTag($tag); + } + } + } + + /** + * Opens a tag for receiving content. Multiple tags + * will be receiving input at the same time. + * @param SimpleTag $tag New content tag. + * @access private + */ + function _openTag(&$tag) { + $name = $tag->getTagName(); + if (! in_array($name, array_keys($this->_tags))) { + $this->_tags[$name] = array(); + } + $this->_tags[$name][] = &$tag; + } +} + +/** + * A wrapper for a web page. + * @package SimpleTest + * @subpackage WebTester + */ +class SimplePage { + var $_links; + var $_title; + var $_last_widget; + var $_label; + var $_left_over_labels; + var $_open_forms; + var $_complete_forms; + var $_frameset; + var $_frames; + var $_frameset_nesting_level; + var $_transport_error; + var $_raw; + var $_text; + var $_sent; + var $_headers; + var $_method; + var $_url; + var $_base = false; + var $_request_data; + + /** + * Parses a page ready to access it's contents. + * @param SimpleHttpResponse $response Result of HTTP fetch. + * @access public + */ + function SimplePage($response = false) { + $this->_links = array(); + $this->_title = false; + $this->_left_over_labels = array(); + $this->_open_forms = array(); + $this->_complete_forms = array(); + $this->_frameset = false; + $this->_frames = array(); + $this->_frameset_nesting_level = 0; + $this->_text = false; + if ($response) { + $this->_extractResponse($response); + } else { + $this->_noResponse(); + } + } + + /** + * Extracts all of the response information. + * @param SimpleHttpResponse $response Response being parsed. + * @access private + */ + function _extractResponse($response) { + $this->_transport_error = $response->getError(); + $this->_raw = $response->getContent(); + $this->_sent = $response->getSent(); + $this->_headers = $response->getHeaders(); + $this->_method = $response->getMethod(); + $this->_url = $response->getUrl(); + $this->_request_data = $response->getRequestData(); + } + + /** + * Sets up a missing response. + * @access private + */ + function _noResponse() { + $this->_transport_error = 'No page fetched yet'; + $this->_raw = false; + $this->_sent = false; + $this->_headers = false; + $this->_method = 'GET'; + $this->_url = false; + $this->_request_data = false; + } + + /** + * Original request as bytes sent down the wire. + * @return mixed Sent content. + * @access public + */ + function getRequest() { + return $this->_sent; + } + + /** + * Accessor for raw text of page. + * @return string Raw unparsed content. + * @access public + */ + function getRaw() { + return $this->_raw; + } + + /** + * Accessor for plain text of page as a text browser + * would see it. + * @return string Plain text of page. + * @access public + */ + function getText() { + if (! $this->_text) { + $this->_text = SimpleHtmlSaxParser::normalise($this->_raw); + } + return $this->_text; + } + + /** + * Accessor for raw headers of page. + * @return string Header block as text. + * @access public + */ + function getHeaders() { + if ($this->_headers) { + return $this->_headers->getRaw(); + } + return false; + } + + /** + * Original request method. + * @return string GET, POST or HEAD. + * @access public + */ + function getMethod() { + return $this->_method; + } + + /** + * Original resource name. + * @return SimpleUrl Current url. + * @access public + */ + function getUrl() { + return $this->_url; + } + + /** + * Base URL if set via BASE tag page url otherwise + * @return SimpleUrl Base url. + * @access public + */ + function getBaseUrl() { + return $this->_base; + } + + /** + * Original request data. + * @return mixed Sent content. + * @access public + */ + function getRequestData() { + return $this->_request_data; + } + + /** + * Accessor for last error. + * @return string Error from last response. + * @access public + */ + function getTransportError() { + return $this->_transport_error; + } + + /** + * Accessor for current MIME type. + * @return string MIME type as string; e.g. 'text/html' + * @access public + */ + function getMimeType() { + if ($this->_headers) { + return $this->_headers->getMimeType(); + } + return false; + } + + /** + * Accessor for HTTP response code. + * @return integer HTTP response code received. + * @access public + */ + function getResponseCode() { + if ($this->_headers) { + return $this->_headers->getResponseCode(); + } + return false; + } + + /** + * Accessor for last Authentication type. Only valid + * straight after a challenge (401). + * @return string Description of challenge type. + * @access public + */ + function getAuthentication() { + if ($this->_headers) { + return $this->_headers->getAuthentication(); + } + return false; + } + + /** + * Accessor for last Authentication realm. Only valid + * straight after a challenge (401). + * @return string Name of security realm. + * @access public + */ + function getRealm() { + if ($this->_headers) { + return $this->_headers->getRealm(); + } + return false; + } + + /** + * Accessor for current frame focus. Will be + * false as no frames. + * @return array Always empty. + * @access public + */ + function getFrameFocus() { + return array(); + } + + /** + * Sets the focus by index. The integer index starts from 1. + * @param integer $choice Chosen frame. + * @return boolean Always false. + * @access public + */ + function setFrameFocusByIndex($choice) { + return false; + } + + /** + * Sets the focus by name. Always fails for a leaf page. + * @param string $name Chosen frame. + * @return boolean False as no frames. + * @access public + */ + function setFrameFocus($name) { + return false; + } + + /** + * Clears the frame focus. Does nothing for a leaf page. + * @access public + */ + function clearFrameFocus() { + } + + /** + * Adds a tag to the page. + * @param SimpleTag $tag Tag to accept. + * @access public + */ + function acceptTag(&$tag) { + if ($tag->getTagName() == "a") { + $this->_addLink($tag); + } elseif ($tag->getTagName() == "base") { + $this->_setBase($tag); + } elseif ($tag->getTagName() == "title") { + $this->_setTitle($tag); + } elseif ($this->_isFormElement($tag->getTagName())) { + for ($i = 0; $i < count($this->_open_forms); $i++) { + $this->_open_forms[$i]->addWidget($tag); + } + $this->_last_widget = &$tag; + } + } + + /** + * Opens a label for a described widget. + * @param SimpleFormTag $tag Tag to accept. + * @access public + */ + function acceptLabelStart(&$tag) { + $this->_label = &$tag; + unset($this->_last_widget); + } + + /** + * Closes the most recently opened label. + * @access public + */ + function acceptLabelEnd() { + if (isset($this->_label)) { + if (isset($this->_last_widget)) { + $this->_last_widget->setLabel($this->_label->getText()); + unset($this->_last_widget); + } else { + $this->_left_over_labels[] = SimpleTestCompatibility::copy($this->_label); + } + unset($this->_label); + } + } + + /** + * Tests to see if a tag is a possible form + * element. + * @param string $name HTML element name. + * @return boolean True if form element. + * @access private + */ + function _isFormElement($name) { + return in_array($name, array('input', 'button', 'textarea', 'select')); + } + + /** + * Opens a form. New widgets go here. + * @param SimpleFormTag $tag Tag to accept. + * @access public + */ + function acceptFormStart(&$tag) { + $this->_open_forms[] = &new SimpleForm($tag, $this); + } + + /** + * Closes the most recently opened form. + * @access public + */ + function acceptFormEnd() { + if (count($this->_open_forms)) { + $this->_complete_forms[] = array_pop($this->_open_forms); + } + } + + /** + * Opens a frameset. A frameset may contain nested + * frameset tags. + * @param SimpleFramesetTag $tag Tag to accept. + * @access public + */ + function acceptFramesetStart(&$tag) { + if (! $this->_isLoadingFrames()) { + $this->_frameset = &$tag; + } + $this->_frameset_nesting_level++; + } + + /** + * Closes the most recently opened frameset. + * @access public + */ + function acceptFramesetEnd() { + if ($this->_isLoadingFrames()) { + $this->_frameset_nesting_level--; + } + } + + /** + * Takes a single frame tag and stashes it in + * the current frame set. + * @param SimpleFrameTag $tag Tag to accept. + * @access public + */ + function acceptFrame(&$tag) { + if ($this->_isLoadingFrames()) { + if ($tag->getAttribute('src')) { + $this->_frames[] = &$tag; + } + } + } + + /** + * Test to see if in the middle of reading + * a frameset. + * @return boolean True if inframeset. + * @access private + */ + function _isLoadingFrames() { + if (! $this->_frameset) { + return false; + } + return ($this->_frameset_nesting_level > 0); + } + + /** + * Test to see if link is an absolute one. + * @param string $url Url to test. + * @return boolean True if absolute. + * @access protected + */ + function _linkIsAbsolute($url) { + $parsed = new SimpleUrl($url); + return (boolean)($parsed->getScheme() && $parsed->getHost()); + } + + /** + * Adds a link to the page. + * @param SimpleAnchorTag $tag Link to accept. + * @access protected + */ + function _addLink($tag) { + $this->_links[] = $tag; + } + + /** + * Marker for end of complete page. Any work in + * progress can now be closed. + * @access public + */ + function acceptPageEnd() { + while (count($this->_open_forms)) { + $this->_complete_forms[] = array_pop($this->_open_forms); + } + foreach ($this->_left_over_labels as $label) { + for ($i = 0, $count = count($this->_complete_forms); $i < $count; $i++) { + $this->_complete_forms[$i]->attachLabelBySelector( + new SimpleById($label->getFor()), + $label->getText()); + } + } + } + + /** + * Test for the presence of a frameset. + * @return boolean True if frameset. + * @access public + */ + function hasFrames() { + return (boolean)$this->_frameset; + } + + /** + * Accessor for frame name and source URL for every frame that + * will need to be loaded. Immediate children only. + * @return boolean/array False if no frameset or + * otherwise a hash of frame URLs. + * The key is either a numerical + * base one index or the name attribute. + * @access public + */ + function getFrameset() { + if (! $this->_frameset) { + return false; + } + $urls = array(); + for ($i = 0; $i < count($this->_frames); $i++) { + $name = $this->_frames[$i]->getAttribute('name'); + $url = new SimpleUrl($this->_frames[$i]->getAttribute('src')); + $urls[$name ? $name : $i + 1] = $this->expandUrl($url); + } + return $urls; + } + + /** + * Fetches a list of loaded frames. + * @return array/string Just the URL for a single page. + * @access public + */ + function getFrames() { + $url = $this->expandUrl($this->getUrl()); + return $url->asString(); + } + + /** + * Accessor for a list of all links. + * @return array List of urls with scheme of + * http or https and hostname. + * @access public + */ + function getUrls() { + $all = array(); + foreach ($this->_links as $link) { + $url = $this->_getUrlFromLink($link); + $all[] = $url->asString(); + } + return $all; + } + + /** + * Accessor for URLs by the link label. Label will match + * regardess of whitespace issues and case. + * @param string $label Text of link. + * @return array List of links with that label. + * @access public + */ + function getUrlsByLabel($label) { + $matches = array(); + foreach ($this->_links as $link) { + if ($link->getText() == $label) { + $matches[] = $this->_getUrlFromLink($link); + } + } + return $matches; + } + + /** + * Accessor for a URL by the id attribute. + * @param string $id Id attribute of link. + * @return SimpleUrl URL with that id of false if none. + * @access public + */ + function getUrlById($id) { + foreach ($this->_links as $link) { + if ($link->getAttribute('id') === (string)$id) { + return $this->_getUrlFromLink($link); + } + } + return false; + } + + /** + * Converts a link tag into a target URL. + * @param SimpleAnchor $link Parsed link. + * @return SimpleUrl URL with frame target if any. + * @access private + */ + function _getUrlFromLink($link) { + $url = $this->expandUrl($link->getHref()); + if ($link->getAttribute('target')) { + $url->setTarget($link->getAttribute('target')); + } + return $url; + } + + /** + * Expands expandomatic URLs into fully qualified + * URLs. + * @param SimpleUrl $url Relative URL. + * @return SimpleUrl Absolute URL. + * @access public + */ + function expandUrl($url) { + if (! is_object($url)) { + $url = new SimpleUrl($url); + } + $location = $this->getBaseUrl() ? $this->getBaseUrl() : new SimpleUrl(); + return $url->makeAbsolute($location->makeAbsolute($this->getUrl())); + } + + /** + * Sets the base url for the page. + * @param SimpleTag $tag Base URL for page. + * @access protected + */ + function _setBase(&$tag) { + $url = $tag->getAttribute('href'); + $this->_base = new SimpleUrl($url); + } + + /** + * Sets the title tag contents. + * @param SimpleTitleTag $tag Title of page. + * @access protected + */ + function _setTitle(&$tag) { + $this->_title = &$tag; + } + + /** + * Accessor for parsed title. + * @return string Title or false if no title is present. + * @access public + */ + function getTitle() { + if ($this->_title) { + return $this->_title->getText(); + } + return false; + } + + /** + * Finds a held form by button label. Will only + * search correctly built forms. + * @param SimpleSelector $selector Button finder. + * @return SimpleForm Form object containing + * the button. + * @access public + */ + function &getFormBySubmit($selector) { + for ($i = 0; $i < count($this->_complete_forms); $i++) { + if ($this->_complete_forms[$i]->hasSubmit($selector)) { + return $this->_complete_forms[$i]; + } + } + $null = null; + return $null; + } + + /** + * Finds a held form by image using a selector. + * Will only search correctly built forms. + * @param SimpleSelector $selector Image finder. + * @return SimpleForm Form object containing + * the image. + * @access public + */ + function &getFormByImage($selector) { + for ($i = 0; $i < count($this->_complete_forms); $i++) { + if ($this->_complete_forms[$i]->hasImage($selector)) { + return $this->_complete_forms[$i]; + } + } + $null = null; + return $null; + } + + /** + * Finds a held form by the form ID. A way of + * identifying a specific form when we have control + * of the HTML code. + * @param string $id Form label. + * @return SimpleForm Form object containing the matching ID. + * @access public + */ + function &getFormById($id) { + for ($i = 0; $i < count($this->_complete_forms); $i++) { + if ($this->_complete_forms[$i]->getId() == $id) { + return $this->_complete_forms[$i]; + } + } + $null = null; + return $null; + } + + /** + * Sets a field on each form in which the field is + * available. + * @param SimpleSelector $selector Field finder. + * @param string $value Value to set field to. + * @return boolean True if value is valid. + * @access public + */ + function setField($selector, $value, $position=false) { + $is_set = false; + for ($i = 0; $i < count($this->_complete_forms); $i++) { + if ($this->_complete_forms[$i]->setField($selector, $value, $position)) { + $is_set = true; + } + } + return $is_set; + } + + /** + * Accessor for a form element value within a page. + * @param SimpleSelector $selector Field finder. + * @return string/boolean A string if the field is + * present, false if unchecked + * and null if missing. + * @access public + */ + function getField($selector) { + for ($i = 0; $i < count($this->_complete_forms); $i++) { + $value = $this->_complete_forms[$i]->getValue($selector); + if (isset($value)) { + return $value; + } + } + return null; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/parser.php b/plugins/www/testgen4web_simpletest/lib/simpletest/parser.php new file mode 100644 index 0000000..3f3b37b --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/parser.php @@ -0,0 +1,764 @@ + $constant) { + if (! defined($constant)) { + define($constant, $i + 1); + } +} +/**#@-*/ + +/** + * Compounded regular expression. Any of + * the contained patterns could match and + * when one does, it's label is returned. + * @package SimpleTest + * @subpackage WebTester + */ +class ParallelRegex { + var $_patterns; + var $_labels; + var $_regex; + var $_case; + + /** + * Constructor. Starts with no patterns. + * @param boolean $case True for case sensitive, false + * for insensitive. + * @access public + */ + function ParallelRegex($case) { + $this->_case = $case; + $this->_patterns = array(); + $this->_labels = array(); + $this->_regex = null; + } + + /** + * Adds a pattern with an optional label. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $label Label of regex to be returned + * on a match. + * @access public + */ + function addPattern($pattern, $label = true) { + $count = count($this->_patterns); + $this->_patterns[$count] = $pattern; + $this->_labels[$count] = $label; + $this->_regex = null; + } + + /** + * Attempts to match all patterns at once against + * a string. + * @param string $subject String to match against. + * @param string $match First matched portion of + * subject. + * @return boolean True on success. + * @access public + */ + function match($subject, &$match) { + if (count($this->_patterns) == 0) { + return false; + } + if (! preg_match($this->_getCompoundedRegex(), $subject, $matches)) { + $match = ''; + return false; + } + $match = $matches[0]; + for ($i = 1; $i < count($matches); $i++) { + if ($matches[$i]) { + return $this->_labels[$i - 1]; + } + } + return true; + } + + /** + * Compounds the patterns into a single + * regular expression separated with the + * "or" operator. Caches the regex. + * Will automatically escape (, ) and / tokens. + * @param array $patterns List of patterns in order. + * @access private + */ + function _getCompoundedRegex() { + if ($this->_regex == null) { + for ($i = 0, $count = count($this->_patterns); $i < $count; $i++) { + $this->_patterns[$i] = '(' . str_replace( + array('/', '(', ')'), + array('\/', '\(', '\)'), + $this->_patterns[$i]) . ')'; + } + $this->_regex = "/" . implode("|", $this->_patterns) . "/" . $this->_getPerlMatchingFlags(); + } + return $this->_regex; + } + + /** + * Accessor for perl regex mode flags to use. + * @return string Perl regex flags. + * @access private + */ + function _getPerlMatchingFlags() { + return ($this->_case ? "msS" : "msSi"); + } +} + +/** + * States for a stack machine. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleStateStack { + var $_stack; + + /** + * Constructor. Starts in named state. + * @param string $start Starting state name. + * @access public + */ + function SimpleStateStack($start) { + $this->_stack = array($start); + } + + /** + * Accessor for current state. + * @return string State. + * @access public + */ + function getCurrent() { + return $this->_stack[count($this->_stack) - 1]; + } + + /** + * Adds a state to the stack and sets it + * to be the current state. + * @param string $state New state. + * @access public + */ + function enter($state) { + array_push($this->_stack, $state); + } + + /** + * Leaves the current state and reverts + * to the previous one. + * @return boolean False if we drop off + * the bottom of the list. + * @access public + */ + function leave() { + if (count($this->_stack) == 1) { + return false; + } + array_pop($this->_stack); + return true; + } +} + +/** + * Accepts text and breaks it into tokens. + * Some optimisation to make the sure the + * content is only scanned by the PHP regex + * parser once. Lexer modes must not start + * with leading underscores. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleLexer { + var $_regexes; + var $_parser; + var $_mode; + var $_mode_handlers; + var $_case; + + /** + * Sets up the lexer in case insensitive matching + * by default. + * @param SimpleSaxParser $parser Handling strategy by + * reference. + * @param string $start Starting handler. + * @param boolean $case True for case sensitive. + * @access public + */ + function SimpleLexer(&$parser, $start = "accept", $case = false) { + $this->_case = $case; + $this->_regexes = array(); + $this->_parser = &$parser; + $this->_mode = &new SimpleStateStack($start); + $this->_mode_handlers = array($start => $start); + } + + /** + * Adds a token search pattern for a particular + * parsing mode. The pattern does not change the + * current mode. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @access public + */ + function addPattern($pattern, $mode = "accept") { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new ParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern); + if (! isset($this->_mode_handlers[$mode])) { + $this->_mode_handlers[$mode] = $mode; + } + } + + /** + * Adds a pattern that will enter a new parsing + * mode. Useful for entering parenthesis, strings, + * tags, etc. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @param string $new_mode Change parsing to this new + * nested mode. + * @access public + */ + function addEntryPattern($pattern, $mode, $new_mode) { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new ParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern, $new_mode); + if (! isset($this->_mode_handlers[$new_mode])) { + $this->_mode_handlers[$new_mode] = $new_mode; + } + } + + /** + * Adds a pattern that will exit the current mode + * and re-enter the previous one. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Mode to leave. + * @access public + */ + function addExitPattern($pattern, $mode) { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new ParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern, "__exit"); + if (! isset($this->_mode_handlers[$mode])) { + $this->_mode_handlers[$mode] = $mode; + } + } + + /** + * Adds a pattern that has a special mode. Acts as an entry + * and exit pattern in one go, effectively calling a special + * parser handler for this token only. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @param string $special Use this mode for this one token. + * @access public + */ + function addSpecialPattern($pattern, $mode, $special) { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new ParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern, "_$special"); + if (! isset($this->_mode_handlers[$special])) { + $this->_mode_handlers[$special] = $special; + } + } + + /** + * Adds a mapping from a mode to another handler. + * @param string $mode Mode to be remapped. + * @param string $handler New target handler. + * @access public + */ + function mapHandler($mode, $handler) { + $this->_mode_handlers[$mode] = $handler; + } + + /** + * Splits the page text into tokens. Will fail + * if the handlers report an error or if no + * content is consumed. If successful then each + * unparsed and parsed token invokes a call to the + * held listener. + * @param string $raw Raw HTML text. + * @return boolean True on success, else false. + * @access public + */ + function parse($raw) { + if (! isset($this->_parser)) { + return false; + } + $length = strlen($raw); + while (is_array($parsed = $this->_reduce($raw))) { + list($raw, $unmatched, $matched, $mode) = $parsed; + if (! $this->_dispatchTokens($unmatched, $matched, $mode)) { + return false; + } + if ($raw === '') { + return true; + } + if (strlen($raw) == $length) { + return false; + } + $length = strlen($raw); + } + if (! $parsed) { + return false; + } + return $this->_invokeParser($raw, LEXER_UNMATCHED); + } + + /** + * Sends the matched token and any leading unmatched + * text to the parser changing the lexer to a new + * mode if one is listed. + * @param string $unmatched Unmatched leading portion. + * @param string $matched Actual token match. + * @param string $mode Mode after match. A boolean + * false mode causes no change. + * @return boolean False if there was any error + * from the parser. + * @access private + */ + function _dispatchTokens($unmatched, $matched, $mode = false) { + if (! $this->_invokeParser($unmatched, LEXER_UNMATCHED)) { + return false; + } + if (is_bool($mode)) { + return $this->_invokeParser($matched, LEXER_MATCHED); + } + if ($this->_isModeEnd($mode)) { + if (! $this->_invokeParser($matched, LEXER_EXIT)) { + return false; + } + return $this->_mode->leave(); + } + if ($this->_isSpecialMode($mode)) { + $this->_mode->enter($this->_decodeSpecial($mode)); + if (! $this->_invokeParser($matched, LEXER_SPECIAL)) { + return false; + } + return $this->_mode->leave(); + } + $this->_mode->enter($mode); + return $this->_invokeParser($matched, LEXER_ENTER); + } + + /** + * Tests to see if the new mode is actually to leave + * the current mode and pop an item from the matching + * mode stack. + * @param string $mode Mode to test. + * @return boolean True if this is the exit mode. + * @access private + */ + function _isModeEnd($mode) { + return ($mode === "__exit"); + } + + /** + * Test to see if the mode is one where this mode + * is entered for this token only and automatically + * leaves immediately afterwoods. + * @param string $mode Mode to test. + * @return boolean True if this is the exit mode. + * @access private + */ + function _isSpecialMode($mode) { + return (strncmp($mode, "_", 1) == 0); + } + + /** + * Strips the magic underscore marking single token + * modes. + * @param string $mode Mode to decode. + * @return string Underlying mode name. + * @access private + */ + function _decodeSpecial($mode) { + return substr($mode, 1); + } + + /** + * Calls the parser method named after the current + * mode. Empty content will be ignored. The lexer + * has a parser handler for each mode in the lexer. + * @param string $content Text parsed. + * @param boolean $is_match Token is recognised rather + * than unparsed data. + * @access private + */ + function _invokeParser($content, $is_match) { + if (($content === '') || ($content === false)) { + return true; + } + $handler = $this->_mode_handlers[$this->_mode->getCurrent()]; + return $this->_parser->$handler($content, $is_match); + } + + /** + * Tries to match a chunk of text and if successful + * removes the recognised chunk and any leading + * unparsed data. Empty strings will not be matched. + * @param string $raw The subject to parse. This is the + * content that will be eaten. + * @return array/boolean Three item list of unparsed + * content followed by the + * recognised token and finally the + * action the parser is to take. + * True if no match, false if there + * is a parsing error. + * @access private + */ + function _reduce($raw) { + if ($action = $this->_regexes[$this->_mode->getCurrent()]->match($raw, $match)) { + $unparsed_character_count = strpos($raw, $match); + $unparsed = substr($raw, 0, $unparsed_character_count); + $raw = substr($raw, $unparsed_character_count + strlen($match)); + return array($raw, $unparsed, $match, $action); + } + return true; + } +} + +/** + * Breaks HTML into SAX events. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleHtmlLexer extends SimpleLexer { + + /** + * Sets up the lexer with case insensitive matching + * and adds the HTML handlers. + * @param SimpleSaxParser $parser Handling strategy by + * reference. + * @access public + */ + function SimpleHtmlLexer(&$parser) { + $this->SimpleLexer($parser, 'text'); + $this->mapHandler('text', 'acceptTextToken'); + $this->_addSkipping(); + foreach ($this->_getParsedTags() as $tag) { + $this->_addTag($tag); + } + $this->_addInTagTokens(); + } + + /** + * List of parsed tags. Others are ignored. + * @return array List of searched for tags. + * @access private + */ + function _getParsedTags() { + return array('a', 'base', 'title', 'form', 'input', 'button', 'textarea', 'select', + 'option', 'frameset', 'frame', 'label'); + } + + /** + * The lexer has to skip certain sections such + * as server code, client code and styles. + * @access private + */ + function _addSkipping() { + $this->mapHandler('css', 'ignore'); + $this->addEntryPattern('addExitPattern('', 'css'); + $this->mapHandler('js', 'ignore'); + $this->addEntryPattern('addExitPattern('', 'js'); + $this->mapHandler('comment', 'ignore'); + $this->addEntryPattern('', 'comment'); + } + + /** + * Pattern matches to start and end a tag. + * @param string $tag Name of tag to scan for. + * @access private + */ + function _addTag($tag) { + $this->addSpecialPattern("", 'text', 'acceptEndToken'); + $this->addEntryPattern("<$tag", 'text', 'tag'); + } + + /** + * Pattern matches to parse the inside of a tag + * including the attributes and their quoting. + * @access private + */ + function _addInTagTokens() { + $this->mapHandler('tag', 'acceptStartToken'); + $this->addSpecialPattern('\s+', 'tag', 'ignore'); + $this->_addAttributeTokens(); + $this->addExitPattern('/>', 'tag'); + $this->addExitPattern('>', 'tag'); + } + + /** + * Matches attributes that are either single quoted, + * double quoted or unquoted. + * @access private + */ + function _addAttributeTokens() { + $this->mapHandler('dq_attribute', 'acceptAttributeToken'); + $this->addEntryPattern('=\s*"', 'tag', 'dq_attribute'); + $this->addPattern("\\\\\"", 'dq_attribute'); + $this->addExitPattern('"', 'dq_attribute'); + $this->mapHandler('sq_attribute', 'acceptAttributeToken'); + $this->addEntryPattern("=\s*'", 'tag', 'sq_attribute'); + $this->addPattern("\\\\'", 'sq_attribute'); + $this->addExitPattern("'", 'sq_attribute'); + $this->mapHandler('uq_attribute', 'acceptAttributeToken'); + $this->addSpecialPattern('=\s*[^>\s]*', 'tag', 'uq_attribute'); + } +} + +/** + * Converts HTML tokens into selected SAX events. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleHtmlSaxParser { + var $_lexer; + var $_listener; + var $_tag; + var $_attributes; + var $_current_attribute; + + /** + * Sets the listener. + * @param SimpleSaxListener $listener SAX event handler. + * @access public + */ + function SimpleHtmlSaxParser(&$listener) { + $this->_listener = &$listener; + $this->_lexer = &$this->createLexer($this); + $this->_tag = ''; + $this->_attributes = array(); + $this->_current_attribute = ''; + } + + /** + * Runs the content through the lexer which + * should call back to the acceptors. + * @param string $raw Page text to parse. + * @return boolean False if parse error. + * @access public + */ + function parse($raw) { + return $this->_lexer->parse($raw); + } + + /** + * Sets up the matching lexer. Starts in 'text' mode. + * @param SimpleSaxParser $parser Event generator, usually $self. + * @return SimpleLexer Lexer suitable for this parser. + * @access public + * @static + */ + function &createLexer(&$parser) { + $lexer = &new SimpleHtmlLexer($parser); + return $lexer; + } + + /** + * Accepts a token from the tag mode. If the + * starting element completes then the element + * is dispatched and the current attributes + * set back to empty. The element or attribute + * name is converted to lower case. + * @param string $token Incoming characters. + * @param integer $event Lexer event type. + * @return boolean False if parse error. + * @access public + */ + function acceptStartToken($token, $event) { + if ($event == LEXER_ENTER) { + $this->_tag = strtolower(substr($token, 1)); + return true; + } + if ($event == LEXER_EXIT) { + $success = $this->_listener->startElement( + $this->_tag, + $this->_attributes); + $this->_tag = ''; + $this->_attributes = array(); + return $success; + } + if ($token != '=') { + $this->_current_attribute = strtolower(SimpleHtmlSaxParser::decodeHtml($token)); + $this->_attributes[$this->_current_attribute] = ''; + } + return true; + } + + /** + * Accepts a token from the end tag mode. + * The element name is converted to lower case. + * @param string $token Incoming characters. + * @param integer $event Lexer event type. + * @return boolean False if parse error. + * @access public + */ + function acceptEndToken($token, $event) { + if (! preg_match('/<\/(.*)>/', $token, $matches)) { + return false; + } + return $this->_listener->endElement(strtolower($matches[1])); + } + + /** + * Part of the tag data. + * @param string $token Incoming characters. + * @param integer $event Lexer event type. + * @return boolean False if parse error. + * @access public + */ + function acceptAttributeToken($token, $event) { + if ($this->_current_attribute) { + if ($event == LEXER_UNMATCHED) { + $this->_attributes[$this->_current_attribute] .= + SimpleHtmlSaxParser::decodeHtml($token); + } + if ($event == LEXER_SPECIAL) { + $this->_attributes[$this->_current_attribute] .= + preg_replace('/^=\s*/' , '', SimpleHtmlSaxParser::decodeHtml($token)); + } + } + return true; + } + + /** + * A character entity. + * @param string $token Incoming characters. + * @param integer $event Lexer event type. + * @return boolean False if parse error. + * @access public + */ + function acceptEntityToken($token, $event) { + } + + /** + * Character data between tags regarded as + * important. + * @param string $token Incoming characters. + * @param integer $event Lexer event type. + * @return boolean False if parse error. + * @access public + */ + function acceptTextToken($token, $event) { + return $this->_listener->addContent($token); + } + + /** + * Incoming data to be ignored. + * @param string $token Incoming characters. + * @param integer $event Lexer event type. + * @return boolean False if parse error. + * @access public + */ + function ignore($token, $event) { + return true; + } + + /** + * Decodes any HTML entities. + * @param string $html Incoming HTML. + * @return string Outgoing plain text. + * @access public + * @static + */ + function decodeHtml($html) { + return html_entity_decode($html, ENT_QUOTES); + } + + /** + * Turns HTML into text browser visible text. Images + * are converted to their alt text and tags are supressed. + * Entities are converted to their visible representation. + * @param string $html HTML to convert. + * @return string Plain text. + * @access public + * @static + */ + function normalise($html) { + $text = preg_replace('||', '', $html); + $text = preg_replace('|]*>.*?|', '', $text); + $text = preg_replace('|]*alt\s*=\s*"([^"]*)"[^>]*>|', ' \1 ', $text); + $text = preg_replace('|]*alt\s*=\s*\'([^\']*)\'[^>]*>|', ' \1 ', $text); + $text = preg_replace('|]*alt\s*=\s*([a-zA-Z_]+)[^>]*>|', ' \1 ', $text); + $text = preg_replace('|<[^>]*>|', '', $text); + $text = SimpleHtmlSaxParser::decodeHtml($text); + $text = preg_replace('|\s+|', ' ', $text); + return trim(trim($text), "\xA0"); // TODO: The \xAO is a  . Add a test for this. + } +} + +/** + * SAX event handler. + * @package SimpleTest + * @subpackage WebTester + * @abstract + */ +class SimpleSaxListener { + + /** + * Sets the document to write to. + * @access public + */ + function SimpleSaxListener() { + } + + /** + * Start of element event. + * @param string $name Element name. + * @param hash $attributes Name value pairs. + * Attributes without content + * are marked as true. + * @return boolean False on parse error. + * @access public + */ + function startElement($name, $attributes) { + } + + /** + * End of element event. + * @param string $name Element name. + * @return boolean False on parse error. + * @access public + */ + function endElement($name) { + } + + /** + * Unparsed, but relevant data. + * @param string $text May include unparsed tags. + * @return boolean False on parse error. + * @access public + */ + function addContent($text) { + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php4.php b/plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php4.php new file mode 100644 index 0000000..6c93915 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php4.php @@ -0,0 +1,136 @@ +_interface = $interface; + } + + /** + * Checks that a class has been declared. + * @return boolean True if defined. + * @access public + */ + function classExists() { + return class_exists($this->_interface); + } + + /** + * Needed to kill the autoload feature in PHP5 + * for classes created dynamically. + * @return boolean True if defined. + * @access public + */ + function classExistsSansAutoload() { + return class_exists($this->_interface); + } + + /** + * Checks that a class or interface has been + * declared. + * @return boolean True if defined. + * @access public + */ + function classOrInterfaceExists() { + return class_exists($this->_interface); + } + + /** + * Needed to kill the autoload feature in PHP5 + * for classes created dynamically. + * @return boolean True if defined. + * @access public + */ + function classOrInterfaceExistsSansAutoload() { + return class_exists($this->_interface); + } + + /** + * Gets the list of methods on a class or + * interface. + * @returns array List of method names. + * @access public + */ + function getMethods() { + return get_class_methods($this->_interface); + } + + /** + * Gets the list of interfaces from a class. If the + * class name is actually an interface then just that + * interface is returned. + * @returns array List of interfaces. + * @access public + */ + function getInterfaces() { + return array(); + } + + /** + * Finds the parent class name. + * @returns string Parent class name. + * @access public + */ + function getParent() { + return strtolower(get_parent_class($this->_interface)); + } + + /** + * Determines if the class is abstract, which for PHP 4 + * will never be the case. + * @returns boolean True if abstract. + * @access public + */ + function isAbstract() { + return false; + } + + /** + * Determines if the the entity is an interface, which for PHP 4 + * will never be the case. + * @returns boolean True if interface. + * @access public + */ + function isInterface() { + return false; + } + + /** + * Scans for final methods, but as it's PHP 4 there + * aren't any. + * @returns boolean True if the class has a final method. + * @access public + */ + function hasFinal() { + return false; + } + + /** + * Gets the source code matching the declaration + * of a method. + * @param string $method Method name. + * @access public + */ + function getSignature($method) { + return "function &$method()"; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php5.php b/plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php5.php new file mode 100644 index 0000000..8383bcc --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/reflection_php5.php @@ -0,0 +1,380 @@ +_interface = $interface; + } + + /** + * Checks that a class has been declared. Versions + * before PHP5.0.2 need a check that it's not really + * an interface. + * @return boolean True if defined. + * @access public + */ + function classExists() { + if (! class_exists($this->_interface)) { + return false; + } + $reflection = new ReflectionClass($this->_interface); + return ! $reflection->isInterface(); + } + + /** + * Needed to kill the autoload feature in PHP5 + * for classes created dynamically. + * @return boolean True if defined. + * @access public + */ + function classExistsSansAutoload() { + return class_exists($this->_interface, false); + } + + /** + * Checks that a class or interface has been + * declared. + * @return boolean True if defined. + * @access public + */ + function classOrInterfaceExists() { + return $this->_classOrInterfaceExistsWithAutoload($this->_interface, true); + } + + /** + * Needed to kill the autoload feature in PHP5 + * for classes created dynamically. + * @return boolean True if defined. + * @access public + */ + function classOrInterfaceExistsSansAutoload() { + return $this->_classOrInterfaceExistsWithAutoload($this->_interface, false); + } + + /** + * Needed to select the autoload feature in PHP5 + * for classes created dynamically. + * @param string $interface Class or interface name. + * @param boolean $autoload True totriggerautoload. + * @return boolean True if interface defined. + * @access private + */ + function _classOrInterfaceExistsWithAutoload($interface, $autoload) { + if (function_exists('interface_exists')) { + if (interface_exists($this->_interface, $autoload)) { + return true; + } + } + return class_exists($this->_interface, $autoload); + } + + /** + * Gets the list of methods on a class or + * interface. + * @returns array List of method names. + * @access public + */ + function getMethods() { + return array_unique(get_class_methods($this->_interface)); + } + + /** + * Gets the list of interfaces from a class. If the + * class name is actually an interface then just that + * interface is returned. + * @returns array List of interfaces. + * @access public + */ + function getInterfaces() { + $reflection = new ReflectionClass($this->_interface); + if ($reflection->isInterface()) { + return array($this->_interface); + } + return $this->_onlyParents($reflection->getInterfaces()); + } + + /** + * Gets the list of methods for the implemented + * interfaces only. + * @returns array List of enforced method signatures. + * @access public + */ + function getInterfaceMethods() { + $methods = array(); + foreach ($this->getInterfaces() as $interface) { + $methods = array_merge($methods, get_class_methods($interface)); + } + return array_unique($methods); + } + + /** + * Checks to see if the method signature has to be tightly + * specified. + * @param string $method Method name. + * @returns boolean True if enforced. + * @access private + */ + function _isInterfaceMethod($method) { + return in_array($method, $this->getInterfaceMethods()); + } + + /** + * Finds the parent class name. + * @returns string Parent class name. + * @access public + */ + function getParent() { + $reflection = new ReflectionClass($this->_interface); + $parent = $reflection->getParentClass(); + if ($parent) { + return $parent->getName(); + } + return false; + } + + /** + * Trivially determines if the class is abstract. + * @returns boolean True if abstract. + * @access public + */ + function isAbstract() { + $reflection = new ReflectionClass($this->_interface); + return $reflection->isAbstract(); + } + + /** + * Trivially determines if the class is an interface. + * @returns boolean True if interface. + * @access public + */ + function isInterface() { + $reflection = new ReflectionClass($this->_interface); + return $reflection->isInterface(); + } + + /** + * Scans for final methods, as they screw up inherited + * mocks by not allowing you to override them. + * @returns boolean True if the class has a final method. + * @access public + */ + function hasFinal() { + $reflection = new ReflectionClass($this->_interface); + foreach ($reflection->getMethods() as $method) { + if ($method->isFinal()) { + return true; + } + } + return false; + } + + /** + * Whittles a list of interfaces down to only the + * necessary top level parents. + * @param array $interfaces Reflection API interfaces + * to reduce. + * @returns array List of parent interface names. + * @access private + */ + function _onlyParents($interfaces) { + $parents = array(); + $blacklist = array(); + foreach ($interfaces as $interface) { + foreach($interfaces as $possible_parent) { + if ($interface->getName() == $possible_parent->getName()) { + continue; + } + if ($interface->isSubClassOf($possible_parent)) { + $blacklist[$possible_parent->getName()] = true; + } + } + if (!isset($blacklist[$interface->getName()])) { + $parents[] = $interface->getName(); + } + } + return $parents; + } + + /** + * Checks whether a method is abstract or not. + * @param string $name Method name. + * @return bool true if method is abstract, else false + * @access private + */ + function _isAbstractMethod($name) { + $interface = new ReflectionClass($this->_interface); + if (! $interface->hasMethod($name)) { + return false; + } + return $interface->getMethod($name)->isAbstract(); + } + + /** + * Checks whether a method is the constructor. + * @param string $name Method name. + * @return bool true if method is the constructor + * @access private + */ + function _isConstructor($name) { + return ($name == '__construct') || ($name == $this->_interface); + } + + /** + * Checks whether a method is abstract in all parents or not. + * @param string $name Method name. + * @return bool true if method is abstract in parent, else false + * @access private + */ + function _isAbstractMethodInParents($name) { + $interface = new ReflectionClass($this->_interface); + $parent = $interface->getParentClass(); + while($parent) { + if (! $parent->hasMethod($name)) { + return false; + } + if ($parent->getMethod($name)->isAbstract()) { + return true; + } + $parent = $parent->getParentClass(); + } + return false; + } + + /** + * Checks whether a method is static or not. + * @param string $name Method name + * @return bool true if method is static, else false + * @access private + */ + function _isStaticMethod($name) { + $interface = new ReflectionClass($this->_interface); + if (! $interface->hasMethod($name)) { + return false; + } + return $interface->getMethod($name)->isStatic(); + } + + /** + * Writes the source code matching the declaration + * of a method. + * @param string $name Method name. + * @return string Method signature up to last + * bracket. + * @access public + */ + function getSignature($name) { + if ($name == '__set') { + return 'function __set($key, $value)'; + } + if ($name == '__call') { + return 'function __call($method, $arguments)'; + } + if (version_compare(phpversion(), '5.1.0', '>=')) { + if (in_array($name, array('__get', '__isset', $name == '__unset'))) { + return "function {$name}(\$key)"; + } + } + if ($name == '__toString') { + return "function $name()"; + } + if ($this->_isInterfaceMethod($name) || + $this->_isAbstractMethod($name) || + $this->_isAbstractMethodInParents($name) || + $this->_isStaticMethod($name)) { + return $this->_getFullSignature($name); + } + return "function $name()"; + } + + /** + * For a signature specified in an interface, full + * details must be replicated to be a valid implementation. + * @param string $name Method name. + * @return string Method signature up to last + * bracket. + * @access private + */ + function _getFullSignature($name) { + $interface = new ReflectionClass($this->_interface); + $method = $interface->getMethod($name); + $reference = $method->returnsReference() ? '&' : ''; + $static = $method->isStatic() ? 'static ' : ''; + return "{$static}function $reference$name(" . + implode(', ', $this->_getParameterSignatures($method)) . + ")"; + } + + /** + * Gets the source code for each parameter. + * @param ReflectionMethod $method Method object from + * reflection API + * @return array List of strings, each + * a snippet of code. + * @access private + */ + function _getParameterSignatures($method) { + $signatures = array(); + foreach ($method->getParameters() as $parameter) { + $signature = ''; + $type = $parameter->getClass(); + if (is_null($type) && version_compare(phpversion(), '5.1.0', '>=') && $parameter->isArray()) { + $signature .= 'array '; + } elseif (!is_null($type)) { + $signature .= $type->getName() . ' '; + } + if ($parameter->isPassedByReference()) { + $signature .= '&'; + } + $signature .= '$' . $this->_suppressSpurious($parameter->getName()); + if ($this->_isOptional($parameter)) { + $signature .= ' = null'; + } + $signatures[] = $signature; + } + return $signatures; + } + + /** + * The SPL library has problems with the + * Reflection library. In particular, you can + * get extra characters in parameter names :(. + * @param string $name Parameter name. + * @return string Cleaner name. + * @access private + */ + function _suppressSpurious($name) { + return str_replace(array('[', ']', ' '), '', $name); + } + + /** + * Test of a reflection parameter being optional + * that works with early versions of PHP5. + * @param reflectionParameter $parameter Is this optional. + * @return boolean True if optional. + * @access private + */ + function _isOptional($parameter) { + if (method_exists($parameter, 'isOptional')) { + return $parameter->isOptional(); + } + return false; + } +} +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/remote.php b/plugins/www/testgen4web_simpletest/lib/simpletest/remote.php new file mode 100644 index 0000000..8889ed7 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/remote.php @@ -0,0 +1,117 @@ +_url = $url; + $this->_dry_url = $dry_url ? $dry_url : $url; + $this->_size = false; + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_url; + } + + /** + * Runs the top level test for this class. Currently + * reads the data as a single chunk. I'll fix this + * once I have added iteration to the browser. + * @param SimpleReporter $reporter Target of test results. + * @returns boolean True if no failures. + * @access public + */ + function run(&$reporter) { + $browser = &$this->_createBrowser(); + $xml = $browser->get($this->_url); + if (! $xml) { + trigger_error('Cannot read remote test URL [' . $this->_url . ']'); + return false; + } + $parser = &$this->_createParser($reporter); + if (! $parser->parse($xml)) { + trigger_error('Cannot parse incoming XML from [' . $this->_url . ']'); + return false; + } + return true; + } + + /** + * Creates a new web browser object for fetching + * the XML report. + * @return SimpleBrowser New browser. + * @access protected + */ + function &_createBrowser() { + $browser = &new SimpleBrowser(); + return $browser; + } + + /** + * Creates the XML parser. + * @param SimpleReporter $reporter Target of test results. + * @return SimpleTestXmlListener XML reader. + * @access protected + */ + function &_createParser(&$reporter) { + $parser = &new SimpleTestXmlParser($reporter); + return $parser; + } + + /** + * Accessor for the number of subtests. + * @return integer Number of test cases. + * @access public + */ + function getSize() { + if ($this->_size === false) { + $browser = &$this->_createBrowser(); + $xml = $browser->get($this->_dry_url); + if (! $xml) { + trigger_error('Cannot read remote test URL [' . $this->_dry_url . ']'); + return false; + } + $reporter = &new SimpleReporter(); + $parser = &$this->_createParser($reporter); + if (! $parser->parse($xml)) { + trigger_error('Cannot parse incoming XML from [' . $this->_dry_url . ']'); + return false; + } + $this->_size = $reporter->getTestCaseCount(); + } + return $this->_size; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/reporter.php b/plugins/www/testgen4web_simpletest/lib/simpletest/reporter.php new file mode 100644 index 0000000..a13eff8 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/reporter.php @@ -0,0 +1,447 @@ +SimpleReporter(); + $this->_character_set = $character_set; + } + + /** + * Paints the top of the web page setting the + * title to the name of the starting test. + * @param string $test_name Name class of test. + * @access public + */ + function paintHeader($test_name) { + $this->sendNoCacheHeaders(); + print ""; + print "\n\n$test_name\n"; + print "\n"; + print "\n"; + print "\n\n"; + print "

$test_name

\n"; + flush(); + } + + /** + * Send the headers necessary to ensure the page is + * reloaded on every request. Otherwise you could be + * scratching your head over out of date test data. + * @access public + * @static + */ + function sendNoCacheHeaders() { + if (! headers_sent()) { + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + } + } + + /** + * Paints the CSS. Add additional styles here. + * @return string CSS code as text. + * @access protected + */ + function _getCss() { + return ".fail { background-color: inherit; color: red; }" . + ".pass { background-color: inherit; color: green; }" . + " pre { background-color: lightgray; color: inherit; }"; + } + + /** + * Paints the end of the test with a summary of + * the passes and failures. + * @param string $test_name Name class of test. + * @access public + */ + function paintFooter($test_name) { + $colour = ($this->getFailCount() + $this->getExceptionCount() > 0 ? "red" : "green"); + print "
"; + print $this->getTestCaseProgress() . "/" . $this->getTestCaseCount(); + print " test cases complete:\n"; + print "" . $this->getPassCount() . " passes, "; + print "" . $this->getFailCount() . " fails and "; + print "" . $this->getExceptionCount() . " exceptions."; + print "
\n"; + print "\n\n"; + } + + /** + * Paints the test failure with a breadcrumbs + * trail of the nesting test suites below the + * top level test. + * @param string $message Failure message displayed in + * the context of the other tests. + * @access public + */ + function paintFail($message) { + parent::paintFail($message); + print "Fail: "; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print implode(" -> ", $breadcrumb); + print " -> " . $this->_htmlEntities($message) . "
\n"; + } + + /** + * Paints a PHP error. + * @param string $message Message is ignored. + * @access public + */ + function paintError($message) { + parent::paintError($message); + print "Exception: "; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print implode(" -> ", $breadcrumb); + print " -> " . $this->_htmlEntities($message) . "
\n"; + } + + /** + * Paints a PHP exception. + * @param Exception $exception Exception to display. + * @access public + */ + function paintException($exception) { + parent::paintException($exception); + print "Exception: "; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print implode(" -> ", $breadcrumb); + $message = 'Unexpected exception of type [' . get_class($exception) . + '] with message ['. $exception->getMessage() . + '] in ['. $exception->getFile() . + ' line ' . $exception->getLine() . ']'; + print " -> " . $this->_htmlEntities($message) . "
\n"; + } + + /** + * Prints the message for skipping tests. + * @param string $message Text of skip condition. + * @access public + */ + function paintSkip($message) { + parent::paintSkip($message); + print "Skipped: "; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print implode(" -> ", $breadcrumb); + print " -> " . $this->_htmlEntities($message) . "
\n"; + } + + /** + * Paints formatted text such as dumped variables. + * @param string $message Text to show. + * @access public + */ + function paintFormattedMessage($message) { + print '
' . $this->_htmlEntities($message) . '
'; + } + + /** + * Character set adjusted entity conversion. + * @param string $message Plain text or Unicode message. + * @return string Browser readable message. + * @access protected + */ + function _htmlEntities($message) { + return htmlentities($message, ENT_COMPAT, $this->_character_set); + } +} + +/** + * Sample minimal test displayer. Generates only + * failure messages and a pass count. For command + * line use. I've tried to make it look like JUnit, + * but I wanted to output the errors as they arrived + * which meant dropping the dots. + * @package SimpleTest + * @subpackage UnitTester + */ +class TextReporter extends SimpleReporter { + + /** + * Does nothing yet. The first output will + * be sent on the first test start. + * @access public + */ + function TextReporter() { + $this->SimpleReporter(); + } + + /** + * Paints the title only. + * @param string $test_name Name class of test. + * @access public + */ + function paintHeader($test_name) { + if (! SimpleReporter::inCli()) { + header('Content-type: text/plain'); + } + print "$test_name\n"; + flush(); + } + + /** + * Paints the end of the test with a summary of + * the passes and failures. + * @param string $test_name Name class of test. + * @access public + */ + function paintFooter($test_name) { + if ($this->getFailCount() + $this->getExceptionCount() == 0) { + print "OK\n"; + } else { + print "FAILURES!!!\n"; + } + print "Test cases run: " . $this->getTestCaseProgress() . + "/" . $this->getTestCaseCount() . + ", Passes: " . $this->getPassCount() . + ", Failures: " . $this->getFailCount() . + ", Exceptions: " . $this->getExceptionCount() . "\n"; + } + + /** + * Paints the test failure as a stack trace. + * @param string $message Failure message displayed in + * the context of the other tests. + * @access public + */ + function paintFail($message) { + parent::paintFail($message); + print $this->getFailCount() . ") $message\n"; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); + print "\n"; + } + + /** + * Paints a PHP error or exception. + * @param string $message Message to be shown. + * @access public + * @abstract + */ + function paintError($message) { + parent::paintError($message); + print "Exception " . $this->getExceptionCount() . "!\n$message\n"; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); + print "\n"; + } + + /** + * Paints a PHP error or exception. + * @param Exception $exception Exception to describe. + * @access public + * @abstract + */ + function paintException($exception) { + parent::paintException($exception); + $message = 'Unexpected exception of type [' . get_class($exception) . + '] with message ['. $exception->getMessage() . + '] in ['. $exception->getFile() . + ' line ' . $exception->getLine() . ']'; + print "Exception " . $this->getExceptionCount() . "!\n$message\n"; + $breadcrumb = $this->getTestList(); + array_shift($breadcrumb); + print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); + print "\n"; + } + + /** + * Prints the message for skipping tests. + * @param string $message Text of skip condition. + * @access public + */ + function paintSkip($message) { + parent::paintSkip($message); + print "Skip: $message\n"; + } + + /** + * Paints formatted text such as dumped variables. + * @param string $message Text to show. + * @access public + */ + function paintFormattedMessage($message) { + print "$message\n"; + flush(); + } +} + +/** + * Runs just a single test group, a single case or + * even a single test within that case. + * @package SimpleTest + * @subpackage UnitTester + */ +class SelectiveReporter extends SimpleReporterDecorator { + var $_just_this_case = false; + var $_just_this_test = false; + var $_on; + + /** + * Selects the test case or group to be run, + * and optionally a specific test. + * @param SimpleScorer $reporter Reporter to receive events. + * @param string $just_this_case Only this case or group will run. + * @param string $just_this_test Only this test method will run. + */ + function SelectiveReporter(&$reporter, $just_this_case = false, $just_this_test = false) { + if (isset($just_this_case) && $just_this_case) { + $this->_just_this_case = strtolower($just_this_case); + $this->_off(); + } else { + $this->_on(); + } + if (isset($just_this_test) && $just_this_test) { + $this->_just_this_test = strtolower($just_this_test); + } + $this->SimpleReporterDecorator($reporter); + } + + /** + * Compares criteria to actual the case/group name. + * @param string $test_case The incoming test. + * @return boolean True if matched. + * @access protected + */ + function _matchesTestCase($test_case) { + return $this->_just_this_case == strtolower($test_case); + } + + /** + * Compares criteria to actual the test name. If no + * name was specified at the beginning, then all tests + * can run. + * @param string $method The incoming test method. + * @return boolean True if matched. + * @access protected + */ + function _shouldRunTest($test_case, $method) { + if ($this->_isOn() || $this->_matchesTestCase($test_case)) { + if ($this->_just_this_test) { + return $this->_just_this_test == strtolower($method); + } else { + return true; + } + } + return false; + } + + /** + * Switch on testing for the group or subgroup. + * @access private + */ + function _on() { + $this->_on = true; + } + + /** + * Switch off testing for the group or subgroup. + * @access private + */ + function _off() { + $this->_on = false; + } + + /** + * Is this group actually being tested? + * @return boolean True if the current test group is active. + * @access private + */ + function _isOn() { + return $this->_on; + } + + /** + * Veto everything that doesn't match the method wanted. + * @param string $test_case Name of test case. + * @param string $method Name of test method. + * @return boolean True if test should be run. + * @access public + */ + function shouldInvoke($test_case, $method) { + if ($this->_shouldRunTest($test_case, $method)) { + return $this->_reporter->shouldInvoke($test_case, $method); + } + return false; + } + + /** + * Paints the start of a group test. + * @param string $test_case Name of test or other label. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($test_case, $size) { + if ($this->_just_this_case && $this->_matchesTestCase($test_case)) { + $this->_on(); + } + $this->_reporter->paintGroupStart($test_case, $size); + } + + /** + * Paints the end of a group test. + * @param string $test_case Name of test or other label. + * @access public + */ + function paintGroupEnd($test_case) { + $this->_reporter->paintGroupEnd($test_case); + if ($this->_just_this_case && $this->_matchesTestCase($test_case)) { + $this->_off(); + } + } +} + +/** + * Suppresses skip messages. + * @package SimpleTest + * @subpackage UnitTester + */ +class NoSkipsReporter extends SimpleReporterDecorator { + + /** + * Does nothing. + * @param string $message Text of skip condition. + * @access public + */ + function paintSkip($message) { } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/scorer.php b/plugins/www/testgen4web_simpletest/lib/simpletest/scorer.php new file mode 100644 index 0000000..cc1331b --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/scorer.php @@ -0,0 +1,863 @@ +_passes = 0; + $this->_fails = 0; + $this->_exceptions = 0; + $this->_is_dry_run = false; + } + + /** + * Signals that the next evaluation will be a dry + * run. That is, the structure events will be + * recorded, but no tests will be run. + * @param boolean $is_dry Dry run if true. + * @access public + */ + function makeDry($is_dry = true) { + $this->_is_dry_run = $is_dry; + } + + /** + * The reporter has a veto on what should be run. + * @param string $test_case_name name of test case. + * @param string $method Name of test method. + * @access public + */ + function shouldInvoke($test_case_name, $method) { + return ! $this->_is_dry_run; + } + + /** + * Can wrap the invoker in preperation for running + * a test. + * @param SimpleInvoker $invoker Individual test runner. + * @return SimpleInvoker Wrapped test runner. + * @access public + */ + function &createInvoker(&$invoker) { + return $invoker; + } + + /** + * Accessor for current status. Will be false + * if there have been any failures or exceptions. + * Used for command line tools. + * @return boolean True if no failures. + * @access public + */ + function getStatus() { + if ($this->_exceptions + $this->_fails > 0) { + return false; + } + return true; + } + + /** + * Paints the start of a group test. + * @param string $test_name Name of test or other label. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($test_name, $size) { + } + + /** + * Paints the end of a group test. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintGroupEnd($test_name) { + } + + /** + * Paints the start of a test case. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseStart($test_name) { + } + + /** + * Paints the end of a test case. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseEnd($test_name) { + } + + /** + * Paints the start of a test method. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintMethodStart($test_name) { + } + + /** + * Paints the end of a test method. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintMethodEnd($test_name) { + } + + /** + * Increments the pass count. + * @param string $message Message is ignored. + * @access public + */ + function paintPass($message) { + $this->_passes++; + } + + /** + * Increments the fail count. + * @param string $message Message is ignored. + * @access public + */ + function paintFail($message) { + $this->_fails++; + } + + /** + * Deals with PHP 4 throwing an error. + * @param string $message Text of error formatted by + * the test case. + * @access public + */ + function paintError($message) { + $this->_exceptions++; + } + + /** + * Deals with PHP 5 throwing an exception. + * @param Exception $exception The actual exception thrown. + * @access public + */ + function paintException($exception) { + $this->_exceptions++; + } + + /** + * Prints the message for skipping tests. + * @param string $message Text of skip condition. + * @access public + */ + function paintSkip($message) { + } + + /** + * Accessor for the number of passes so far. + * @return integer Number of passes. + * @access public + */ + function getPassCount() { + return $this->_passes; + } + + /** + * Accessor for the number of fails so far. + * @return integer Number of fails. + * @access public + */ + function getFailCount() { + return $this->_fails; + } + + /** + * Accessor for the number of untrapped errors + * so far. + * @return integer Number of exceptions. + * @access public + */ + function getExceptionCount() { + return $this->_exceptions; + } + + /** + * Paints a simple supplementary message. + * @param string $message Text to display. + * @access public + */ + function paintMessage($message) { + } + + /** + * Paints a formatted ASCII message such as a + * variable dump. + * @param string $message Text to display. + * @access public + */ + function paintFormattedMessage($message) { + } + + /** + * By default just ignores user generated events. + * @param string $type Event type as text. + * @param mixed $payload Message or object. + * @access public + */ + function paintSignal($type, $payload) { + } +} + +/** + * Recipient of generated test messages that can display + * page footers and headers. Also keeps track of the + * test nesting. This is the main base class on which + * to build the finished test (page based) displays. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleReporter extends SimpleScorer { + var $_test_stack; + var $_size; + var $_progress; + + /** + * Starts the display with no results in. + * @access public + */ + function SimpleReporter() { + $this->SimpleScorer(); + $this->_test_stack = array(); + $this->_size = null; + $this->_progress = 0; + } + + /** + * Gets the formatter for variables and other small + * generic data items. + * @return SimpleDumper Formatter. + * @access public + */ + function getDumper() { + return new SimpleDumper(); + } + + /** + * Paints the start of a group test. Will also paint + * the page header and footer if this is the + * first test. Will stash the size if the first + * start. + * @param string $test_name Name of test that is starting. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($test_name, $size) { + if (! isset($this->_size)) { + $this->_size = $size; + } + if (count($this->_test_stack) == 0) { + $this->paintHeader($test_name); + } + $this->_test_stack[] = $test_name; + } + + /** + * Paints the end of a group test. Will paint the page + * footer if the stack of tests has unwound. + * @param string $test_name Name of test that is ending. + * @param integer $progress Number of test cases ending. + * @access public + */ + function paintGroupEnd($test_name) { + array_pop($this->_test_stack); + if (count($this->_test_stack) == 0) { + $this->paintFooter($test_name); + } + } + + /** + * Paints the start of a test case. Will also paint + * the page header and footer if this is the + * first test. Will stash the size if the first + * start. + * @param string $test_name Name of test that is starting. + * @access public + */ + function paintCaseStart($test_name) { + if (! isset($this->_size)) { + $this->_size = 1; + } + if (count($this->_test_stack) == 0) { + $this->paintHeader($test_name); + } + $this->_test_stack[] = $test_name; + } + + /** + * Paints the end of a test case. Will paint the page + * footer if the stack of tests has unwound. + * @param string $test_name Name of test that is ending. + * @access public + */ + function paintCaseEnd($test_name) { + $this->_progress++; + array_pop($this->_test_stack); + if (count($this->_test_stack) == 0) { + $this->paintFooter($test_name); + } + } + + /** + * Paints the start of a test method. + * @param string $test_name Name of test that is starting. + * @access public + */ + function paintMethodStart($test_name) { + $this->_test_stack[] = $test_name; + } + + /** + * Paints the end of a test method. Will paint the page + * footer if the stack of tests has unwound. + * @param string $test_name Name of test that is ending. + * @access public + */ + function paintMethodEnd($test_name) { + array_pop($this->_test_stack); + } + + /** + * Paints the test document header. + * @param string $test_name First test top level + * to start. + * @access public + * @abstract + */ + function paintHeader($test_name) { + } + + /** + * Paints the test document footer. + * @param string $test_name The top level test. + * @access public + * @abstract + */ + function paintFooter($test_name) { + } + + /** + * Accessor for internal test stack. For + * subclasses that need to see the whole test + * history for display purposes. + * @return array List of methods in nesting order. + * @access public + */ + function getTestList() { + return $this->_test_stack; + } + + /** + * Accessor for total test size in number + * of test cases. Null until the first + * test is started. + * @return integer Total number of cases at start. + * @access public + */ + function getTestCaseCount() { + return $this->_size; + } + + /** + * Accessor for the number of test cases + * completed so far. + * @return integer Number of ended cases. + * @access public + */ + function getTestCaseProgress() { + return $this->_progress; + } + + /** + * Static check for running in the comand line. + * @return boolean True if CLI. + * @access public + * @static + */ + function inCli() { + return php_sapi_name() == 'cli'; + } +} + +/** + * For modifying the behaviour of the visual reporters. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleReporterDecorator { + var $_reporter; + + /** + * Mediates between the reporter and the test case. + * @param SimpleScorer $reporter Reporter to receive events. + */ + function SimpleReporterDecorator(&$reporter) { + $this->_reporter = &$reporter; + } + + /** + * Signals that the next evaluation will be a dry + * run. That is, the structure events will be + * recorded, but no tests will be run. + * @param boolean $is_dry Dry run if true. + * @access public + */ + function makeDry($is_dry = true) { + $this->_reporter->makeDry($is_dry); + } + + /** + * Accessor for current status. Will be false + * if there have been any failures or exceptions. + * Used for command line tools. + * @return boolean True if no failures. + * @access public + */ + function getStatus() { + return $this->_reporter->getStatus(); + } + + /** + * The reporter has a veto on what should be run. + * @param string $test_case_name name of test case. + * @param string $method Name of test method. + * @return boolean True if test should be run. + * @access public + */ + function shouldInvoke($test_case_name, $method) { + return $this->_reporter->shouldInvoke($test_case_name, $method); + } + + /** + * Can wrap the invoker in preperation for running + * a test. + * @param SimpleInvoker $invoker Individual test runner. + * @return SimpleInvoker Wrapped test runner. + * @access public + */ + function &createInvoker(&$invoker) { + return $this->_reporter->createInvoker($invoker); + } + + /** + * Gets the formatter for variables and other small + * generic data items. + * @return SimpleDumper Formatter. + * @access public + */ + function getDumper() { + return $this->_reporter->getDumper(); + } + + /** + * Paints the start of a group test. + * @param string $test_name Name of test or other label. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($test_name, $size) { + $this->_reporter->paintGroupStart($test_name, $size); + } + + /** + * Paints the end of a group test. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintGroupEnd($test_name) { + $this->_reporter->paintGroupEnd($test_name); + } + + /** + * Paints the start of a test case. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseStart($test_name) { + $this->_reporter->paintCaseStart($test_name); + } + + /** + * Paints the end of a test case. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseEnd($test_name) { + $this->_reporter->paintCaseEnd($test_name); + } + + /** + * Paints the start of a test method. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintMethodStart($test_name) { + $this->_reporter->paintMethodStart($test_name); + } + + /** + * Paints the end of a test method. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintMethodEnd($test_name) { + $this->_reporter->paintMethodEnd($test_name); + } + + /** + * Chains to the wrapped reporter. + * @param string $message Message is ignored. + * @access public + */ + function paintPass($message) { + $this->_reporter->paintPass($message); + } + + /** + * Chains to the wrapped reporter. + * @param string $message Message is ignored. + * @access public + */ + function paintFail($message) { + $this->_reporter->paintFail($message); + } + + /** + * Chains to the wrapped reporter. + * @param string $message Text of error formatted by + * the test case. + * @access public + */ + function paintError($message) { + $this->_reporter->paintError($message); + } + + /** + * Chains to the wrapped reporter. + * @param Exception $exception Exception to show. + * @access public + */ + function paintException($exception) { + $this->_reporter->paintException($exception); + } + + /** + * Prints the message for skipping tests. + * @param string $message Text of skip condition. + * @access public + */ + function paintSkip($message) { + $this->_reporter->paintSkip($message); + } + + /** + * Chains to the wrapped reporter. + * @param string $message Text to display. + * @access public + */ + function paintMessage($message) { + $this->_reporter->paintMessage($message); + } + + /** + * Chains to the wrapped reporter. + * @param string $message Text to display. + * @access public + */ + function paintFormattedMessage($message) { + $this->_reporter->paintFormattedMessage($message); + } + + /** + * Chains to the wrapped reporter. + * @param string $type Event type as text. + * @param mixed $payload Message or object. + * @return boolean Should return false if this + * type of signal should fail the + * test suite. + * @access public + */ + function paintSignal($type, &$payload) { + $this->_reporter->paintSignal($type, $payload); + } +} + +/** + * For sending messages to multiple reporters at + * the same time. + * @package SimpleTest + * @subpackage UnitTester + */ +class MultipleReporter { + var $_reporters = array(); + + /** + * Adds a reporter to the subscriber list. + * @param SimpleScorer $reporter Reporter to receive events. + * @access public + */ + function attachReporter(&$reporter) { + $this->_reporters[] = &$reporter; + } + + /** + * Signals that the next evaluation will be a dry + * run. That is, the structure events will be + * recorded, but no tests will be run. + * @param boolean $is_dry Dry run if true. + * @access public + */ + function makeDry($is_dry = true) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->makeDry($is_dry); + } + } + + /** + * Accessor for current status. Will be false + * if there have been any failures or exceptions. + * If any reporter reports a failure, the whole + * suite fails. + * @return boolean True if no failures. + * @access public + */ + function getStatus() { + for ($i = 0; $i < count($this->_reporters); $i++) { + if (! $this->_reporters[$i]->getStatus()) { + return false; + } + } + return true; + } + + /** + * The reporter has a veto on what should be run. + * It requires all reporters to want to run the method. + * @param string $test_case_name name of test case. + * @param string $method Name of test method. + * @access public + */ + function shouldInvoke($test_case_name, $method) { + for ($i = 0; $i < count($this->_reporters); $i++) { + if (! $this->_reporters[$i]->shouldInvoke($test_case_name, $method)) { + return false; + } + } + return true; + } + + /** + * Every reporter gets a chance to wrap the invoker. + * @param SimpleInvoker $invoker Individual test runner. + * @return SimpleInvoker Wrapped test runner. + * @access public + */ + function &createInvoker(&$invoker) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $invoker = &$this->_reporters[$i]->createInvoker($invoker); + } + return $invoker; + } + + /** + * Gets the formatter for variables and other small + * generic data items. + * @return SimpleDumper Formatter. + * @access public + */ + function getDumper() { + return new SimpleDumper(); + } + + /** + * Paints the start of a group test. + * @param string $test_name Name of test or other label. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($test_name, $size) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintGroupStart($test_name, $size); + } + } + + /** + * Paints the end of a group test. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintGroupEnd($test_name) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintGroupEnd($test_name); + } + } + + /** + * Paints the start of a test case. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseStart($test_name) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintCaseStart($test_name); + } + } + + /** + * Paints the end of a test case. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintCaseEnd($test_name) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintCaseEnd($test_name); + } + } + + /** + * Paints the start of a test method. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintMethodStart($test_name) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintMethodStart($test_name); + } + } + + /** + * Paints the end of a test method. + * @param string $test_name Name of test or other label. + * @access public + */ + function paintMethodEnd($test_name) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintMethodEnd($test_name); + } + } + + /** + * Chains to the wrapped reporter. + * @param string $message Message is ignored. + * @access public + */ + function paintPass($message) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintPass($message); + } + } + + /** + * Chains to the wrapped reporter. + * @param string $message Message is ignored. + * @access public + */ + function paintFail($message) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintFail($message); + } + } + + /** + * Chains to the wrapped reporter. + * @param string $message Text of error formatted by + * the test case. + * @access public + */ + function paintError($message) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintError($message); + } + } + + /** + * Chains to the wrapped reporter. + * @param Exception $exception Exception to display. + * @access public + */ + function paintException($exception) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintException($exception); + } + } + + /** + * Prints the message for skipping tests. + * @param string $message Text of skip condition. + * @access public + */ + function paintSkip($message) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintSkip($message); + } + } + + /** + * Chains to the wrapped reporter. + * @param string $message Text to display. + * @access public + */ + function paintMessage($message) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintMessage($message); + } + } + + /** + * Chains to the wrapped reporter. + * @param string $message Text to display. + * @access public + */ + function paintFormattedMessage($message) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintFormattedMessage($message); + } + } + + /** + * Chains to the wrapped reporter. + * @param string $type Event type as text. + * @param mixed $payload Message or object. + * @return boolean Should return false if this + * type of signal should fail the + * test suite. + * @access public + */ + function paintSignal($type, &$payload) { + for ($i = 0; $i < count($this->_reporters); $i++) { + $this->_reporters[$i]->paintSignal($type, $payload); + } + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/selector.php b/plugins/www/testgen4web_simpletest/lib/simpletest/selector.php new file mode 100644 index 0000000..de044b8 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/selector.php @@ -0,0 +1,137 @@ +_name = $name; + } + + function getName() { + return $this->_name; + } + + /** + * Compares with name attribute of widget. + * @param SimpleWidget $widget Control to compare. + * @access public + */ + function isMatch($widget) { + return ($widget->getName() == $this->_name); + } +} + +/** + * Used to extract form elements for testing against. + * Searches by visible label or alt text. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleByLabel { + var $_label; + + /** + * Stashes the name for later comparison. + * @param string $label Visible text to match. + */ + function SimpleByLabel($label) { + $this->_label = $label; + } + + /** + * Comparison. Compares visible text of widget or + * related label. + * @param SimpleWidget $widget Control to compare. + * @access public + */ + function isMatch($widget) { + if (! method_exists($widget, 'isLabel')) { + return false; + } + return $widget->isLabel($this->_label); + } +} + +/** + * Used to extract form elements for testing against. + * Searches dy id attribute. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleById { + var $_id; + + /** + * Stashes the name for later comparison. + * @param string $id ID atribute to match. + */ + function SimpleById($id) { + $this->_id = $id; + } + + /** + * Comparison. Compares id attribute of widget. + * @param SimpleWidget $widget Control to compare. + * @access public + */ + function isMatch($widget) { + return $widget->isId($this->_id); + } +} + +/** + * Used to extract form elements for testing against. + * Searches by visible label, name or alt text. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleByLabelOrName { + var $_label; + + /** + * Stashes the name/label for later comparison. + * @param string $label Visible text to match. + */ + function SimpleByLabelOrName($label) { + $this->_label = $label; + } + + /** + * Comparison. Compares visible text of widget or + * related label or name. + * @param SimpleWidget $widget Control to compare. + * @access public + */ + function isMatch($widget) { + if (method_exists($widget, 'isLabel')) { + if ($widget->isLabel($this->_label)) { + return true; + } + } + return ($widget->getName() == $this->_label); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/shell_tester.php b/plugins/www/testgen4web_simpletest/lib/simpletest/shell_tester.php new file mode 100644 index 0000000..7b98869 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/shell_tester.php @@ -0,0 +1,333 @@ +_output = false; + } + + /** + * Actually runs the command. Does not trap the + * error stream output as this need PHP 4.3+. + * @param string $command The actual command line + * to run. + * @return integer Exit code. + * @access public + */ + function execute($command) { + $this->_output = false; + exec($command, $this->_output, $ret); + return $ret; + } + + /** + * Accessor for the last output. + * @return string Output as text. + * @access public + */ + function getOutput() { + return implode("\n", $this->_output); + } + + /** + * Accessor for the last output. + * @return array Output as array of lines. + * @access public + */ + function getOutputAsList() { + return $this->_output; + } +} + +/** + * Test case for testing of command line scripts and + * utilities. Usually scripts that are external to the + * PHP code, but support it in some way. + * @package SimpleTest + * @subpackage UnitTester + */ +class ShellTestCase extends SimpleTestCase { + var $_current_shell; + var $_last_status; + var $_last_command; + + /** + * Creates an empty test case. Should be subclassed + * with test methods for a functional test case. + * @param string $label Name of test case. Will use + * the class name if none specified. + * @access public + */ + function ShellTestCase($label = false) { + $this->SimpleTestCase($label); + $this->_current_shell = &$this->_createShell(); + $this->_last_status = false; + $this->_last_command = ''; + } + + /** + * Executes a command and buffers the results. + * @param string $command Command to run. + * @return boolean True if zero exit code. + * @access public + */ + function execute($command) { + $shell = &$this->_getShell(); + $this->_last_status = $shell->execute($command); + $this->_last_command = $command; + return ($this->_last_status === 0); + } + + /** + * Dumps the output of the last command. + * @access public + */ + function dumpOutput() { + $this->dump($this->getOutput()); + } + + /** + * Accessor for the last output. + * @return string Output as text. + * @access public + */ + function getOutput() { + $shell = &$this->_getShell(); + return $shell->getOutput(); + } + + /** + * Accessor for the last output. + * @return array Output as array of lines. + * @access public + */ + function getOutputAsList() { + $shell = &$this->_getShell(); + return $shell->getOutputAsList(); + } + + /** + * Called from within the test methods to register + * passes and failures. + * @param boolean $result Pass on true. + * @param string $message Message to display describing + * the test state. + * @return boolean True on pass + * @access public + */ + function assertTrue($result, $message = false) { + return $this->assert(new TrueExpectation(), $result, $message); + } + + /** + * Will be true on false and vice versa. False + * is the PHP definition of false, so that null, + * empty strings, zero and an empty array all count + * as false. + * @param boolean $result Pass on false. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertFalse($result, $message = '%s') { + return $this->assert(new FalseExpectation(), $result, $message); + } + + /** + * Will trigger a pass if the two parameters have + * the same value only. Otherwise a fail. This + * is for testing hand extracted text, etc. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertEqual($first, $second, $message = "%s") { + return $this->assert( + new EqualExpectation($first), + $second, + $message); + } + + /** + * Will trigger a pass if the two parameters have + * a different value. Otherwise a fail. This + * is for testing hand extracted text, etc. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertNotEqual($first, $second, $message = "%s") { + return $this->assert( + new NotEqualExpectation($first), + $second, + $message); + } + + /** + * Tests the last status code from the shell. + * @param integer $status Expected status of last + * command. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertExitCode($status, $message = "%s") { + $message = sprintf($message, "Expected status code of [$status] from [" . + $this->_last_command . "], but got [" . + $this->_last_status . "]"); + return $this->assertTrue($status === $this->_last_status, $message); + } + + /** + * Attempt to exactly match the combined STDERR and + * STDOUT output. + * @param string $expected Expected output. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertOutput($expected, $message = "%s") { + $shell = &$this->_getShell(); + return $this->assert( + new EqualExpectation($expected), + $shell->getOutput(), + $message); + } + + /** + * Scans the output for a Perl regex. If found + * anywhere it passes, else it fails. + * @param string $pattern Regex to search for. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertOutputPattern($pattern, $message = "%s") { + $shell = &$this->_getShell(); + return $this->assert( + new PatternExpectation($pattern), + $shell->getOutput(), + $message); + } + + /** + * If a Perl regex is found anywhere in the current + * output then a failure is generated, else a pass. + * @param string $pattern Regex to search for. + * @param $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertNoOutputPattern($pattern, $message = "%s") { + $shell = &$this->_getShell(); + return $this->assert( + new NoPatternExpectation($pattern), + $shell->getOutput(), + $message); + } + + /** + * File existence check. + * @param string $path Full filename and path. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertFileExists($path, $message = "%s") { + $message = sprintf($message, "File [$path] should exist"); + return $this->assertTrue(file_exists($path), $message); + } + + /** + * File non-existence check. + * @param string $path Full filename and path. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertFileNotExists($path, $message = "%s") { + $message = sprintf($message, "File [$path] should not exist"); + return $this->assertFalse(file_exists($path), $message); + } + + /** + * Scans a file for a Perl regex. If found + * anywhere it passes, else it fails. + * @param string $pattern Regex to search for. + * @param string $path Full filename and path. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertFilePattern($pattern, $path, $message = "%s") { + $shell = &$this->_getShell(); + return $this->assert( + new PatternExpectation($pattern), + implode('', file($path)), + $message); + } + + /** + * If a Perl regex is found anywhere in the named + * file then a failure is generated, else a pass. + * @param string $pattern Regex to search for. + * @param string $path Full filename and path. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertNoFilePattern($pattern, $path, $message = "%s") { + $shell = &$this->_getShell(); + return $this->assert( + new NoPatternExpectation($pattern), + implode('', file($path)), + $message); + } + + /** + * Accessor for current shell. Used for testing the + * the tester itself. + * @return Shell Current shell. + * @access protected + */ + function &_getShell() { + return $this->_current_shell; + } + + /** + * Factory for the shell to run the command on. + * @return Shell New shell object. + * @access protected + */ + function &_createShell() { + $shell = &new SimpleShell(); + return $shell; + } +} +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/simpletest.php b/plugins/www/testgen4web_simpletest/lib/simpletest/simpletest.php new file mode 100644 index 0000000..bab2c1a --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/simpletest.php @@ -0,0 +1,478 @@ += 0) { + require_once(dirname(__FILE__) . '/reflection_php5.php'); +} else { + require_once(dirname(__FILE__) . '/reflection_php4.php'); +} +require_once(dirname(__FILE__) . '/default_reporter.php'); +require_once(dirname(__FILE__) . '/compatibility.php'); +/**#@-*/ + +/** + * Registry and test context. Includes a few + * global options that I'm slowly getting rid of. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleTest { + + /** + * Reads the SimpleTest version from the release file. + * @return string Version string. + * @static + * @access public + */ + function getVersion() { + $content = file(dirname(__FILE__) . '/VERSION'); + return trim($content[0]); + } + + /** + * Sets the name of a test case to ignore, usually + * because the class is an abstract case that should + * not be run. Once PHP4 is dropped this will disappear + * as a public method and "abstract" will rule. + * @param string $class Add a class to ignore. + * @static + * @access public + */ + function ignore($class) { + $registry = &SimpleTest::_getRegistry(); + $registry['IgnoreList'][strtolower($class)] = true; + } + + /** + * Scans the now complete ignore list, and adds + * all parent classes to the list. If a class + * is not a runnable test case, then it's parents + * wouldn't be either. This is syntactic sugar + * to cut down on ommissions of ignore()'s or + * missing abstract declarations. This cannot + * be done whilst loading classes wiithout forcing + * a particular order on the class declarations and + * the ignore() calls. It's just nice to have the ignore() + * calls at the top of the file before the actual declarations. + * @param array $classes Class names of interest. + * @static + * @access public + */ + function ignoreParentsIfIgnored($classes) { + $registry = &SimpleTest::_getRegistry(); + foreach ($classes as $class) { + if (SimpleTest::isIgnored($class)) { + $reflection = new SimpleReflection($class); + if ($parent = $reflection->getParent()) { + SimpleTest::ignore($parent); + } + } + } + } + + /** + * Puts the object to the global pool of 'preferred' objects + * which can be retrieved with SimpleTest :: preferred() method. + * Instances of the same class are overwritten. + * @param object $object Preferred object + * @static + * @access public + * @see preferred() + */ + function prefer(&$object) { + $registry = &SimpleTest::_getRegistry(); + $registry['Preferred'][] = &$object; + } + + /** + * Retrieves 'preferred' objects from global pool. Class filter + * can be applied in order to retrieve the object of the specific + * class + * @param array|string $classes Allowed classes or interfaces. + * @static + * @access public + * @return array|object|null + * @see prefer() + */ + function &preferred($classes) { + if (! is_array($classes)) { + $classes = array($classes); + } + $registry = &SimpleTest::_getRegistry(); + for ($i = count($registry['Preferred']) - 1; $i >= 0; $i--) { + foreach ($classes as $class) { + if (SimpleTestCompatibility::isA($registry['Preferred'][$i], $class)) { + return $registry['Preferred'][$i]; + } + } + } + return null; + } + + /** + * Test to see if a test case is in the ignore + * list. Quite obviously the ignore list should + * be a separate object and will be one day. + * This method is internal to SimpleTest. Don't + * use it. + * @param string $class Class name to test. + * @return boolean True if should not be run. + * @access public + * @static + */ + function isIgnored($class) { + $registry = &SimpleTest::_getRegistry(); + return isset($registry['IgnoreList'][strtolower($class)]); + } + + /** + * @deprecated + */ + function setMockBaseClass($mock_base) { + $registry = &SimpleTest::_getRegistry(); + $registry['MockBaseClass'] = $mock_base; + } + + /** + * @deprecated + */ + function getMockBaseClass() { + $registry = &SimpleTest::_getRegistry(); + return $registry['MockBaseClass']; + } + + /** + * Sets proxy to use on all requests for when + * testing from behind a firewall. Set host + * to false to disable. This will take effect + * if there are no other proxy settings. + * @param string $proxy Proxy host as URL. + * @param string $username Proxy username for authentication. + * @param string $password Proxy password for authentication. + * @access public + */ + function useProxy($proxy, $username = false, $password = false) { + $registry = &SimpleTest::_getRegistry(); + $registry['DefaultProxy'] = $proxy; + $registry['DefaultProxyUsername'] = $username; + $registry['DefaultProxyPassword'] = $password; + } + + /** + * Accessor for default proxy host. + * @return string Proxy URL. + * @access public + */ + function getDefaultProxy() { + $registry = &SimpleTest::_getRegistry(); + return $registry['DefaultProxy']; + } + + /** + * Accessor for default proxy username. + * @return string Proxy username for authentication. + * @access public + */ + function getDefaultProxyUsername() { + $registry = &SimpleTest::_getRegistry(); + return $registry['DefaultProxyUsername']; + } + + /** + * Accessor for default proxy password. + * @return string Proxy password for authentication. + * @access public + */ + function getDefaultProxyPassword() { + $registry = &SimpleTest::_getRegistry(); + return $registry['DefaultProxyPassword']; + } + + /** + * Accessor for global registry of options. + * @return hash All stored values. + * @access private + * @static + */ + function &_getRegistry() { + static $registry = false; + if (! $registry) { + $registry = SimpleTest::_getDefaults(); + } + return $registry; + } + + /** + * Accessor for the context of the current + * test run. + * @return SimpleTestContext Current test run. + * @access public + * @static + */ + function &getContext() { + static $context = false; + if (! $context) { + $context = new SimpleTestContext(); + } + return $context; + } + + /** + * Constant default values. + * @return hash All registry defaults. + * @access private + * @static + */ + function _getDefaults() { + return array( + 'StubBaseClass' => 'SimpleStub', + 'MockBaseClass' => 'SimpleMock', + 'IgnoreList' => array(), + 'DefaultProxy' => false, + 'DefaultProxyUsername' => false, + 'DefaultProxyPassword' => false, + 'Preferred' => array(new HtmlReporter(), new TextReporter(), new XmlReporter())); + } +} + +/** + * Container for all components for a specific + * test run. Makes things like error queues + * available to PHP event handlers, and also + * gets around some nasty reference issues in + * the mocks. + * @package SimpleTest + */ +class SimpleTestContext { + var $_test; + var $_reporter; + var $_resources; + + /** + * Clears down the current context. + * @access public + */ + function clear() { + $this->_resources = array(); + } + + /** + * Sets the current test case instance. This + * global instance can be used by the mock objects + * to send message to the test cases. + * @param SimpleTestCase $test Test case to register. + * @access public + */ + function setTest(&$test) { + $this->clear(); + $this->_test = &$test; + } + + /** + * Accessor for currently running test case. + * @return SimpleTestCase Current test. + * @access public + */ + function &getTest() { + return $this->_test; + } + + /** + * Sets the current reporter. This + * global instance can be used by the mock objects + * to send messages. + * @param SimpleReporter $reporter Reporter to register. + * @access public + */ + function setReporter(&$reporter) { + $this->clear(); + $this->_reporter = &$reporter; + } + + /** + * Accessor for current reporter. + * @return SimpleReporter Current reporter. + * @access public + */ + function &getReporter() { + return $this->_reporter; + } + + /** + * Accessor for the Singleton resource. + * @return object Global resource. + * @access public + * @static + */ + function &get($resource) { + if (! isset($this->_resources[$resource])) { + $this->_resources[$resource] = &new $resource(); + } + return $this->_resources[$resource]; + } +} + +/** + * Interrogates the stack trace to recover the + * failure point. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleStackTrace { + var $_prefixes; + + /** + * Stashes the list of target prefixes. + * @param array $prefixes List of method prefixes + * to search for. + */ + function SimpleStackTrace($prefixes) { + $this->_prefixes = $prefixes; + } + + /** + * Extracts the last method name that was not within + * Simpletest itself. Captures a stack trace if none given. + * @param array $stack List of stack frames. + * @return string Snippet of test report with line + * number and file. + * @access public + */ + function traceMethod($stack = false) { + $stack = $stack ? $stack : $this->_captureTrace(); + foreach ($stack as $frame) { + if ($this->_frameLiesWithinSimpleTestFolder($frame)) { + continue; + } + if ($this->_frameMatchesPrefix($frame)) { + return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']'; + } + } + return ''; + } + + /** + * Test to see if error is generated by SimpleTest itself. + * @param array $frame PHP stack frame. + * @return boolean True if a SimpleTest file. + * @access private + */ + function _frameLiesWithinSimpleTestFolder($frame) { + if (isset($frame['file'])) { + $path = substr(SIMPLE_TEST, 0, -1); + if (strpos($frame['file'], $path) === 0) { + if (dirname($frame['file']) == $path) { + return true; + } + } + } + return false; + } + + /** + * Tries to determine if the method call is an assert, etc. + * @param array $frame PHP stack frame. + * @return boolean True if matches a target. + * @access private + */ + function _frameMatchesPrefix($frame) { + foreach ($this->_prefixes as $prefix) { + if (strncmp($frame['function'], $prefix, strlen($prefix)) == 0) { + return true; + } + } + return false; + } + + /** + * Grabs a current stack trace. + * @return array Fulle trace. + * @access private + */ + function _captureTrace() { + if (function_exists('debug_backtrace')) { + return array_reverse(debug_backtrace()); + } + return array(); + } +} + +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class SimpleTestOptions extends SimpleTest { + + /** + * @deprecated + */ + function getVersion() { + return Simpletest::getVersion(); + } + + /** + * @deprecated + */ + function ignore($class) { + return Simpletest::ignore($class); + } + + /** + * @deprecated + */ + function isIgnored($class) { + return Simpletest::isIgnored($class); + } + + /** + * @deprecated + */ + function setMockBaseClass($mock_base) { + return Simpletest::setMockBaseClass($mock_base); + } + + /** + * @deprecated + */ + function getMockBaseClass() { + return Simpletest::getMockBaseClass(); + } + + /** + * @deprecated + */ + function useProxy($proxy, $username = false, $password = false) { + return Simpletest::useProxy($proxy, $username, $password); + } + + /** + * @deprecated + */ + function getDefaultProxy() { + return Simpletest::getDefaultProxy(); + } + + /** + * @deprecated + */ + function getDefaultProxyUsername() { + return Simpletest::getDefaultProxyUsername(); + } + + /** + * @deprecated + */ + function getDefaultProxyPassword() { + return Simpletest::getDefaultProxyPassword(); + } +} +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/socket.php b/plugins/www/testgen4web_simpletest/lib/simpletest/socket.php new file mode 100644 index 0000000..3ad5a9f --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/socket.php @@ -0,0 +1,216 @@ +_clearError(); + } + + /** + * Test for an outstanding error. + * @return boolean True if there is an error. + * @access public + */ + function isError() { + return ($this->_error != ''); + } + + /** + * Accessor for an outstanding error. + * @return string Empty string if no error otherwise + * the error message. + * @access public + */ + function getError() { + return $this->_error; + } + + /** + * Sets the internal error. + * @param string Error message to stash. + * @access protected + */ + function _setError($error) { + $this->_error = $error; + } + + /** + * Resets the error state to no error. + * @access protected + */ + function _clearError() { + $this->_setError(''); + } +} + +/** + * Wrapper for TCP/IP socket. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleSocket extends SimpleStickyError { + var $_handle; + var $_is_open = false; + var $_sent = ''; + var $lock_size; + + /** + * Opens a socket for reading and writing. + * @param string $host Hostname to send request to. + * @param integer $port Port on remote machine to open. + * @param integer $timeout Connection timeout in seconds. + * @param integer $block_size Size of chunk to read. + * @access public + */ + function SimpleSocket($host, $port, $timeout, $block_size = 255) { + $this->SimpleStickyError(); + if (! ($this->_handle = $this->_openSocket($host, $port, $error_number, $error, $timeout))) { + $this->_setError("Cannot open [$host:$port] with [$error] within [$timeout] seconds"); + return; + } + $this->_is_open = true; + $this->_block_size = $block_size; + SimpleTestCompatibility::setTimeout($this->_handle, $timeout); + } + + /** + * Writes some data to the socket and saves alocal copy. + * @param string $message String to send to socket. + * @return boolean True if successful. + * @access public + */ + function write($message) { + if ($this->isError() || ! $this->isOpen()) { + return false; + } + $count = fwrite($this->_handle, $message); + if (! $count) { + if ($count === false) { + $this->_setError('Cannot write to socket'); + $this->close(); + } + return false; + } + fflush($this->_handle); + $this->_sent .= $message; + return true; + } + + /** + * Reads data from the socket. The error suppresion + * is a workaround for PHP4 always throwing a warning + * with a secure socket. + * @return integer/boolean Incoming bytes. False + * on error. + * @access public + */ + function read() { + if ($this->isError() || ! $this->isOpen()) { + return false; + } + $raw = @fread($this->_handle, $this->_block_size); + if ($raw === false) { + $this->_setError('Cannot read from socket'); + $this->close(); + } + return $raw; + } + + /** + * Accessor for socket open state. + * @return boolean True if open. + * @access public + */ + function isOpen() { + return $this->_is_open; + } + + /** + * Closes the socket preventing further reads. + * Cannot be reopened once closed. + * @return boolean True if successful. + * @access public + */ + function close() { + $this->_is_open = false; + return fclose($this->_handle); + } + + /** + * Accessor for content so far. + * @return string Bytes sent only. + * @access public + */ + function getSent() { + return $this->_sent; + } + + /** + * Actually opens the low level socket. + * @param string $host Host to connect to. + * @param integer $port Port on host. + * @param integer $error_number Recipient of error code. + * @param string $error Recipoent of error message. + * @param integer $timeout Maximum time to wait for connection. + * @access protected + */ + function _openSocket($host, $port, &$error_number, &$error, $timeout) { + return @fsockopen($host, $port, $error_number, $error, $timeout); + } +} + +/** + * Wrapper for TCP/IP socket over TLS. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleSecureSocket extends SimpleSocket { + + /** + * Opens a secure socket for reading and writing. + * @param string $host Hostname to send request to. + * @param integer $port Port on remote machine to open. + * @param integer $timeout Connection timeout in seconds. + * @access public + */ + function SimpleSecureSocket($host, $port, $timeout) { + $this->SimpleSocket($host, $port, $timeout); + } + + /** + * Actually opens the low level socket. + * @param string $host Host to connect to. + * @param integer $port Port on host. + * @param integer $error_number Recipient of error code. + * @param string $error Recipient of error message. + * @param integer $timeout Maximum time to wait for connection. + * @access protected + */ + function _openSocket($host, $port, &$error_number, &$error, $timeout) { + return parent::_openSocket("tls://$host", $port, $error_number, $error, $timeout); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/tag.php b/plugins/www/testgen4web_simpletest/lib/simpletest/tag.php new file mode 100644 index 0000000..7bccae2 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/tag.php @@ -0,0 +1,1418 @@ +_name = strtolower(trim($name)); + $this->_attributes = $attributes; + $this->_content = ''; + } + + /** + * Check to see if the tag can have both start and + * end tags with content in between. + * @return boolean True if content allowed. + * @access public + */ + function expectEndTag() { + return true; + } + + /** + * The current tag should not swallow all content for + * itself as it's searchable page content. Private + * content tags are usually widgets that contain default + * values. + * @return boolean False as content is available + * to other tags by default. + * @access public + */ + function isPrivateContent() { + return false; + } + + /** + * Appends string content to the current content. + * @param string $content Additional text. + * @access public + */ + function addContent($content) { + $this->_content .= (string)$content; + } + + /** + * Adds an enclosed tag to the content. + * @param SimpleTag $tag New tag. + * @access public + */ + function addTag(&$tag) { + } + + /** + * Accessor for tag name. + * @return string Name of tag. + * @access public + */ + function getTagName() { + return $this->_name; + } + + /** + * List of legal child elements. + * @return array List of element names. + * @access public + */ + function getChildElements() { + return array(); + } + + /** + * Accessor for an attribute. + * @param string $label Attribute name. + * @return string Attribute value. + * @access public + */ + function getAttribute($label) { + $label = strtolower($label); + if (! isset($this->_attributes[$label])) { + return false; + } + return (string)$this->_attributes[$label]; + } + + /** + * Sets an attribute. + * @param string $label Attribute name. + * @return string $value New attribute value. + * @access protected + */ + function _setAttribute($label, $value) { + $this->_attributes[strtolower($label)] = $value; + } + + /** + * Accessor for the whole content so far. + * @return string Content as big raw string. + * @access public + */ + function getContent() { + return $this->_content; + } + + /** + * Accessor for content reduced to visible text. Acts + * like a text mode browser, normalising space and + * reducing images to their alt text. + * @return string Content as plain text. + * @access public + */ + function getText() { + return SimpleHtmlSaxParser::normalise($this->_content); + } + + /** + * Test to see if id attribute matches. + * @param string $id ID to test against. + * @return boolean True on match. + * @access public + */ + function isId($id) { + return ($this->getAttribute('id') == $id); + } +} + +/** + * Base url. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleBaseTag extends SimpleTag { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleBaseTag($attributes) { + $this->SimpleTag('base', $attributes); + } + + /** + * Base tag is not a block tag. + * @return boolean false + * @access public + */ + function expectEndTag() { + return false; + } +} + +/** + * Page title. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleTitleTag extends SimpleTag { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleTitleTag($attributes) { + $this->SimpleTag('title', $attributes); + } +} + +/** + * Link. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleAnchorTag extends SimpleTag { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleAnchorTag($attributes) { + $this->SimpleTag('a', $attributes); + } + + /** + * Accessor for URL as string. + * @return string Coerced as string. + * @access public + */ + function getHref() { + $url = $this->getAttribute('href'); + if (is_bool($url)) { + $url = ''; + } + return $url; + } +} + +/** + * Form element. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleWidget extends SimpleTag { + var $_value; + var $_label; + var $_is_set; + + /** + * Starts with a named tag with attributes only. + * @param string $name Tag name. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleWidget($name, $attributes) { + $this->SimpleTag($name, $attributes); + $this->_value = false; + $this->_label = false; + $this->_is_set = false; + } + + /** + * Accessor for name submitted as the key in + * GET/POST variables hash. + * @return string Parsed value. + * @access public + */ + function getName() { + return $this->getAttribute('name'); + } + + /** + * Accessor for default value parsed with the tag. + * @return string Parsed value. + * @access public + */ + function getDefault() { + return $this->getAttribute('value'); + } + + /** + * Accessor for currently set value or default if + * none. + * @return string Value set by form or default + * if none. + * @access public + */ + function getValue() { + if (! $this->_is_set) { + return $this->getDefault(); + } + return $this->_value; + } + + /** + * Sets the current form element value. + * @param string $value New value. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + $this->_value = $value; + $this->_is_set = true; + return true; + } + + /** + * Resets the form element value back to the + * default. + * @access public + */ + function resetValue() { + $this->_is_set = false; + } + + /** + * Allows setting of a label externally, say by a + * label tag. + * @param string $label Label to attach. + * @access public + */ + function setLabel($label) { + $this->_label = trim($label); + } + + /** + * Reads external or internal label. + * @param string $label Label to test. + * @return boolean True is match. + * @access public + */ + function isLabel($label) { + return $this->_label == trim($label); + } + + /** + * Dispatches the value into the form encoded packet. + * @param SimpleEncoding $encoding Form packet. + * @access public + */ + function write(&$encoding) { + if ($this->getName()) { + $encoding->add($this->getName(), $this->getValue()); + } + } +} + +/** + * Text, password and hidden field. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleTextTag extends SimpleWidget { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleTextTag($attributes) { + $this->SimpleWidget('input', $attributes); + if ($this->getAttribute('value') === false) { + $this->_setAttribute('value', ''); + } + } + + /** + * Tag contains no content. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } + + /** + * Sets the current form element value. Cannot + * change the value of a hidden field. + * @param string $value New value. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + if ($this->getAttribute('type') == 'hidden') { + return false; + } + return parent::setValue($value); + } +} + +/** + * Submit button as input tag. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleSubmitTag extends SimpleWidget { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleSubmitTag($attributes) { + $this->SimpleWidget('input', $attributes); + if ($this->getAttribute('value') === false) { + $this->_setAttribute('value', 'Submit'); + } + } + + /** + * Tag contains no end element. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } + + /** + * Disables the setting of the button value. + * @param string $value Ignored. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + return false; + } + + /** + * Value of browser visible text. + * @return string Visible label. + * @access public + */ + function getLabel() { + return $this->getValue(); + } + + /** + * Test for a label match when searching. + * @param string $label Label to test. + * @return boolean True on match. + * @access public + */ + function isLabel($label) { + return trim($label) == trim($this->getLabel()); + } +} + +/** + * Image button as input tag. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleImageSubmitTag extends SimpleWidget { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleImageSubmitTag($attributes) { + $this->SimpleWidget('input', $attributes); + } + + /** + * Tag contains no end element. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } + + /** + * Disables the setting of the button value. + * @param string $value Ignored. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + return false; + } + + /** + * Value of browser visible text. + * @return string Visible label. + * @access public + */ + function getLabel() { + if ($this->getAttribute('title')) { + return $this->getAttribute('title'); + } + return $this->getAttribute('alt'); + } + + /** + * Test for a label match when searching. + * @param string $label Label to test. + * @return boolean True on match. + * @access public + */ + function isLabel($label) { + return trim($label) == trim($this->getLabel()); + } + + /** + * Dispatches the value into the form encoded packet. + * @param SimpleEncoding $encoding Form packet. + * @param integer $x X coordinate of click. + * @param integer $y Y coordinate of click. + * @access public + */ + function write(&$encoding, $x, $y) { + if ($this->getName()) { + $encoding->add($this->getName() . '.x', $x); + $encoding->add($this->getName() . '.y', $y); + } else { + $encoding->add('x', $x); + $encoding->add('y', $y); + } + } +} + +/** + * Submit button as button tag. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleButtonTag extends SimpleWidget { + + /** + * Starts with a named tag with attributes only. + * Defaults are very browser dependent. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleButtonTag($attributes) { + $this->SimpleWidget('button', $attributes); + } + + /** + * Check to see if the tag can have both start and + * end tags with content in between. + * @return boolean True if content allowed. + * @access public + */ + function expectEndTag() { + return true; + } + + /** + * Disables the setting of the button value. + * @param string $value Ignored. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + return false; + } + + /** + * Value of browser visible text. + * @return string Visible label. + * @access public + */ + function getLabel() { + return $this->getContent(); + } + + /** + * Test for a label match when searching. + * @param string $label Label to test. + * @return boolean True on match. + * @access public + */ + function isLabel($label) { + return trim($label) == trim($this->getLabel()); + } +} + +/** + * Content tag for text area. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleTextAreaTag extends SimpleWidget { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleTextAreaTag($attributes) { + $this->SimpleWidget('textarea', $attributes); + } + + /** + * Accessor for starting value. + * @return string Parsed value. + * @access public + */ + function getDefault() { + return $this->_wrap(SimpleHtmlSaxParser::decodeHtml($this->getContent())); + } + + /** + * Applies word wrapping if needed. + * @param string $value New value. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + return parent::setValue($this->_wrap($value)); + } + + /** + * Test to see if text should be wrapped. + * @return boolean True if wrapping on. + * @access private + */ + function _wrapIsEnabled() { + if ($this->getAttribute('cols')) { + $wrap = $this->getAttribute('wrap'); + if (($wrap == 'physical') || ($wrap == 'hard')) { + return true; + } + } + return false; + } + + /** + * Performs the formatting that is peculiar to + * this tag. There is strange behaviour in this + * one, including stripping a leading new line. + * Go figure. I am using Firefox as a guide. + * @param string $text Text to wrap. + * @return string Text wrapped with carriage + * returns and line feeds + * @access private + */ + function _wrap($text) { + $text = str_replace("\r\r\n", "\r\n", str_replace("\n", "\r\n", $text)); + $text = str_replace("\r\n\n", "\r\n", str_replace("\r", "\r\n", $text)); + if (strncmp($text, "\r\n", strlen("\r\n")) == 0) { + $text = substr($text, strlen("\r\n")); + } + if ($this->_wrapIsEnabled()) { + return wordwrap( + $text, + (integer)$this->getAttribute('cols'), + "\r\n"); + } + return $text; + } + + /** + * The content of textarea is not part of the page. + * @return boolean True. + * @access public + */ + function isPrivateContent() { + return true; + } +} + +/** + * File upload widget. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleUploadTag extends SimpleWidget { + + /** + * Starts with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleUploadTag($attributes) { + $this->SimpleWidget('input', $attributes); + } + + /** + * Tag contains no content. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } + + /** + * Dispatches the value into the form encoded packet. + * @param SimpleEncoding $encoding Form packet. + * @access public + */ + function write(&$encoding) { + if (! file_exists($this->getValue())) { + return; + } + $encoding->attach( + $this->getName(), + implode('', file($this->getValue())), + basename($this->getValue())); + } +} + +/** + * Drop down widget. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleSelectionTag extends SimpleWidget { + var $_options; + var $_choice; + + /** + * Starts with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleSelectionTag($attributes) { + $this->SimpleWidget('select', $attributes); + $this->_options = array(); + $this->_choice = false; + } + + /** + * Adds an option tag to a selection field. + * @param SimpleOptionTag $tag New option. + * @access public + */ + function addTag(&$tag) { + if ($tag->getTagName() == 'option') { + $this->_options[] = &$tag; + } + } + + /** + * Text within the selection element is ignored. + * @param string $content Ignored. + * @access public + */ + function addContent($content) { + } + + /** + * Scans options for defaults. If none, then + * the first option is selected. + * @return string Selected field. + * @access public + */ + function getDefault() { + for ($i = 0, $count = count($this->_options); $i < $count; $i++) { + if ($this->_options[$i]->getAttribute('selected') !== false) { + return $this->_options[$i]->getDefault(); + } + } + if ($count > 0) { + return $this->_options[0]->getDefault(); + } + return ''; + } + + /** + * Can only set allowed values. + * @param string $value New choice. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + for ($i = 0, $count = count($this->_options); $i < $count; $i++) { + if ($this->_options[$i]->isValue($value)) { + $this->_choice = $i; + return true; + } + } + return false; + } + + /** + * Accessor for current selection value. + * @return string Value attribute or + * content of opton. + * @access public + */ + function getValue() { + if ($this->_choice === false) { + return $this->getDefault(); + } + return $this->_options[$this->_choice]->getValue(); + } +} + +/** + * Drop down widget. + * @package SimpleTest + * @subpackage WebTester + */ +class MultipleSelectionTag extends SimpleWidget { + var $_options; + var $_values; + + /** + * Starts with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function MultipleSelectionTag($attributes) { + $this->SimpleWidget('select', $attributes); + $this->_options = array(); + $this->_values = false; + } + + /** + * Adds an option tag to a selection field. + * @param SimpleOptionTag $tag New option. + * @access public + */ + function addTag(&$tag) { + if ($tag->getTagName() == 'option') { + $this->_options[] = &$tag; + } + } + + /** + * Text within the selection element is ignored. + * @param string $content Ignored. + * @access public + */ + function addContent($content) { + } + + /** + * Scans options for defaults to populate the + * value array(). + * @return array Selected fields. + * @access public + */ + function getDefault() { + $default = array(); + for ($i = 0, $count = count($this->_options); $i < $count; $i++) { + if ($this->_options[$i]->getAttribute('selected') !== false) { + $default[] = $this->_options[$i]->getDefault(); + } + } + return $default; + } + + /** + * Can only set allowed values. Any illegal value + * will result in a failure, but all correct values + * will be set. + * @param array $desired New choices. + * @return boolean True if all allowed. + * @access public + */ + function setValue($desired) { + $achieved = array(); + foreach ($desired as $value) { + $success = false; + for ($i = 0, $count = count($this->_options); $i < $count; $i++) { + if ($this->_options[$i]->isValue($value)) { + $achieved[] = $this->_options[$i]->getValue(); + $success = true; + break; + } + } + if (! $success) { + return false; + } + } + $this->_values = $achieved; + return true; + } + + /** + * Accessor for current selection value. + * @return array List of currently set options. + * @access public + */ + function getValue() { + if ($this->_values === false) { + return $this->getDefault(); + } + return $this->_values; + } +} + +/** + * Option for selection field. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleOptionTag extends SimpleWidget { + + /** + * Stashes the attributes. + */ + function SimpleOptionTag($attributes) { + $this->SimpleWidget('option', $attributes); + } + + /** + * Does nothing. + * @param string $value Ignored. + * @return boolean Not allowed. + * @access public + */ + function setValue($value) { + return false; + } + + /** + * Test to see if a value matches the option. + * @param string $compare Value to compare with. + * @return boolean True if possible match. + * @access public + */ + function isValue($compare) { + $compare = trim($compare); + if (trim($this->getValue()) == $compare) { + return true; + } + return trim($this->getContent()) == $compare; + } + + /** + * Accessor for starting value. Will be set to + * the option label if no value exists. + * @return string Parsed value. + * @access public + */ + function getDefault() { + if ($this->getAttribute('value') === false) { + return $this->getContent(); + } + return $this->getAttribute('value'); + } + + /** + * The content of options is not part of the page. + * @return boolean True. + * @access public + */ + function isPrivateContent() { + return true; + } +} + +/** + * Radio button. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleRadioButtonTag extends SimpleWidget { + + /** + * Stashes the attributes. + * @param array $attributes Hash of attributes. + */ + function SimpleRadioButtonTag($attributes) { + $this->SimpleWidget('input', $attributes); + if ($this->getAttribute('value') === false) { + $this->_setAttribute('value', 'on'); + } + } + + /** + * Tag contains no content. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } + + /** + * The only allowed value sn the one in the + * "value" attribute. + * @param string $value New value. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + if ($value === false) { + return parent::setValue($value); + } + if ($value != $this->getAttribute('value')) { + return false; + } + return parent::setValue($value); + } + + /** + * Accessor for starting value. + * @return string Parsed value. + * @access public + */ + function getDefault() { + if ($this->getAttribute('checked') !== false) { + return $this->getAttribute('value'); + } + return false; + } +} + +/** + * Checkbox widget. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleCheckboxTag extends SimpleWidget { + + /** + * Starts with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleCheckboxTag($attributes) { + $this->SimpleWidget('input', $attributes); + if ($this->getAttribute('value') === false) { + $this->_setAttribute('value', 'on'); + } + } + + /** + * Tag contains no content. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } + + /** + * The only allowed value in the one in the + * "value" attribute. The default for this + * attribute is "on". If this widget is set to + * true, then the usual value will be taken. + * @param string $value New value. + * @return boolean True if allowed. + * @access public + */ + function setValue($value) { + if ($value === false) { + return parent::setValue($value); + } + if ($value === true) { + return parent::setValue($this->getAttribute('value')); + } + if ($value != $this->getAttribute('value')) { + return false; + } + return parent::setValue($value); + } + + /** + * Accessor for starting value. The default + * value is "on". + * @return string Parsed value. + * @access public + */ + function getDefault() { + if ($this->getAttribute('checked') !== false) { + return $this->getAttribute('value'); + } + return false; + } +} + +/** + * A group of multiple widgets with some shared behaviour. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleTagGroup { + var $_widgets = array(); + + /** + * Adds a tag to the group. + * @param SimpleWidget $widget + * @access public + */ + function addWidget(&$widget) { + $this->_widgets[] = &$widget; + } + + /** + * Accessor to widget set. + * @return array All widgets. + * @access protected + */ + function &_getWidgets() { + return $this->_widgets; + } + + /** + * Accessor for an attribute. + * @param string $label Attribute name. + * @return boolean Always false. + * @access public + */ + function getAttribute($label) { + return false; + } + + /** + * Fetches the name for the widget from the first + * member. + * @return string Name of widget. + * @access public + */ + function getName() { + if (count($this->_widgets) > 0) { + return $this->_widgets[0]->getName(); + } + } + + /** + * Scans the widgets for one with the appropriate + * ID field. + * @param string $id ID value to try. + * @return boolean True if matched. + * @access public + */ + function isId($id) { + for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) { + if ($this->_widgets[$i]->isId($id)) { + return true; + } + } + return false; + } + + /** + * Scans the widgets for one with the appropriate + * attached label. + * @param string $label Attached label to try. + * @return boolean True if matched. + * @access public + */ + function isLabel($label) { + for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) { + if ($this->_widgets[$i]->isLabel($label)) { + return true; + } + } + return false; + } + + /** + * Dispatches the value into the form encoded packet. + * @param SimpleEncoding $encoding Form packet. + * @access public + */ + function write(&$encoding) { + $encoding->add($this->getName(), $this->getValue()); + } +} + +/** + * A group of tags with the same name within a form. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleCheckboxGroup extends SimpleTagGroup { + + /** + * Accessor for current selected widget or false + * if none. + * @return string/array Widget values or false if none. + * @access public + */ + function getValue() { + $values = array(); + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + if ($widgets[$i]->getValue() !== false) { + $values[] = $widgets[$i]->getValue(); + } + } + return $this->_coerceValues($values); + } + + /** + * Accessor for starting value that is active. + * @return string/array Widget values or false if none. + * @access public + */ + function getDefault() { + $values = array(); + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + if ($widgets[$i]->getDefault() !== false) { + $values[] = $widgets[$i]->getDefault(); + } + } + return $this->_coerceValues($values); + } + + /** + * Accessor for current set values. + * @param string/array/boolean $values Either a single string, a + * hash or false for nothing set. + * @return boolean True if all values can be set. + * @access public + */ + function setValue($values) { + $values = $this->_makeArray($values); + if (! $this->_valuesArePossible($values)) { + return false; + } + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + $possible = $widgets[$i]->getAttribute('value'); + if (in_array($widgets[$i]->getAttribute('value'), $values)) { + $widgets[$i]->setValue($possible); + } else { + $widgets[$i]->setValue(false); + } + } + return true; + } + + /** + * Tests to see if a possible value set is legal. + * @param string/array/boolean $values Either a single string, a + * hash or false for nothing set. + * @return boolean False if trying to set a + * missing value. + * @access private + */ + function _valuesArePossible($values) { + $matches = array(); + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + $possible = $widgets[$i]->getAttribute('value'); + if (in_array($possible, $values)) { + $matches[] = $possible; + } + } + return ($values == $matches); + } + + /** + * Converts the output to an appropriate format. This means + * that no values is false, a single value is just that + * value and only two or more are contained in an array. + * @param array $values List of values of widgets. + * @return string/array/boolean Expected format for a tag. + * @access private + */ + function _coerceValues($values) { + if (count($values) == 0) { + return false; + } elseif (count($values) == 1) { + return $values[0]; + } else { + return $values; + } + } + + /** + * Converts false or string into array. The opposite of + * the coercian method. + * @param string/array/boolean $value A single item is converted + * to a one item list. False + * gives an empty list. + * @return array List of values, possibly empty. + * @access private + */ + function _makeArray($value) { + if ($value === false) { + return array(); + } + if (is_string($value)) { + return array($value); + } + return $value; + } +} + +/** + * A group of tags with the same name within a form. + * Used for radio buttons. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleRadioGroup extends SimpleTagGroup { + + /** + * Each tag is tried in turn until one is + * successfully set. The others will be + * unchecked if successful. + * @param string $value New value. + * @return boolean True if any allowed. + * @access public + */ + function setValue($value) { + if (! $this->_valueIsPossible($value)) { + return false; + } + $index = false; + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + if (! $widgets[$i]->setValue($value)) { + $widgets[$i]->setValue(false); + } + } + return true; + } + + /** + * Tests to see if a value is allowed. + * @param string Attempted value. + * @return boolean True if a valid value. + * @access private + */ + function _valueIsPossible($value) { + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + if ($widgets[$i]->getAttribute('value') == $value) { + return true; + } + } + return false; + } + + /** + * Accessor for current selected widget or false + * if none. + * @return string/boolean Value attribute or + * content of opton. + * @access public + */ + function getValue() { + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + if ($widgets[$i]->getValue() !== false) { + return $widgets[$i]->getValue(); + } + } + return false; + } + + /** + * Accessor for starting value that is active. + * @return string/boolean Value of first checked + * widget or false if none. + * @access public + */ + function getDefault() { + $widgets = &$this->_getWidgets(); + for ($i = 0, $count = count($widgets); $i < $count; $i++) { + if ($widgets[$i]->getDefault() !== false) { + return $widgets[$i]->getDefault(); + } + } + return false; + } +} + +/** + * Tag to keep track of labels. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleLabelTag extends SimpleTag { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleLabelTag($attributes) { + $this->SimpleTag('label', $attributes); + } + + /** + * Access for the ID to attach the label to. + * @return string For attribute. + * @access public + */ + function getFor() { + return $this->getAttribute('for'); + } +} + +/** + * Tag to aid parsing the form. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleFormTag extends SimpleTag { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleFormTag($attributes) { + $this->SimpleTag('form', $attributes); + } +} + +/** + * Tag to aid parsing the frames in a page. + * @package SimpleTest + * @subpackage WebTester + */ +class SimpleFrameTag extends SimpleTag { + + /** + * Starts with a named tag with attributes only. + * @param hash $attributes Attribute names and + * string values. + */ + function SimpleFrameTag($attributes) { + $this->SimpleTag('frame', $attributes); + } + + /** + * Tag contains no content. + * @return boolean False. + * @access public + */ + function expectEndTag() { + return false; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/test_case.php b/plugins/www/testgen4web_simpletest/lib/simpletest/test_case.php new file mode 100644 index 0000000..e5b2298 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/test_case.php @@ -0,0 +1,708 @@ += 0) { + require_once(dirname(__FILE__) . '/exceptions.php'); + require_once(dirname(__FILE__) . '/reflection_php5.php'); +} else { + require_once(dirname(__FILE__) . '/reflection_php4.php'); +} +if (! defined('SIMPLE_TEST')) { + /** + * @ignore + */ + define('SIMPLE_TEST', dirname(__FILE__) . DIRECTORY_SEPARATOR); +} +/**#@-*/ + +/** + * Basic test case. This is the smallest unit of a test + * suite. It searches for + * all methods that start with the the string "test" and + * runs them. Working test cases extend this class. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleTestCase { + var $_label = false; + var $_reporter; + var $_observers; + var $_should_skip = false; + + /** + * Sets up the test with no display. + * @param string $label If no test name is given then + * the class name is used. + * @access public + */ + function SimpleTestCase($label = false) { + if ($label) { + $this->_label = $label; + } + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_label ? $this->_label : get_class($this); + } + + /** + * This is a placeholder for skipping tests. In this + * method you place skipIf() and skipUnless() calls to + * set the skipping state. + * @access public + */ + function skip() { + } + + /** + * Will issue a message to the reporter and tell the test + * case to skip if the incoming flag is true. + * @param string $should_skip Condition causing the tests to be skipped. + * @param string $message Text of skip condition. + * @access public + */ + function skipIf($should_skip, $message = '%s') { + if ($should_skip && ! $this->_should_skip) { + $this->_should_skip = true; + $message = sprintf($message, 'Skipping [' . get_class($this) . ']'); + $this->_reporter->paintSkip($message . $this->getAssertionLine()); + } + } + + /** + * Will issue a message to the reporter and tell the test + * case to skip if the incoming flag is false. + * @param string $shouldnt_skip Condition causing the tests to be run. + * @param string $message Text of skip condition. + * @access public + */ + function skipUnless($shouldnt_skip, $message = false) { + $this->skipIf(! $shouldnt_skip, $message); + } + + /** + * Used to invoke the single tests. + * @return SimpleInvoker Individual test runner. + * @access public + */ + function &createInvoker() { + $invoker = &new SimpleErrorTrappingInvoker(new SimpleInvoker($this)); + if (version_compare(phpversion(), '5') >= 0) { + $invoker = &new SimpleExceptionTrappingInvoker($invoker); + } + return $invoker; + } + + /** + * Uses reflection to run every method within itself + * starting with the string "test" unless a method + * is specified. + * @param SimpleReporter $reporter Current test reporter. + * @return boolean True if all tests passed. + * @access public + */ + function run(&$reporter) { + $context = &SimpleTest::getContext(); + $context->setTest($this); + $context->setReporter($reporter); + $this->_reporter = &$reporter; + $started = false; + foreach ($this->getTests() as $method) { + if ($reporter->shouldInvoke($this->getLabel(), $method)) { + $this->skip(); + if ($this->_should_skip) { + break; + } + if (! $started) { + $reporter->paintCaseStart($this->getLabel()); + $started = true; + } + $invoker = &$this->_reporter->createInvoker($this->createInvoker()); + $invoker->before($method); + $invoker->invoke($method); + $invoker->after($method); + } + } + if ($started) { + $reporter->paintCaseEnd($this->getLabel()); + } + unset($this->_reporter); + return $reporter->getStatus(); + } + + /** + * Gets a list of test names. Normally that will + * be all internal methods that start with the + * name "test". This method should be overridden + * if you want a different rule. + * @return array List of test names. + * @access public + */ + function getTests() { + $methods = array(); + foreach (get_class_methods(get_class($this)) as $method) { + if ($this->_isTest($method)) { + $methods[] = $method; + } + } + return $methods; + } + + /** + * Tests to see if the method is a test that should + * be run. Currently any method that starts with 'test' + * is a candidate unless it is the constructor. + * @param string $method Method name to try. + * @return boolean True if test method. + * @access protected + */ + function _isTest($method) { + if (strtolower(substr($method, 0, 4)) == 'test') { + return ! SimpleTestCompatibility::isA($this, strtolower($method)); + } + return false; + } + + /** + * Announces the start of the test. + * @param string $method Test method just started. + * @access public + */ + function before($method) { + $this->_reporter->paintMethodStart($method); + $this->_observers = array(); + } + + /** + * Sets up unit test wide variables at the start + * of each test method. To be overridden in + * actual user test cases. + * @access public + */ + function setUp() { + } + + /** + * Clears the data set in the setUp() method call. + * To be overridden by the user in actual user test cases. + * @access public + */ + function tearDown() { + } + + /** + * Announces the end of the test. Includes private clean up. + * @param string $method Test method just finished. + * @access public + */ + function after($method) { + for ($i = 0; $i < count($this->_observers); $i++) { + $this->_observers[$i]->atTestEnd($method, $this); + } + $this->_reporter->paintMethodEnd($method); + } + + /** + * Sets up an observer for the test end. + * @param object $observer Must have atTestEnd() + * method. + * @access public + */ + function tell(&$observer) { + $this->_observers[] = &$observer; + } + + /** + * @deprecated + */ + function pass($message = "Pass") { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); + } + $this->_reporter->paintPass( + $message . $this->getAssertionLine()); + return true; + } + + /** + * Sends a fail event with a message. + * @param string $message Message to send. + * @access public + */ + function fail($message = "Fail") { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); + } + $this->_reporter->paintFail( + $message . $this->getAssertionLine()); + return false; + } + + /** + * Formats a PHP error and dispatches it to the + * reporter. + * @param integer $severity PHP error code. + * @param string $message Text of error. + * @param string $file File error occoured in. + * @param integer $line Line number of error. + * @access public + */ + function error($severity, $message, $file, $line) { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); + } + $this->_reporter->paintError( + "Unexpected PHP error [$message] severity [$severity] in [$file line $line]"); + } + + /** + * Formats an exception and dispatches it to the + * reporter. + * @param Exception $exception Object thrown. + * @access public + */ + function exception($exception) { + $this->_reporter->paintException($exception); + } + + /** + * @deprecated + */ + function signal($type, &$payload) { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); + } + $this->_reporter->paintSignal($type, $payload); + } + + /** + * Runs an expectation directly, for extending the + * tests with new expectation classes. + * @param SimpleExpectation $expectation Expectation subclass. + * @param mixed $compare Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assert(&$expectation, $compare, $message = '%s') { + if ($expectation->test($compare)) { + return $this->pass(sprintf( + $message, + $expectation->overlayMessage($compare, $this->_reporter->getDumper()))); + } else { + return $this->fail(sprintf( + $message, + $expectation->overlayMessage($compare, $this->_reporter->getDumper()))); + } + } + + /** + * @deprecated + */ + function assertExpectation(&$expectation, $compare, $message = '%s') { + return $this->assert($expectation, $compare, $message); + } + + /** + * Uses a stack trace to find the line of an assertion. + * @return string Line number of first assert* + * method embedded in format string. + * @access public + */ + function getAssertionLine() { + $trace = new SimpleStackTrace(array('assert', 'expect', 'pass', 'fail', 'skip')); + return $trace->traceMethod(); + } + + /** + * Sends a formatted dump of a variable to the + * test suite for those emergency debugging + * situations. + * @param mixed $variable Variable to display. + * @param string $message Message to display. + * @return mixed The original variable. + * @access public + */ + function dump($variable, $message = false) { + $dumper = $this->_reporter->getDumper(); + $formatted = $dumper->dump($variable); + if ($message) { + $formatted = $message . "\n" . $formatted; + } + $this->_reporter->paintFormattedMessage($formatted); + return $variable; + } + + /** + * @deprecated + */ + function sendMessage($message) { + $this->_reporter->PaintMessage($message); + } + + /** + * Accessor for the number of subtests including myelf. + * @return integer Number of test cases. + * @access public + * @static + */ + function getSize() { + return 1; + } +} + +/** + * Helps to extract test cases automatically from a file. + */ +class SimpleFileLoader { + + /** + * Builds a test suite from a library of test cases. + * The new suite is composed into this one. + * @param string $test_file File name of library with + * test case classes. + * @return TestSuite The new test suite. + * @access public + */ + function &load($test_file) { + $existing_classes = get_declared_classes(); + $existing_globals = get_defined_vars(); + include_once($test_file); + $new_globals = get_defined_vars(); + $this->_makeFileVariablesGlobal($existing_globals, $new_globals); + $new_classes = array_diff(get_declared_classes(), $existing_classes); + if (empty($new_classes)) { + $new_classes = $this->_scrapeClassesFromFile($test_file); + } + $classes = $this->selectRunnableTests($new_classes); + $suite = &$this->createSuiteFromClasses($test_file, $classes); + return $suite; + } + + /** + * Imports new variables into the global namespace. + * @param hash $existing Variables before the file was loaded. + * @param hash $new Variables after the file was loaded. + * @access private + */ + function _makeFileVariablesGlobal($existing, $new) { + $globals = array_diff(array_keys($new), array_keys($existing)); + foreach ($globals as $global) { + $_GLOBALS[$global] = $new[$global]; + } + } + + /** + * Lookup classnames from file contents, in case the + * file may have been included before. + * Note: This is probably too clever by half. Figuring this + * out after a failed test case is going to be tricky for us, + * never mind the user. A test case should not be included + * twice anyway. + * @param string $test_file File name with classes. + * @access private + */ + function _scrapeClassesFromFile($test_file) { + preg_match_all('~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', + file_get_contents($test_file), + $matches ); + return $matches[1]; + } + + /** + * Calculates the incoming test cases. Skips abstract + * and ignored classes. + * @param array $candidates Candidate classes. + * @return array New classes which are test + * cases that shouldn't be ignored. + * @access public + */ + function selectRunnableTests($candidates) { + $classes = array(); + foreach ($candidates as $class) { + if (TestSuite::getBaseTestCase($class)) { + $reflection = new SimpleReflection($class); + if ($reflection->isAbstract()) { + SimpleTest::ignore($class); + } else { + $classes[] = $class; + } + } + } + return $classes; + } + + /** + * Builds a test suite from a class list. + * @param string $title Title of new group. + * @param array $classes Test classes. + * @return TestSuite Group loaded with the new + * test cases. + * @access public + */ + function &createSuiteFromClasses($title, $classes) { + if (count($classes) == 0) { + $suite = &new BadTestSuite($title, "No runnable test cases in [$title]"); + return $suite; + } + SimpleTest::ignoreParentsIfIgnored($classes); + $suite = &new TestSuite($title); + foreach ($classes as $class) { + if (! SimpleTest::isIgnored($class)) { + $suite->addTestClass($class); + } + } + return $suite; + } +} + +/** + * This is a composite test class for combining + * test cases and other RunnableTest classes into + * a group test. + * @package SimpleTest + * @subpackage UnitTester + */ +class TestSuite { + var $_label; + var $_test_cases; + + /** + * Sets the name of the test suite. + * @param string $label Name sent at the start and end + * of the test. + * @access public + */ + function TestSuite($label = false) { + $this->_label = $label; + $this->_test_cases = array(); + } + + /** + * Accessor for the test name for subclasses. If the suite + * wraps a single test case the label defaults to the name of that test. + * @return string Name of the test. + * @access public + */ + function getLabel() { + if (! $this->_label) { + return ($this->getSize() == 1) ? + get_class($this->_test_cases[0]) : get_class($this); + } else { + return $this->_label; + } + } + + /** + * @deprecated + */ + function addTestCase(&$test_case) { + $this->_test_cases[] = &$test_case; + } + + /** + * @deprecated + */ + function addTestClass($class) { + if (TestSuite::getBaseTestCase($class) == 'testsuite') { + $this->_test_cases[] = &new $class(); + } else { + $this->_test_cases[] = $class; + } + } + + /** + * Adds a test into the suite by instance or class. The class will + * be instantiated if it's a test suite. + * @param SimpleTestCase $test_case Suite or individual test + * case implementing the + * runnable test interface. + * @access public + */ + function add(&$test_case) { + if (! is_string($test_case)) { + $this->_test_cases[] = &$test_case; + } elseif (TestSuite::getBaseTestCase($class) == 'testsuite') { + $this->_test_cases[] = &new $class(); + } else { + $this->_test_cases[] = $class; + } + } + + /** + * @deprecated + */ + function addTestFile($test_file) { + $this->addFile($test_file); + } + + /** + * Builds a test suite from a library of test cases. + * The new suite is composed into this one. + * @param string $test_file File name of library with + * test case classes. + * @access public + */ + function addFile($test_file) { + $extractor = new SimpleFileLoader(); + $this->add($extractor->load($test_file)); + } + + /** + * Delegates to a visiting collector to add test + * files. + * @param string $path Path to scan from. + * @param SimpleCollector $collector Directory scanner. + * @access public + */ + function collect($path, &$collector) { + $collector->collect($this, $path); + } + + /** + * Invokes run() on all of the held test cases, instantiating + * them if necessary. + * @param SimpleReporter $reporter Current test reporter. + * @access public + */ + function run(&$reporter) { + $reporter->paintGroupStart($this->getLabel(), $this->getSize()); + for ($i = 0, $count = count($this->_test_cases); $i < $count; $i++) { + if (is_string($this->_test_cases[$i])) { + $class = $this->_test_cases[$i]; + $test = &new $class(); + $test->run($reporter); + unset($test); + } else { + $this->_test_cases[$i]->run($reporter); + } + } + $reporter->paintGroupEnd($this->getLabel()); + return $reporter->getStatus(); + } + + /** + * Number of contained test cases. + * @return integer Total count of cases in the group. + * @access public + */ + function getSize() { + $count = 0; + foreach ($this->_test_cases as $case) { + if (is_string($case)) { + if (! SimpleTest::isIgnored($case)) { + $count++; + } + } else { + $count += $case->getSize(); + } + } + return $count; + } + + /** + * Test to see if a class is derived from the + * SimpleTestCase class. + * @param string $class Class name. + * @access public + * @static + */ + function getBaseTestCase($class) { + while ($class = get_parent_class($class)) { + $class = strtolower($class); + if ($class == 'simpletestcase' || $class == 'testsuite') { + return $class; + } + } + return false; + } +} + +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class GroupTest extends TestSuite { } + +/** + * This is a failing group test for when a test suite hasn't + * loaded properly. + * @package SimpleTest + * @subpackage UnitTester + */ +class BadTestSuite { + var $_label; + var $_error; + + /** + * Sets the name of the test suite and error message. + * @param string $label Name sent at the start and end + * of the test. + * @access public + */ + function BadTestSuite($label, $error) { + $this->_label = $label; + $this->_error = $error; + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_label; + } + + /** + * Sends a single error to the reporter. + * @param SimpleReporter $reporter Current test reporter. + * @access public + */ + function run(&$reporter) { + $reporter->paintGroupStart($this->getLabel(), $this->getSize()); + $reporter->paintFail('Bad TestSuite [' . $this->getLabel() . + '] with error [' . $this->_error . ']'); + $reporter->paintGroupEnd($this->getLabel()); + return $reporter->getStatus(); + } + + /** + * Number of contained test cases. Always zero. + * @return integer Total count of cases in the group. + * @access public + */ + function getSize() { + return 0; + } +} + +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class BadGroupTest extends BadTestSuite { } +?> diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/unit_tester.php b/plugins/www/testgen4web_simpletest/lib/simpletest/unit_tester.php new file mode 100644 index 0000000..8bb757d --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/unit_tester.php @@ -0,0 +1,420 @@ +SimpleTestCase($label); + } + + /** + * Called from within the test methods to register + * passes and failures. + * @param boolean $result Pass on true. + * @param string $message Message to display describing + * the test state. + * @return boolean True on pass + * @access public + */ + function assertTrue($result, $message = false) { + return $this->assert(new TrueExpectation(), $result, $message); + } + + /** + * Will be true on false and vice versa. False + * is the PHP definition of false, so that null, + * empty strings, zero and an empty array all count + * as false. + * @param boolean $result Pass on false. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertFalse($result, $message = '%s') { + return $this->assert(new FalseExpectation(), $result, $message); + } + + /** + * Will be true if the value is null. + * @param null $value Supposedly null value. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertNull($value, $message = '%s') { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + '[' . $dumper->describeValue($value) . '] should be null'); + return $this->assertTrue(! isset($value), $message); + } + + /** + * Will be true if the value is set. + * @param mixed $value Supposedly set value. + * @param string $message Message to display. + * @return boolean True on pass. + * @access public + */ + function assertNotNull($value, $message = '%s') { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + '[' . $dumper->describeValue($value) . '] should not be null'); + return $this->assertTrue(isset($value), $message); + } + + /** + * Type and class test. Will pass if class + * matches the type name or is a subclass or + * if not an object, but the type is correct. + * @param mixed $object Object to test. + * @param string $type Type name as string. + * @param string $message Message to display. + * @return boolean True on pass. + * @access public + */ + function assertIsA($object, $type, $message = '%s') { + return $this->assert( + new IsAExpectation($type), + $object, + $message); + } + + /** + * Type and class mismatch test. Will pass if class + * name or underling type does not match the one + * specified. + * @param mixed $object Object to test. + * @param string $type Type name as string. + * @param string $message Message to display. + * @return boolean True on pass. + * @access public + */ + function assertNotA($object, $type, $message = '%s') { + return $this->assert( + new NotAExpectation($type), + $object, + $message); + } + + /** + * Will trigger a pass if the two parameters have + * the same value only. Otherwise a fail. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertEqual($first, $second, $message = '%s') { + return $this->assert( + new EqualExpectation($first), + $second, + $message); + } + + /** + * Will trigger a pass if the two parameters have + * a different value. Otherwise a fail. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertNotEqual($first, $second, $message = '%s') { + return $this->assert( + new NotEqualExpectation($first), + $second, + $message); + } + + /** + * Will trigger a pass if the if the first parameter + * is near enough to the second by the margin. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param mixed $margin Fuzziness of match. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertWithinMargin($first, $second, $margin, $message = '%s') { + return $this->assert( + new WithinMarginExpectation($first, $margin), + $second, + $message); + } + + /** + * Will trigger a pass if the two parameters differ + * by more than the margin. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param mixed $margin Fuzziness of match. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertOutsideMargin($first, $second, $margin, $message = '%s') { + return $this->assert( + new OutsideMarginExpectation($first, $margin), + $second, + $message); + } + + /** + * Will trigger a pass if the two parameters have + * the same value and same type. Otherwise a fail. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertIdentical($first, $second, $message = '%s') { + return $this->assert( + new IdenticalExpectation($first), + $second, + $message); + } + + /** + * Will trigger a pass if the two parameters have + * the different value or different type. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertNotIdentical($first, $second, $message = '%s') { + return $this->assert( + new NotIdenticalExpectation($first), + $second, + $message); + } + + /** + * Will trigger a pass if both parameters refer + * to the same object. Fail otherwise. + * @param mixed $first Object reference to check. + * @param mixed $second Hopefully the same object. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertReference(&$first, &$second, $message = '%s') { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + '[' . $dumper->describeValue($first) . + '] and [' . $dumper->describeValue($second) . + '] should reference the same object'); + return $this->assertTrue( + SimpleTestCompatibility::isReference($first, $second), + $message); + } + + /** + * Will trigger a pass if both parameters refer + * to different objects. Fail otherwise. The objects + * have to be identical though. + * @param mixed $first Object reference to check. + * @param mixed $second Hopefully not the same object. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertClone(&$first, &$second, $message = '%s') { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + '[' . $dumper->describeValue($first) . + '] and [' . $dumper->describeValue($second) . + '] should not be the same object'); + $identical = &new IdenticalExpectation($first); + return $this->assertTrue( + $identical->test($second) && + ! SimpleTestCompatibility::isReference($first, $second), + $message); + } + + /** + * @deprecated + */ + function assertCopy(&$first, &$second, $message = "%s") { + $dumper = &new SimpleDumper(); + $message = sprintf( + $message, + "[" . $dumper->describeValue($first) . + "] and [" . $dumper->describeValue($second) . + "] should not be the same object"); + return $this->assertFalse( + SimpleTestCompatibility::isReference($first, $second), + $message); + } + + /** + * Will trigger a pass if the Perl regex pattern + * is found in the subject. Fail otherwise. + * @param string $pattern Perl regex to look for including + * the regex delimiters. + * @param string $subject String to search in. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertPattern($pattern, $subject, $message = '%s') { + return $this->assert( + new PatternExpectation($pattern), + $subject, + $message); + } + + /** + * @deprecated + */ + function assertWantedPattern($pattern, $subject, $message = '%s') { + return $this->assertPattern($pattern, $subject, $message); + } + + /** + * Will trigger a pass if the perl regex pattern + * is not present in subject. Fail if found. + * @param string $pattern Perl regex to look for including + * the regex delimiters. + * @param string $subject String to search in. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertNoPattern($pattern, $subject, $message = '%s') { + return $this->assert( + new NoPatternExpectation($pattern), + $subject, + $message); + } + + /** + * @deprecated + */ + function assertNoUnwantedPattern($pattern, $subject, $message = '%s') { + return $this->assertNoPattern($pattern, $subject, $message); + } + + /** + * @deprecated + */ + function swallowErrors() { + $context = &SimpleTest::getContext(); + $queue = &$context->get('SimpleErrorQueue'); + $queue->clear(); + } + + /** + * @deprecated + */ + function assertNoErrors($message = '%s') { + $context = &SimpleTest::getContext(); + $queue = &$context->get('SimpleErrorQueue'); + return $queue->assertNoErrors($message); + } + + /** + * @deprecated + */ + function assertError($expected = false, $message = '%s') { + $context = &SimpleTest::getContext(); + $queue = &$context->get('SimpleErrorQueue'); + return $queue->assertError($this->_coerceExpectation($expected), $message); + } + + /** + * Prepares for an error. If the error mismatches it + * passes through, otherwise it is swallowed. Any + * left over errors trigger failures. + * @param SimpleExpectation/string $expected The error to match. + * @param string $message Message on failure. + * @access public + */ + function expectError($expected = false, $message = '%s') { + $context = &SimpleTest::getContext(); + $queue = &$context->get('SimpleErrorQueue'); + $queue->expectError($this->_coerceExpectation($expected), $message); + } + + /** + * Prepares for an exception. If the error mismatches it + * passes through, otherwise it is swallowed. Any + * left over errors trigger failures. + * @param SimpleExpectation/Exception $expected The error to match. + * @param string $message Message on failure. + * @access public + */ + function expectException($expected = false, $message = '%s') { + $context = &SimpleTest::getContext(); + $queue = &$context->get('SimpleExceptionTrap'); + // :HACK: Directly substituting in seems to cause a segfault with + // Zend Optimizer on some systems + $line = $this->getAssertionLine(); + $queue->expectException($expected, $message . $line); + } + + /** + * Creates an equality expectation if the + * object/value is not already some type + * of expectation. + * @param mixed $expected Expected value. + * @return SimpleExpectation Expectation object. + * @access private + */ + function _coerceExpectation($expected) { + if ($expected == false) { + return new TrueExpectation(); + } + if (SimpleTestCompatibility::isA($expected, 'SimpleExpectation')) { + return $expected; + } + return new EqualExpectation( + is_string($expected) ? str_replace('%', '%%', $expected) : $expected); + } + + /** + * @deprecated + */ + function assertErrorPattern($pattern, $message = '%s') { + return $this->assertError(new PatternExpectation($pattern), $message); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/url.php b/plugins/www/testgen4web_simpletest/lib/simpletest/url.php new file mode 100644 index 0000000..0ea2204 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/url.php @@ -0,0 +1,528 @@ +_chompCoordinates($url); + $this->setCoordinates($x, $y); + $this->_scheme = $this->_chompScheme($url); + list($this->_username, $this->_password) = $this->_chompLogin($url); + $this->_host = $this->_chompHost($url); + $this->_port = false; + if (preg_match('/(.*?):(.*)/', $this->_host, $host_parts)) { + $this->_host = $host_parts[1]; + $this->_port = (integer)$host_parts[2]; + } + $this->_path = $this->_chompPath($url); + $this->_request = $this->_parseRequest($this->_chompRequest($url)); + $this->_fragment = (strncmp($url, "#", 1) == 0 ? substr($url, 1) : false); + $this->_target = false; + } + + /** + * Extracts the X, Y coordinate pair from an image map. + * @param string $url URL so far. The coordinates will be + * removed. + * @return array X, Y as a pair of integers. + * @access private + */ + function _chompCoordinates(&$url) { + if (preg_match('/(.*)\?(\d+),(\d+)$/', $url, $matches)) { + $url = $matches[1]; + return array((integer)$matches[2], (integer)$matches[3]); + } + return array(false, false); + } + + /** + * Extracts the scheme part of an incoming URL. + * @param string $url URL so far. The scheme will be + * removed. + * @return string Scheme part or false. + * @access private + */ + function _chompScheme(&$url) { + if (preg_match('/^([^\/:]*):(\/\/)(.*)/', $url, $matches)) { + $url = $matches[2] . $matches[3]; + return $matches[1]; + } + return false; + } + + /** + * Extracts the username and password from the + * incoming URL. The // prefix will be reattached + * to the URL after the doublet is extracted. + * @param string $url URL so far. The username and + * password are removed. + * @return array Two item list of username and + * password. Will urldecode() them. + * @access private + */ + function _chompLogin(&$url) { + $prefix = ''; + if (preg_match('/^(\/\/)(.*)/', $url, $matches)) { + $prefix = $matches[1]; + $url = $matches[2]; + } + if (preg_match('/^([^\/]*)@(.*)/', $url, $matches)) { + $url = $prefix . $matches[2]; + $parts = split(":", $matches[1]); + return array( + urldecode($parts[0]), + isset($parts[1]) ? urldecode($parts[1]) : false); + } + $url = $prefix . $url; + return array(false, false); + } + + /** + * Extracts the host part of an incoming URL. + * Includes the port number part. Will extract + * the host if it starts with // or it has + * a top level domain or it has at least two + * dots. + * @param string $url URL so far. The host will be + * removed. + * @return string Host part guess or false. + * @access private + */ + function _chompHost(&$url) { + if (preg_match('/^(\/\/)(.*?)(\/.*|\?.*|#.*|$)/', $url, $matches)) { + $url = $matches[3]; + return $matches[2]; + } + if (preg_match('/(.*?)(\.\.\/|\.\/|\/|\?|#|$)(.*)/', $url, $matches)) { + $tlds = SimpleUrl::getAllTopLevelDomains(); + if (preg_match('/[a-z0-9\-]+\.(' . $tlds . ')/i', $matches[1])) { + $url = $matches[2] . $matches[3]; + return $matches[1]; + } elseif (preg_match('/[a-z0-9\-]+\.[a-z0-9\-]+\.[a-z0-9\-]+/i', $matches[1])) { + $url = $matches[2] . $matches[3]; + return $matches[1]; + } + } + return false; + } + + /** + * Extracts the path information from the incoming + * URL. Strips this path from the URL. + * @param string $url URL so far. The host will be + * removed. + * @return string Path part or '/'. + * @access private + */ + function _chompPath(&$url) { + if (preg_match('/(.*?)(\?|#|$)(.*)/', $url, $matches)) { + $url = $matches[2] . $matches[3]; + return ($matches[1] ? $matches[1] : ''); + } + return ''; + } + + /** + * Strips off the request data. + * @param string $url URL so far. The request will be + * removed. + * @return string Raw request part. + * @access private + */ + function _chompRequest(&$url) { + if (preg_match('/\?(.*?)(#|$)(.*)/', $url, $matches)) { + $url = $matches[2] . $matches[3]; + return $matches[1]; + } + return ''; + } + + /** + * Breaks the request down into an object. + * @param string $raw Raw request. + * @return SimpleFormEncoding Parsed data. + * @access private + */ + function _parseRequest($raw) { + $this->_raw = $raw; + $request = new SimpleGetEncoding(); + foreach (split("&", $raw) as $pair) { + if (preg_match('/(.*?)=(.*)/', $pair, $matches)) { + $request->add($matches[1], urldecode($matches[2])); + } elseif ($pair) { + $request->add($pair, ''); + } + } + return $request; + } + + /** + * Accessor for protocol part. + * @param string $default Value to use if not present. + * @return string Scheme name, e.g "http". + * @access public + */ + function getScheme($default = false) { + return $this->_scheme ? $this->_scheme : $default; + } + + /** + * Accessor for user name. + * @return string Username preceding host. + * @access public + */ + function getUsername() { + return $this->_username; + } + + /** + * Accessor for password. + * @return string Password preceding host. + * @access public + */ + function getPassword() { + return $this->_password; + } + + /** + * Accessor for hostname and port. + * @param string $default Value to use if not present. + * @return string Hostname only. + * @access public + */ + function getHost($default = false) { + return $this->_host ? $this->_host : $default; + } + + /** + * Accessor for top level domain. + * @return string Last part of host. + * @access public + */ + function getTld() { + $path_parts = pathinfo($this->getHost()); + return (isset($path_parts['extension']) ? $path_parts['extension'] : false); + } + + /** + * Accessor for port number. + * @return integer TCP/IP port number. + * @access public + */ + function getPort() { + return $this->_port; + } + + /** + * Accessor for path. + * @return string Full path including leading slash if implied. + * @access public + */ + function getPath() { + if (! $this->_path && $this->_host) { + return '/'; + } + return $this->_path; + } + + /** + * Accessor for page if any. This may be a + * directory name if ambiguious. + * @return Page name. + * @access public + */ + function getPage() { + if (! preg_match('/([^\/]*?)$/', $this->getPath(), $matches)) { + return false; + } + return $matches[1]; + } + + /** + * Gets the path to the page. + * @return string Path less the page. + * @access public + */ + function getBasePath() { + if (! preg_match('/(.*\/)[^\/]*?$/', $this->getPath(), $matches)) { + return false; + } + return $matches[1]; + } + + /** + * Accessor for fragment at end of URL after the "#". + * @return string Part after "#". + * @access public + */ + function getFragment() { + return $this->_fragment; + } + + /** + * Sets image coordinates. Set to false to clear + * them. + * @param integer $x Horizontal position. + * @param integer $y Vertical position. + * @access public + */ + function setCoordinates($x = false, $y = false) { + if (($x === false) || ($y === false)) { + $this->_x = $this->_y = false; + return; + } + $this->_x = (integer)$x; + $this->_y = (integer)$y; + } + + /** + * Accessor for horizontal image coordinate. + * @return integer X value. + * @access public + */ + function getX() { + return $this->_x; + } + + /** + * Accessor for vertical image coordinate. + * @return integer Y value. + * @access public + */ + function getY() { + return $this->_y; + } + + /** + * Accessor for current request parameters + * in URL string form. Will return teh original request + * if at all possible even if it doesn't make much + * sense. + * @return string Form is string "?a=1&b=2", etc. + * @access public + */ + function getEncodedRequest() { + if ($this->_raw) { + $encoded = $this->_raw; + } else { + $encoded = $this->_request->asUrlRequest(); + } + if ($encoded) { + return '?' . preg_replace('/^\?/', '', $encoded); + } + return ''; + } + + /** + * Adds an additional parameter to the request. + * @param string $key Name of parameter. + * @param string $value Value as string. + * @access public + */ + function addRequestParameter($key, $value) { + $this->_raw = false; + $this->_request->add($key, $value); + } + + /** + * Adds additional parameters to the request. + * @param hash/SimpleFormEncoding $parameters Additional + * parameters. + * @access public + */ + function addRequestParameters($parameters) { + $this->_raw = false; + $this->_request->merge($parameters); + } + + /** + * Clears down all parameters. + * @access public + */ + function clearRequest() { + $this->_raw = false; + $this->_request = &new SimpleGetEncoding(); + } + + /** + * Gets the frame target if present. Although + * not strictly part of the URL specification it + * acts as similarily to the browser. + * @return boolean/string Frame name or false if none. + * @access public + */ + function getTarget() { + return $this->_target; + } + + /** + * Attaches a frame target. + * @param string $frame Name of frame. + * @access public + */ + function setTarget($frame) { + $this->_raw = false; + $this->_target = $frame; + } + + /** + * Renders the URL back into a string. + * @return string URL in canonical form. + * @access public + */ + function asString() { + $path = $this->_path; + $scheme = $identity = $host = $encoded = $fragment = ''; + if ($this->_username && $this->_password) { + $identity = $this->_username . ':' . $this->_password . '@'; + } + if ($this->getHost()) { + $scheme = $this->getScheme() ? $this->getScheme() : 'http'; + $scheme .= "://"; + $host = $this->getHost(); + } + if (substr($this->_path, 0, 1) == '/') { + $path = $this->normalisePath($this->_path); + } + $encoded = $this->getEncodedRequest(); + $fragment = $this->getFragment() ? '#'. $this->getFragment() : ''; + $coords = $this->getX() === false ? '' : '?' . $this->getX() . ',' . $this->getY(); + return "$scheme$identity$host$path$encoded$fragment$coords"; + } + + /** + * Replaces unknown sections to turn a relative + * URL into an absolute one. The base URL can + * be either a string or a SimpleUrl object. + * @param string/SimpleUrl $base Base URL. + * @access public + */ + function makeAbsolute($base) { + if (! is_object($base)) { + $base = new SimpleUrl($base); + } + if ($this->getHost()) { + $scheme = $this->getScheme(); + $host = $this->getHost(); + $port = $this->getPort() ? ':' . $this->getPort() : ''; + $identity = $this->getIdentity() ? $this->getIdentity() . '@' : ''; + if (! $identity) { + $identity = $base->getIdentity() ? $base->getIdentity() . '@' : ''; + } + } else { + $scheme = $base->getScheme(); + $host = $base->getHost(); + $port = $base->getPort() ? ':' . $base->getPort() : ''; + $identity = $base->getIdentity() ? $base->getIdentity() . '@' : ''; + } + $path = $this->normalisePath($this->_extractAbsolutePath($base)); + $encoded = $this->getEncodedRequest(); + $fragment = $this->getFragment() ? '#'. $this->getFragment() : ''; + $coords = $this->getX() === false ? '' : '?' . $this->getX() . ',' . $this->getY(); + return new SimpleUrl("$scheme://$identity$host$port$path$encoded$fragment$coords"); + } + + /** + * Replaces unknown sections of the path with base parts + * to return a complete absolute one. + * @param string/SimpleUrl $base Base URL. + * @param string Absolute path. + * @access private + */ + function _extractAbsolutePath($base) { + if ($this->getHost()) { + return $this->_path; + } + if (! $this->_isRelativePath($this->_path)) { + return $this->_path; + } + if ($this->_path) { + return $base->getBasePath() . $this->_path; + } + return $base->getPath(); + } + + /** + * Simple test to see if a path part is relative. + * @param string $path Path to test. + * @return boolean True if starts with a "/". + * @access private + */ + function _isRelativePath($path) { + return (substr($path, 0, 1) != '/'); + } + + /** + * Extracts the username and password for use in rendering + * a URL. + * @return string/boolean Form of username:password or false. + * @access public + */ + function getIdentity() { + if ($this->_username && $this->_password) { + return $this->_username . ':' . $this->_password; + } + return false; + } + + /** + * Replaces . and .. sections of the path. + * @param string $path Unoptimised path. + * @return string Path with dots removed if possible. + * @access public + */ + function normalisePath($path) { + $path = preg_replace('|/\./|', '/', $path); + return preg_replace('|/[^/]+/\.\./|', '/', $path); + } + + /** + * A pipe seperated list of all TLDs that result in two part + * domain names. + * @return string Pipe separated list. + * @access public + * @static + */ + function getAllTopLevelDomains() { + return 'com|edu|net|org|gov|mil|int|biz|info|name|pro|aero|coop|museum'; + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/user_agent.php b/plugins/www/testgen4web_simpletest/lib/simpletest/user_agent.php new file mode 100644 index 0000000..b3f6f05 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/user_agent.php @@ -0,0 +1,332 @@ +_cookie_jar = &new SimpleCookieJar(); + $this->_authenticator = &new SimpleAuthenticator(); + } + + /** + * Removes expired and temporary cookies as if + * the browser was closed and re-opened. Authorisation + * has to be obtained again as well. + * @param string/integer $date Time when session restarted. + * If omitted then all persistent + * cookies are kept. + * @access public + */ + function restart($date = false) { + $this->_cookie_jar->restartSession($date); + $this->_authenticator->restartSession(); + } + + /** + * Adds a header to every fetch. + * @param string $header Header line to add to every + * request until cleared. + * @access public + */ + function addHeader($header) { + $this->_additional_headers[] = $header; + } + + /** + * Ages the cookies by the specified time. + * @param integer $interval Amount in seconds. + * @access public + */ + function ageCookies($interval) { + $this->_cookie_jar->agePrematurely($interval); + } + + /** + * Sets an additional cookie. If a cookie has + * the same name and path it is replaced. + * @param string $name Cookie key. + * @param string $value Value of cookie. + * @param string $host Host upon which the cookie is valid. + * @param string $path Cookie path if not host wide. + * @param string $expiry Expiry date. + * @access public + */ + function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { + $this->_cookie_jar->setCookie($name, $value, $host, $path, $expiry); + } + + /** + * Reads the most specific cookie value from the + * browser cookies. + * @param string $host Host to search. + * @param string $path Applicable path. + * @param string $name Name of cookie to read. + * @return string False if not present, else the + * value as a string. + * @access public + */ + function getCookieValue($host, $path, $name) { + return $this->_cookie_jar->getCookieValue($host, $path, $name); + } + + /** + * Reads the current cookies within the base URL. + * @param string $name Key of cookie to find. + * @param SimpleUrl $base Base URL to search from. + * @return string/boolean Null if there is no base URL, false + * if the cookie is not set. + * @access public + */ + function getBaseCookieValue($name, $base) { + if (! $base) { + return null; + } + return $this->getCookieValue($base->getHost(), $base->getPath(), $name); + } + + /** + * Switches off cookie sending and recieving. + * @access public + */ + function ignoreCookies() { + $this->_cookies_enabled = false; + } + + /** + * Switches back on the cookie sending and recieving. + * @access public + */ + function useCookies() { + $this->_cookies_enabled = true; + } + + /** + * Sets the socket timeout for opening a connection. + * @param integer $timeout Maximum time in seconds. + * @access public + */ + function setConnectionTimeout($timeout) { + $this->_connection_timeout = $timeout; + } + + /** + * Sets the maximum number of redirects before + * a page will be loaded anyway. + * @param integer $max Most hops allowed. + * @access public + */ + function setMaximumRedirects($max) { + $this->_max_redirects = $max; + } + + /** + * Sets proxy to use on all requests for when + * testing from behind a firewall. Set URL + * to false to disable. + * @param string $proxy Proxy URL. + * @param string $username Proxy username for authentication. + * @param string $password Proxy password for authentication. + * @access public + */ + function useProxy($proxy, $username, $password) { + if (! $proxy) { + $this->_proxy = false; + return; + } + if ((strncmp($proxy, 'http://', 7) != 0) && (strncmp($proxy, 'https://', 8) != 0)) { + $proxy = 'http://'. $proxy; + } + $this->_proxy = &new SimpleUrl($proxy); + $this->_proxy_username = $username; + $this->_proxy_password = $password; + } + + /** + * Test to see if the redirect limit is passed. + * @param integer $redirects Count so far. + * @return boolean True if over. + * @access private + */ + function _isTooManyRedirects($redirects) { + return ($redirects > $this->_max_redirects); + } + + /** + * Sets the identity for the current realm. + * @param string $host Host to which realm applies. + * @param string $realm Full name of realm. + * @param string $username Username for realm. + * @param string $password Password for realm. + * @access public + */ + function setIdentity($host, $realm, $username, $password) { + $this->_authenticator->setIdentityForRealm($host, $realm, $username, $password); + } + + /** + * Fetches a URL as a response object. Will keep trying if redirected. + * It will also collect authentication realm information. + * @param string/SimpleUrl $url Target to fetch. + * @param SimpleEncoding $encoding Additional parameters for request. + * @return SimpleHttpResponse Hopefully the target page. + * @access public + */ + function &fetchResponse($url, $encoding) { + if ($encoding->getMethod() != 'POST') { + $url->addRequestParameters($encoding); + $encoding->clear(); + } + $response = &$this->_fetchWhileRedirected($url, $encoding); + if ($headers = $response->getHeaders()) { + if ($headers->isChallenge()) { + $this->_authenticator->addRealm( + $url, + $headers->getAuthentication(), + $headers->getRealm()); + } + } + return $response; + } + + /** + * Fetches the page until no longer redirected or + * until the redirect limit runs out. + * @param SimpleUrl $url Target to fetch. + * @param SimpelFormEncoding $encoding Additional parameters for request. + * @return SimpleHttpResponse Hopefully the target page. + * @access private + */ + function &_fetchWhileRedirected($url, $encoding) { + $redirects = 0; + do { + $response = &$this->_fetch($url, $encoding); + if ($response->isError()) { + return $response; + } + $headers = $response->getHeaders(); + $location = new SimpleUrl($headers->getLocation()); + $url = $location->makeAbsolute($url); + if ($this->_cookies_enabled) { + $headers->writeCookiesToJar($this->_cookie_jar, $url); + } + if (! $headers->isRedirect()) { + break; + } + $encoding = new SimpleGetEncoding(); + } while (! $this->_isTooManyRedirects(++$redirects)); + return $response; + } + + /** + * Actually make the web request. + * @param SimpleUrl $url Target to fetch. + * @param SimpleFormEncoding $encoding Additional parameters for request. + * @return SimpleHttpResponse Headers and hopefully content. + * @access protected + */ + function &_fetch($url, $encoding) { + $request = &$this->_createRequest($url, $encoding); + $response = &$request->fetch($this->_connection_timeout); + return $response; + } + + /** + * Creates a full page request. + * @param SimpleUrl $url Target to fetch as url object. + * @param SimpleFormEncoding $encoding POST/GET parameters. + * @return SimpleHttpRequest New request. + * @access private + */ + function &_createRequest($url, $encoding) { + $request = &$this->_createHttpRequest($url, $encoding); + $this->_addAdditionalHeaders($request); + if ($this->_cookies_enabled) { + $request->readCookiesFromJar($this->_cookie_jar, $url); + } + $this->_authenticator->addHeaders($request, $url); + return $request; + } + + /** + * Builds the appropriate HTTP request object. + * @param SimpleUrl $url Target to fetch as url object. + * @param SimpleFormEncoding $parameters POST/GET parameters. + * @return SimpleHttpRequest New request object. + * @access protected + */ + function &_createHttpRequest($url, $encoding) { + $request = &new SimpleHttpRequest($this->_createRoute($url), $encoding); + return $request; + } + + /** + * Sets up either a direct route or via a proxy. + * @param SimpleUrl $url Target to fetch as url object. + * @return SimpleRoute Route to take to fetch URL. + * @access protected + */ + function &_createRoute($url) { + if ($this->_proxy) { + $route = &new SimpleProxyRoute( + $url, + $this->_proxy, + $this->_proxy_username, + $this->_proxy_password); + } else { + $route = &new SimpleRoute($url); + } + return $route; + } + + /** + * Adds additional manual headers. + * @param SimpleHttpRequest $request Outgoing request. + * @access private + */ + function _addAdditionalHeaders(&$request) { + foreach ($this->_additional_headers as $header) { + $request->addHeaderLine($header); + } + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/web_tester.php b/plugins/www/testgen4web_simpletest/lib/simpletest/web_tester.php new file mode 100644 index 0000000..40b1612 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/web_tester.php @@ -0,0 +1,1541 @@ +SimpleExpectation($message); + if (is_array($value)) { + sort($value); + } + $this->_value = $value; + } + + /** + * Tests the expectation. True if it matches + * a string value or an array value in any order. + * @param mixed $compare Comparison value. False for + * an unset field. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + if ($this->_value === false) { + return ($compare === false); + } + if ($this->_isSingle($this->_value)) { + return $this->_testSingle($compare); + } + if (is_array($this->_value)) { + return $this->_testMultiple($compare); + } + return false; + } + + /** + * Tests for valid field comparisons with a single option. + * @param mixed $value Value to type check. + * @return boolean True if integer, string or float. + * @access private + */ + function _isSingle($value) { + return is_string($value) || is_integer($value) || is_float($value); + } + + /** + * String comparison for simple field with a single option. + * @param mixed $compare String to test against. + * @returns boolean True if matching. + * @access private + */ + function _testSingle($compare) { + if (is_array($compare) && count($compare) == 1) { + $compare = $compare[0]; + } + if (! $this->_isSingle($compare)) { + return false; + } + return ($this->_value == $compare); + } + + /** + * List comparison for multivalue field. + * @param mixed $compare List in any order to test against. + * @returns boolean True if matching. + * @access private + */ + function _testMultiple($compare) { + if (is_string($compare)) { + $compare = array($compare); + } + if (! is_array($compare)) { + return false; + } + sort($compare); + return ($this->_value === $compare); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $dumper = &$this->_getDumper(); + if (is_array($compare)) { + sort($compare); + } + if ($this->test($compare)) { + return "Field expectation [" . $dumper->describeValue($this->_value) . "]"; + } else { + return "Field expectation [" . $dumper->describeValue($this->_value) . + "] fails with [" . + $dumper->describeValue($compare) . "] " . + $dumper->describeDifference($this->_value, $compare); + } + } +} + +/** + * Test for a specific HTTP header within a header block. + * @package SimpleTest + * @subpackage WebTester + */ +class HttpHeaderExpectation extends SimpleExpectation { + var $_expected_header; + var $_expected_value; + + /** + * Sets the field and value to compare against. + * @param string $header Case insenstive trimmed header name. + * @param mixed $value Optional value to compare. If not + * given then any value will match. If + * an expectation object then that will + * be used instead. + * @param string $message Optiona message override. Can use %s as + * a placeholder for the original message. + */ + function HttpHeaderExpectation($header, $value = false, $message = '%s') { + $this->SimpleExpectation($message); + $this->_expected_header = $this->_normaliseHeader($header); + $this->_expected_value = $value; + } + + /** + * Accessor for aggregated object. + * @return mixed Expectation set in constructor. + * @access protected + */ + function _getExpectation() { + return $this->_expected_value; + } + + /** + * Removes whitespace at ends and case variations. + * @param string $header Name of header. + * @param string Trimmed and lowecased header + * name. + * @access private + */ + function _normaliseHeader($header) { + return strtolower(trim($header)); + } + + /** + * Tests the expectation. True if it matches + * a string value or an array value in any order. + * @param mixed $compare Raw header block to search. + * @return boolean True if header present. + * @access public + */ + function test($compare) { + return is_string($this->_findHeader($compare)); + } + + /** + * Searches the incoming result. Will extract the matching + * line as text. + * @param mixed $compare Raw header block to search. + * @return string Matching header line. + * @access protected + */ + function _findHeader($compare) { + $lines = split("\r\n", $compare); + foreach ($lines as $line) { + if ($this->_testHeaderLine($line)) { + return $line; + } + } + return false; + } + + /** + * Compares a single header line against the expectation. + * @param string $line A single line to compare. + * @return boolean True if matched. + * @access private + */ + function _testHeaderLine($line) { + if (count($parsed = split(':', $line, 2)) < 2) { + return false; + } + list($header, $value) = $parsed; + if ($this->_normaliseHeader($header) != $this->_expected_header) { + return false; + } + return $this->_testHeaderValue($value, $this->_expected_value); + } + + /** + * Tests the value part of the header. + * @param string $value Value to test. + * @param mixed $expected Value to test against. + * @return boolean True if matched. + * @access protected + */ + function _testHeaderValue($value, $expected) { + if ($expected === false) { + return true; + } + if (SimpleExpectation::isExpectation($expected)) { + return $expected->test(trim($value)); + } + return (trim($value) == trim($expected)); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Raw header block to search. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if (SimpleExpectation::isExpectation($this->_expected_value)) { + $message = $this->_expected_value->overlayMessage($compare, $this->_getDumper()); + } else { + $message = $this->_expected_header . + ($this->_expected_value ? ': ' . $this->_expected_value : ''); + } + if (is_string($line = $this->_findHeader($compare))) { + return "Searching for header [$message] found [$line]"; + } else { + return "Failed to find header [$message]"; + } + } +} + +/** + * Test for a specific HTTP header within a header block that + * should not be found. + * @package SimpleTest + * @subpackage WebTester + */ +class NoHttpHeaderExpectation extends HttpHeaderExpectation { + var $_expected_header; + var $_expected_value; + + /** + * Sets the field and value to compare against. + * @param string $unwanted Case insenstive trimmed header name. + * @param string $message Optiona message override. Can use %s as + * a placeholder for the original message. + */ + function NoHttpHeaderExpectation($unwanted, $message = '%s') { + $this->HttpHeaderExpectation($unwanted, false, $message); + } + + /** + * Tests that the unwanted header is not found. + * @param mixed $compare Raw header block to search. + * @return boolean True if header present. + * @access public + */ + function test($compare) { + return ($this->_findHeader($compare) === false); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Raw header block to search. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + $expectation = $this->_getExpectation(); + if (is_string($line = $this->_findHeader($compare))) { + return "Found unwanted header [$expectation] with [$line]"; + } else { + return "Did not find unwanted header [$expectation]"; + } + } +} + +/** + * Test for a text substring. + * @package SimpleTest + * @subpackage UnitTester + */ +class TextExpectation extends SimpleExpectation { + var $_substring; + + /** + * Sets the value to compare against. + * @param string $substring Text to search for. + * @param string $message Customised message on failure. + * @access public + */ + function TextExpectation($substring, $message = '%s') { + $this->SimpleExpectation($message); + $this->_substring = $substring; + } + + /** + * Accessor for the substring. + * @return string Text to match. + * @access protected + */ + function _getSubstring() { + return $this->_substring; + } + + /** + * Tests the expectation. True if the text contains the + * substring. + * @param string $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return (strpos($compare, $this->_substring) !== false); + } + + /** + * Returns a human readable test message. + * @param mixed $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + return $this->_describeTextMatch($this->_getSubstring(), $compare); + } else { + $dumper = &$this->_getDumper(); + return "Text [" . $this->_getSubstring() . + "] not detected in [" . + $dumper->describeValue($compare) . "]"; + } + } + + /** + * Describes a pattern match including the string + * found and it's position. + * @param string $substring Text to search for. + * @param string $subject Subject to search. + * @access protected + */ + function _describeTextMatch($substring, $subject) { + $position = strpos($subject, $substring); + $dumper = &$this->_getDumper(); + return "Text [$substring] detected at character [$position] in [" . + $dumper->describeValue($subject) . "] in region [" . + $dumper->clipString($subject, 100, $position) . "]"; + } +} + +/** + * Fail if a substring is detected within the + * comparison text. + * @package SimpleTest + * @subpackage UnitTester + */ +class NoTextExpectation extends TextExpectation { + + /** + * Sets the reject pattern + * @param string $substring Text to search for. + * @param string $message Customised message on failure. + * @access public + */ + function NoTextExpectation($substring, $message = '%s') { + $this->TextExpectation($substring, $message); + } + + /** + * Tests the expectation. False if the substring appears + * in the text. + * @param string $compare Comparison value. + * @return boolean True if correct. + * @access public + */ + function test($compare) { + return ! parent::test($compare); + } + + /** + * Returns a human readable test message. + * @param string $compare Comparison value. + * @return string Description of success + * or failure. + * @access public + */ + function testMessage($compare) { + if ($this->test($compare)) { + $dumper = &$this->_getDumper(); + return "Text [" . $this->_getSubstring() . + "] not detected in [" . + $dumper->describeValue($compare) . "]"; + } else { + return $this->_describeTextMatch($this->_getSubstring(), $compare); + } + } +} + +/** + * Test case for testing of web pages. Allows + * fetching of pages, parsing of HTML and + * submitting forms. + * @package SimpleTest + * @subpackage WebTester + */ +class WebTestCase extends SimpleTestCase { + var $_browser; + var $_ignore_errors = false; + + /** + * Creates an empty test case. Should be subclassed + * with test methods for a functional test case. + * @param string $label Name of test case. Will use + * the class name if none specified. + * @access public + */ + function WebTestCase($label = false) { + $this->SimpleTestCase($label); + } + + /** + * Announces the start of the test. + * @param string $method Test method just started. + * @access public + */ + function before($method) { + parent::before($method); + $this->setBrowser($this->createBrowser()); + } + + /** + * Announces the end of the test. Includes private clean up. + * @param string $method Test method just finished. + * @access public + */ + function after($method) { + $this->unsetBrowser(); + parent::after($method); + } + + /** + * Gets a current browser reference for setting + * special expectations or for detailed + * examination of page fetches. + * @return SimpleBrowser Current test browser object. + * @access public + */ + function &getBrowser() { + return $this->_browser; + } + + /** + * Gets a current browser reference for setting + * special expectations or for detailed + * examination of page fetches. + * @param SimpleBrowser $browser New test browser object. + * @access public + */ + function setBrowser(&$browser) { + return $this->_browser = &$browser; + } + + /** + * Clears the current browser reference to help the + * PHP garbage collector. + * @access public + */ + function unsetBrowser() { + unset($this->_browser); + } + + /** + * Creates a new default web browser object. + * Will be cleared at the end of the test method. + * @return TestBrowser New browser. + * @access public + */ + function &createBrowser() { + $browser = &new SimpleBrowser(); + return $browser; + } + + /** + * Gets the last response error. + * @return string Last low level HTTP error. + * @access public + */ + function getTransportError() { + return $this->_browser->getTransportError(); + } + + /** + * Accessor for the currently selected URL. + * @return string Current location or false if + * no page yet fetched. + * @access public + */ + function getUrl() { + return $this->_browser->getUrl(); + } + + /** + * Dumps the current request for debugging. + * @access public + */ + function showRequest() { + $this->dump($this->_browser->getRequest()); + } + + /** + * Dumps the current HTTP headers for debugging. + * @access public + */ + function showHeaders() { + $this->dump($this->_browser->getHeaders()); + } + + /** + * Dumps the current HTML source for debugging. + * @access public + */ + function showSource() { + $this->dump($this->_browser->getContent()); + } + + /** + * Dumps the visible text only for debugging. + * @access public + */ + function showText() { + $this->dump(wordwrap($this->_browser->getContentAsText(), 80)); + } + + /** + * Simulates the closing and reopening of the browser. + * Temporary cookies will be discarded and timed + * cookies will be expired if later than the + * specified time. + * @param string/integer $date Time when session restarted. + * If ommitted then all persistent + * cookies are kept. Time is either + * Cookie format string or timestamp. + * @access public + */ + function restart($date = false) { + if ($date === false) { + $date = time(); + } + $this->_browser->restart($date); + } + + /** + * Moves cookie expiry times back into the past. + * Useful for testing timeouts and expiries. + * @param integer $interval Amount to age in seconds. + * @access public + */ + function ageCookies($interval) { + $this->_browser->ageCookies($interval); + } + + /** + * Disables frames support. Frames will not be fetched + * and the frameset page will be used instead. + * @access public + */ + function ignoreFrames() { + $this->_browser->ignoreFrames(); + } + + /** + * Switches off cookie sending and recieving. + * @access public + */ + function ignoreCookies() { + $this->_browser->ignoreCookies(); + } + + /** + * Skips errors for the next request only. You might + * want to confirm that a page is unreachable for + * example. + * @access public + */ + function ignoreErrors() { + $this->_ignore_errors = true; + } + + /** + * Issues a fail if there is a transport error anywhere + * in the current frameset. Only one such error is + * reported. + * @param string/boolean $result HTML or failure. + * @return string/boolean $result Passes through result. + * @access private + */ + function _failOnError($result) { + if (! $this->_ignore_errors) { + if ($error = $this->_browser->getTransportError()) { + $this->fail($error); + } + } + $this->_ignore_errors = false; + return $result; + } + + /** + * Adds a header to every fetch. + * @param string $header Header line to add to every + * request until cleared. + * @access public + */ + function addHeader($header) { + $this->_browser->addHeader($header); + } + + /** + * Sets the maximum number of redirects before + * the web page is loaded regardless. + * @param integer $max Maximum hops. + * @access public + */ + function setMaximumRedirects($max) { + if (! $this->_browser) { + trigger_error( + 'Can only set maximum redirects in a test method, setUp() or tearDown()'); + } + $this->_browser->setMaximumRedirects($max); + } + + /** + * Sets the socket timeout for opening a connection and + * receiving at least one byte of information. + * @param integer $timeout Maximum time in seconds. + * @access public + */ + function setConnectionTimeout($timeout) { + $this->_browser->setConnectionTimeout($timeout); + } + + /** + * Sets proxy to use on all requests for when + * testing from behind a firewall. Set URL + * to false to disable. + * @param string $proxy Proxy URL. + * @param string $username Proxy username for authentication. + * @param string $password Proxy password for authentication. + * @access public + */ + function useProxy($proxy, $username = false, $password = false) { + $this->_browser->useProxy($proxy, $username, $password); + } + + /** + * Fetches a page into the page buffer. If + * there is no base for the URL then the + * current base URL is used. After the fetch + * the base URL reflects the new location. + * @param string $url URL to fetch. + * @param hash $parameters Optional additional GET data. + * @return boolean/string Raw page on success. + * @access public + */ + function get($url, $parameters = false) { + return $this->_failOnError($this->_browser->get($url, $parameters)); + } + + /** + * Fetches a page by POST into the page buffer. + * If there is no base for the URL then the + * current base URL is used. After the fetch + * the base URL reflects the new location. + * @param string $url URL to fetch. + * @param hash $parameters Optional additional GET data. + * @return boolean/string Raw page on success. + * @access public + */ + function post($url, $parameters = false) { + return $this->_failOnError($this->_browser->post($url, $parameters)); + } + + /** + * Does a HTTP HEAD fetch, fetching only the page + * headers. The current base URL is unchanged by this. + * @param string $url URL to fetch. + * @param hash $parameters Optional additional GET data. + * @return boolean True on success. + * @access public + */ + function head($url, $parameters = false) { + return $this->_failOnError($this->_browser->head($url, $parameters)); + } + + /** + * Equivalent to hitting the retry button on the + * browser. Will attempt to repeat the page fetch. + * @return boolean True if fetch succeeded. + * @access public + */ + function retry() { + return $this->_failOnError($this->_browser->retry()); + } + + /** + * Equivalent to hitting the back button on the + * browser. + * @return boolean True if history entry and + * fetch succeeded. + * @access public + */ + function back() { + return $this->_failOnError($this->_browser->back()); + } + + /** + * Equivalent to hitting the forward button on the + * browser. + * @return boolean True if history entry and + * fetch succeeded. + * @access public + */ + function forward() { + return $this->_failOnError($this->_browser->forward()); + } + + /** + * Retries a request after setting the authentication + * for the current realm. + * @param string $username Username for realm. + * @param string $password Password for realm. + * @return boolean/string HTML on successful fetch. Note + * that authentication may still have + * failed. + * @access public + */ + function authenticate($username, $password) { + return $this->_failOnError( + $this->_browser->authenticate($username, $password)); + } + + /** + * Gets the cookie value for the current browser context. + * @param string $name Name of cookie. + * @return string Value of cookie or false if unset. + * @access public + */ + function getCookie($name) { + return $this->_browser->getCurrentCookieValue($name); + } + + /** + * Sets a cookie in the current browser. + * @param string $name Name of cookie. + * @param string $value Cookie value. + * @param string $host Host upon which the cookie is valid. + * @param string $path Cookie path if not host wide. + * @param string $expiry Expiry date. + * @access public + */ + function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { + $this->_browser->setCookie($name, $value, $host, $path, $expiry); + } + + /** + * Accessor for current frame focus. Will be + * false if no frame has focus. + * @return integer/string/boolean Label if any, otherwise + * the position in the frameset + * or false if none. + * @access public + */ + function getFrameFocus() { + return $this->_browser->getFrameFocus(); + } + + /** + * Sets the focus by index. The integer index starts from 1. + * @param integer $choice Chosen frame. + * @return boolean True if frame exists. + * @access public + */ + function setFrameFocusByIndex($choice) { + return $this->_browser->setFrameFocusByIndex($choice); + } + + /** + * Sets the focus by name. + * @param string $name Chosen frame. + * @return boolean True if frame exists. + * @access public + */ + function setFrameFocus($name) { + return $this->_browser->setFrameFocus($name); + } + + /** + * Clears the frame focus. All frames will be searched + * for content. + * @access public + */ + function clearFrameFocus() { + return $this->_browser->clearFrameFocus(); + } + + /** + * Clicks a visible text item. Will first try buttons, + * then links and then images. + * @param string $label Visible text or alt text. + * @return string/boolean Raw page or false. + * @access public + */ + function click($label) { + return $this->_failOnError($this->_browser->click($label)); + } + + /** + * Checks for a click target. + * @param string $label Visible text or alt text. + * @return boolean True if click target. + * @access public + */ + function assertClickable($label, $message = '%s') { + return $this->assertTrue( + $this->_browser->isClickable($label), + sprintf($message, "Click target [$label] should exist")); + } + + /** + * Clicks the submit button by label. The owning + * form will be submitted by this. + * @param string $label Button label. An unlabeled + * button can be triggered by 'Submit'. + * @param hash $additional Additional form values. + * @return boolean/string Page on success, else false. + * @access public + */ + function clickSubmit($label = 'Submit', $additional = false) { + return $this->_failOnError( + $this->_browser->clickSubmit($label, $additional)); + } + + /** + * Clicks the submit button by name attribute. The owning + * form will be submitted by this. + * @param string $name Name attribute of button. + * @param hash $additional Additional form values. + * @return boolean/string Page on success. + * @access public + */ + function clickSubmitByName($name, $additional = false) { + return $this->_failOnError( + $this->_browser->clickSubmitByName($name, $additional)); + } + + /** + * Clicks the submit button by ID attribute. The owning + * form will be submitted by this. + * @param string $id ID attribute of button. + * @param hash $additional Additional form values. + * @return boolean/string Page on success. + * @access public + */ + function clickSubmitById($id, $additional = false) { + return $this->_failOnError( + $this->_browser->clickSubmitById($id, $additional)); + } + + /** + * Checks for a valid button label. + * @param string $label Visible text. + * @return boolean True if click target. + * @access public + */ + function assertSubmit($label, $message = '%s') { + return $this->assertTrue( + $this->_browser->isSubmit($label), + sprintf($message, "Submit button [$label] should exist")); + } + + /** + * Clicks the submit image by some kind of label. Usually + * the alt tag or the nearest equivalent. The owning + * form will be submitted by this. Clicking outside of + * the boundary of the coordinates will result in + * a failure. + * @param string $label Alt attribute of button. + * @param integer $x X-coordinate of imaginary click. + * @param integer $y Y-coordinate of imaginary click. + * @param hash $additional Additional form values. + * @return boolean/string Page on success. + * @access public + */ + function clickImage($label, $x = 1, $y = 1, $additional = false) { + return $this->_failOnError( + $this->_browser->clickImage($label, $x, $y, $additional)); + } + + /** + * Clicks the submit image by the name. Usually + * the alt tag or the nearest equivalent. The owning + * form will be submitted by this. Clicking outside of + * the boundary of the coordinates will result in + * a failure. + * @param string $name Name attribute of button. + * @param integer $x X-coordinate of imaginary click. + * @param integer $y Y-coordinate of imaginary click. + * @param hash $additional Additional form values. + * @return boolean/string Page on success. + * @access public + */ + function clickImageByName($name, $x = 1, $y = 1, $additional = false) { + return $this->_failOnError( + $this->_browser->clickImageByName($name, $x, $y, $additional)); + } + + /** + * Clicks the submit image by ID attribute. The owning + * form will be submitted by this. Clicking outside of + * the boundary of the coordinates will result in + * a failure. + * @param integer/string $id ID attribute of button. + * @param integer $x X-coordinate of imaginary click. + * @param integer $y Y-coordinate of imaginary click. + * @param hash $additional Additional form values. + * @return boolean/string Page on success. + * @access public + */ + function clickImageById($id, $x = 1, $y = 1, $additional = false) { + return $this->_failOnError( + $this->_browser->clickImageById($id, $x, $y, $additional)); + } + + /** + * Checks for a valid image with atht alt text or title. + * @param string $label Visible text. + * @return boolean True if click target. + * @access public + */ + function assertImage($label, $message = '%s') { + return $this->assertTrue( + $this->_browser->isImage($label), + sprintf($message, "Image with text [$label] should exist")); + } + + /** + * Submits a form by the ID. + * @param string $id Form ID. No button information + * is submitted this way. + * @return boolean/string Page on success. + * @access public + */ + function submitFormById($id) { + return $this->_failOnError($this->_browser->submitFormById($id)); + } + + /** + * Follows a link by name. Will click the first link + * found with this link text by default, or a later + * one if an index is given. Match is case insensitive + * with normalised space. + * @param string $label Text between the anchor tags. + * @param integer $index Link position counting from zero. + * @return boolean/string Page on success. + * @access public + */ + function clickLink($label, $index = 0) { + return $this->_failOnError($this->_browser->clickLink($label, $index)); + } + + /** + * Follows a link by id attribute. + * @param string $id ID attribute value. + * @return boolean/string Page on success. + * @access public + */ + function clickLinkById($id) { + return $this->_failOnError($this->_browser->clickLinkById($id)); + } + + /** + * Tests for the presence of a link label. Match is + * case insensitive with normalised space. + * @param string $label Text between the anchor tags. + * @param mixed $expected Expected URL or expectation object. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if link present. + * @access public + */ + function assertLink($label, $expected = true, $message = '%s') { + $url = $this->_browser->getLink($label); + if ($expected === true || ($expected !== true && $url === false)) { + return $this->assertTrue($url !== false, sprintf($message, "Link [$label] should exist")); + } + if (! SimpleExpectation::isExpectation($expected)) { + $expected = new IdenticalExpectation($expected); + } + return $this->assert($expected, $url->asString(), sprintf($message, "Link [$label] should match")); + } + + /** + * Tests for the non-presence of a link label. Match is + * case insensitive with normalised space. + * @param string/integer $label Text between the anchor tags + * or ID attribute. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if link missing. + * @access public + */ + function assertNoLink($label, $message = '%s') { + return $this->assertTrue( + $this->_browser->getLink($label) === false, + sprintf($message, "Link [$label] should not exist")); + } + + /** + * Tests for the presence of a link id attribute. + * @param string $id Id attribute value. + * @param mixed $expected Expected URL or expectation object. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if link present. + * @access public + */ + function assertLinkById($id, $expected = true, $message = '%s') { + $url = $this->_browser->getLinkById($id); + if ($expected === true) { + return $this->assertTrue($url !== false, sprintf($message, "Link ID [$id] should exist")); + } + if (! SimpleExpectation::isExpectation($expected)) { + $expected = new IdenticalExpectation($expected); + } + return $this->assert($expected, $url->asString(), sprintf($message, "Link ID [$id] should match")); + } + + /** + * Tests for the non-presence of a link label. Match is + * case insensitive with normalised space. + * @param string $id Id attribute value. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if link missing. + * @access public + */ + function assertNoLinkById($id, $message = '%s') { + return $this->assertTrue( + $this->_browser->getLinkById($id) === false, + sprintf($message, "Link ID [$id] should not exist")); + } + + /** + * Sets all form fields with that label, or name if there + * is no label attached. + * @param string $name Name of field in forms. + * @param string $value New value of field. + * @return boolean True if field exists, otherwise false. + * @access public + */ + function setField($label, $value, $position=false) { + return $this->_browser->setField($label, $value, $position); + } + + /** + * Sets all form fields with that name. + * @param string $name Name of field in forms. + * @param string $value New value of field. + * @return boolean True if field exists, otherwise false. + * @access public + */ + function setFieldByName($name, $value, $position=false) { + return $this->_browser->setFieldByName($name, $value, $position); + } + + /** + * Sets all form fields with that id. + * @param string/integer $id Id of field in forms. + * @param string $value New value of field. + * @return boolean True if field exists, otherwise false. + * @access public + */ + function setFieldById($id, $value) { + return $this->_browser->setFieldById($id, $value); + } + + /** + * Confirms that the form element is currently set + * to the expected value. A missing form will always + * fail. If no value is given then only the existence + * of the field is checked. + * @param string $name Name of field in forms. + * @param mixed $expected Expected string/array value or + * false for unset fields. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if pass. + * @access public + */ + function assertField($label, $expected = true, $message = '%s') { + $value = $this->_browser->getField($label); + return $this->_assertFieldValue($label, $value, $expected, $message); + } + + /** + * Confirms that the form element is currently set + * to the expected value. A missing form element will always + * fail. If no value is given then only the existence + * of the field is checked. + * @param string $name Name of field in forms. + * @param mixed $expected Expected string/array value or + * false for unset fields. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if pass. + * @access public + */ + function assertFieldByName($name, $expected = true, $message = '%s') { + $value = $this->_browser->getFieldByName($name); + return $this->_assertFieldValue($name, $value, $expected, $message); + } + + /** + * Confirms that the form element is currently set + * to the expected value. A missing form will always + * fail. If no ID is given then only the existence + * of the field is checked. + * @param string/integer $id Name of field in forms. + * @param mixed $expected Expected string/array value or + * false for unset fields. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if pass. + * @access public + */ + function assertFieldById($id, $expected = true, $message = '%s') { + $value = $this->_browser->getFieldById($id); + return $this->_assertFieldValue($id, $value, $expected, $message); + } + + /** + * Tests the field value against the expectation. + * @param string $identifier Name, ID or label. + * @param mixed $value Current field value. + * @param mixed $expected Expected value to match. + * @param string $message Failure message. + * @return boolean True if pass + * @access protected + */ + function _assertFieldValue($identifier, $value, $expected, $message) { + if ($expected === true) { + return $this->assertTrue( + isset($value), + sprintf($message, "Field [$identifier] should exist")); + } + if (! SimpleExpectation::isExpectation($expected)) { + $identifier = str_replace('%', '%%', $identifier); + $expected = new FieldExpectation( + $expected, + "Field [$identifier] should match with [%s]"); + } + return $this->assert($expected, $value, $message); + } + + /** + * Checks the response code against a list + * of possible values. + * @param array $responses Possible responses for a pass. + * @param string $message Message to display. Default + * can be embedded with %s. + * @return boolean True if pass. + * @access public + */ + function assertResponse($responses, $message = '%s') { + $responses = (is_array($responses) ? $responses : array($responses)); + $code = $this->_browser->getResponseCode(); + $message = sprintf($message, "Expecting response in [" . + implode(", ", $responses) . "] got [$code]"); + return $this->assertTrue(in_array($code, $responses), $message); + } + + /** + * Checks the mime type against a list + * of possible values. + * @param array $types Possible mime types for a pass. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertMime($types, $message = '%s') { + $types = (is_array($types) ? $types : array($types)); + $type = $this->_browser->getMimeType(); + $message = sprintf($message, "Expecting mime type in [" . + implode(", ", $types) . "] got [$type]"); + return $this->assertTrue(in_array($type, $types), $message); + } + + /** + * Attempt to match the authentication type within + * the security realm we are currently matching. + * @param string $authentication Usually basic. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertAuthentication($authentication = false, $message = '%s') { + if (! $authentication) { + $message = sprintf($message, "Expected any authentication type, got [" . + $this->_browser->getAuthentication() . "]"); + return $this->assertTrue( + $this->_browser->getAuthentication(), + $message); + } else { + $message = sprintf($message, "Expected authentication [$authentication] got [" . + $this->_browser->getAuthentication() . "]"); + return $this->assertTrue( + strtolower($this->_browser->getAuthentication()) == strtolower($authentication), + $message); + } + } + + /** + * Checks that no authentication is necessary to view + * the desired page. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertNoAuthentication($message = '%s') { + $message = sprintf($message, "Expected no authentication type, got [" . + $this->_browser->getAuthentication() . "]"); + return $this->assertFalse($this->_browser->getAuthentication(), $message); + } + + /** + * Attempts to match the current security realm. + * @param string $realm Name of security realm. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertRealm($realm, $message = '%s') { + if (! SimpleExpectation::isExpectation($realm)) { + $realm = new EqualExpectation($realm); + } + return $this->assert( + $realm, + $this->_browser->getRealm(), + "Expected realm -> $message"); + } + + /** + * Checks each header line for the required value. If no + * value is given then only an existence check is made. + * @param string $header Case insensitive header name. + * @param mixed $value Case sensitive trimmed string to + * match against. An expectation object + * can be used for pattern matching. + * @return boolean True if pass. + * @access public + */ + function assertHeader($header, $value = false, $message = '%s') { + return $this->assert( + new HttpHeaderExpectation($header, $value), + $this->_browser->getHeaders(), + $message); + } + + /** + * @deprecated + */ + function assertHeaderPattern($header, $pattern, $message = '%s') { + return $this->assert( + new HttpHeaderExpectation($header, new PatternExpectation($pattern)), + $this->_browser->getHeaders(), + $message); + } + + /** + * Confirms that the header type has not been received. + * Only the landing page is checked. If you want to check + * redirect pages, then you should limit redirects so + * as to capture the page you want. + * @param string $header Case insensitive header name. + * @return boolean True if pass. + * @access public + */ + function assertNoHeader($header, $message = '%s') { + return $this->assert( + new NoHttpHeaderExpectation($header), + $this->_browser->getHeaders(), + $message); + } + + /** + * @deprecated + */ + function assertNoUnwantedHeader($header, $message = '%s') { + return $this->assertNoHeader($header, $message); + } + + /** + * Tests the text between the title tags. + * @param string/SimpleExpectation $title Expected title. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertTitle($title = false, $message = '%s') { + if (! SimpleExpectation::isExpectation($title)) { + $title = new EqualExpectation($title); + } + return $this->assert($title, $this->_browser->getTitle(), $message); + } + + /** + * Will trigger a pass if the text is found in the plain + * text form of the page. + * @param string $text Text to look for. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertText($text, $message = '%s') { + return $this->assert( + new TextExpectation($text), + $this->_browser->getContentAsText(), + $message); + } + + /** + * @deprecated + */ + function assertWantedText($text, $message = '%s') { + return $this->assertText($text, $message); + } + + /** + * Will trigger a pass if the text is not found in the plain + * text form of the page. + * @param string $text Text to look for. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertNoText($text, $message = '%s') { + return $this->assert( + new NoTextExpectation($text), + $this->_browser->getContentAsText(), + $message); + } + + /** + * @deprecated + */ + function assertNoUnwantedText($text, $message = '%s') { + return $this->assertNoText($text, $message); + } + + /** + * Will trigger a pass if the Perl regex pattern + * is found in the raw content. + * @param string $pattern Perl regex to look for including + * the regex delimiters. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertPattern($pattern, $message = '%s') { + return $this->assert( + new PatternExpectation($pattern), + $this->_browser->getContent(), + $message); + } + + /** + * @deprecated + */ + function assertWantedPattern($pattern, $message = '%s') { + return $this->assertPattern($pattern, $message); + } + + /** + * Will trigger a pass if the perl regex pattern + * is not present in raw content. + * @param string $pattern Perl regex to look for including + * the regex delimiters. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertNoPattern($pattern, $message = '%s') { + return $this->assert( + new NoPatternExpectation($pattern), + $this->_browser->getContent(), + $message); + } + + /** + * @deprecated + */ + function assertNoUnwantedPattern($pattern, $message = '%s') { + return $this->assertNoPattern($pattern, $message); + } + + /** + * Checks that a cookie is set for the current page + * and optionally checks the value. + * @param string $name Name of cookie to test. + * @param string $expected Expected value as a string or + * false if any value will do. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertCookie($name, $expected = false, $message = '%s') { + $value = $this->getCookie($name); + if (! $expected) { + return $this->assertTrue( + $value, + sprintf($message, "Expecting cookie [$name]")); + } + if (! SimpleExpectation::isExpectation($expected)) { + $expected = new EqualExpectation($expected); + } + return $this->assert($expected, $value, "Expecting cookie [$name] -> $message"); + } + + /** + * Checks that no cookie is present or that it has + * been successfully cleared. + * @param string $name Name of cookie to test. + * @param string $message Message to display. + * @return boolean True if pass. + * @access public + */ + function assertNoCookie($name, $message = '%s') { + return $this->assertTrue( + $this->getCookie($name) === false, + sprintf($message, "Not expecting cookie [$name]")); + } + + /** + * Called from within the test methods to register + * passes and failures. + * @param boolean $result Pass on true. + * @param string $message Message to display describing + * the test state. + * @return boolean True on pass + * @access public + */ + function assertTrue($result, $message = false) { + return $this->assert(new TrueExpectation(), $result, $message); + } + + /** + * Will be true on false and vice versa. False + * is the PHP definition of false, so that null, + * empty strings, zero and an empty array all count + * as false. + * @param boolean $result Pass on false. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertFalse($result, $message = '%s') { + return $this->assert(new FalseExpectation(), $result, $message); + } + + /** + * Will trigger a pass if the two parameters have + * the same value only. Otherwise a fail. This + * is for testing hand extracted text, etc. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertEqual($first, $second, $message = '%s') { + return $this->assert( + new EqualExpectation($first), + $second, + $message); + } + + /** + * Will trigger a pass if the two parameters have + * a different value. Otherwise a fail. This + * is for testing hand extracted text, etc. + * @param mixed $first Value to compare. + * @param mixed $second Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertNotEqual($first, $second, $message = '%s') { + return $this->assert( + new NotEqualExpectation($first), + $second, + $message); + } + + /** + * Uses a stack trace to find the line of an assertion. + * @return string Line number of first assert* + * method embedded in format string. + * @access public + */ + function getAssertionLine() { + $trace = new SimpleStackTrace(array('assert', 'click', 'pass', 'fail')); + return $trace->traceMethod(); + } +} +?> \ No newline at end of file diff --git a/plugins/www/testgen4web_simpletest/lib/simpletest/xml.php b/plugins/www/testgen4web_simpletest/lib/simpletest/xml.php new file mode 100644 index 0000000..1666cb9 --- /dev/null +++ b/plugins/www/testgen4web_simpletest/lib/simpletest/xml.php @@ -0,0 +1,647 @@ +SimpleReporter(); + $this->_namespace = ($namespace ? $namespace . ':' : ''); + $this->_indent = $indent; + } + + /** + * Calculates the pretty printing indent level + * from the current level of nesting. + * @param integer $offset Extra indenting level. + * @return string Leading space. + * @access protected + */ + function _getIndent($offset = 0) { + return str_repeat( + $this->_indent, + count($this->getTestList()) + $offset); + } + + /** + * Converts character string to parsed XML + * entities string. + * @param string text Unparsed character data. + * @return string Parsed character data. + * @access public + */ + function toParsedXml($text) { + return str_replace( + array('&', '<', '>', '"', '\''), + array('&', '<', '>', '"', '''), + $text); + } + + /** + * Paints the start of a group test. + * @param string $test_name Name of test that is starting. + * @param integer $size Number of test cases starting. + * @access public + */ + function paintGroupStart($test_name, $size) { + parent::paintGroupStart($test_name, $size); + print $this->_getIndent(); + print "<" . $this->_namespace . "group size=\"$size\">\n"; + print $this->_getIndent(1); + print "<" . $this->_namespace . "name>" . + $this->toParsedXml($test_name) . + "_namespace . "name>\n"; + } + + /** + * Paints the end of a group test. + * @param string $test_name Name of test that is ending. + * @access public + */ + function paintGroupEnd($test_name) { + print $this->_getIndent(); + print "_namespace . "group>\n"; + parent::paintGroupEnd($test_name); + } + + /** + * Paints the start of a test case. + * @param string $test_name Name of test that is starting. + * @access public + */ + function paintCaseStart($test_name) { + parent::paintCaseStart($test_name); + print $this->_getIndent(); + print "<" . $this->_namespace . "case>\n"; + print $this->_getIndent(1); + print "<" . $this->_namespace . "name>" . + $this->toParsedXml($test_name) . + "_namespace . "name>\n"; + } + + /** + * Paints the end of a test case. + * @param string $test_name Name of test that is ending. + * @access public + */ + function paintCaseEnd($test_name) { + print $this->_getIndent(); + print "_namespace . "case>\n"; + parent::paintCaseEnd($test_name); + } + + /** + * Paints the start of a test method. + * @param string $test_name Name of test that is starting. + * @access public + */ + function paintMethodStart($test_name) { + parent::paintMethodStart($test_name); + print $this->_getIndent(); + print "<" . $this->_namespace . "test>\n"; + print $this->_getIndent(1); + print "<" . $this->_namespace . "name>" . + $this->toParsedXml($test_name) . + "_namespace . "name>\n"; + } + + /** + * Paints the end of a test method. + * @param string $test_name Name of test that is ending. + * @param integer $progress Number of test cases ending. + * @access public + */ + function paintMethodEnd($test_name) { + print $this->_getIndent(); + print "_namespace . "test>\n"; + parent::paintMethodEnd($test_name); + } + + /** + * Paints pass as XML. + * @param string $message Message to encode. + * @access public + */ + function paintPass($message) { + parent::paintPass($message); + print $this->_getIndent(1); + print "<" . $this->_namespace . "pass>"; + print $this->toParsedXml($message); + print "_namespace . "pass>\n"; + } + + /** + * Paints failure as XML. + * @param string $message Message to encode. + * @access public + */ + function paintFail($message) { + parent::paintFail($message); + print $this->_getIndent(1); + print "<" . $this->_namespace . "fail>"; + print $this->toParsedXml($message); + print "_namespace . "fail>\n"; + } + + /** + * Paints error as XML. + * @param string $message Message to encode. + * @access public + */ + function paintError($message) { + parent::paintError($message); + print $this->_getIndent(1); + print "<" . $this->_namespace . "exception>"; + print $this->toParsedXml($message); + print "_namespace . "exception>\n"; + } + + /** + * Paints exception as XML. + * @param Exception $exception Exception to encode. + * @access public + */ + function paintException($exception) { + parent::paintException($exception); + print $this->_getIndent(1); + print "<" . $this->_namespace . "exception>"; + $message = 'Unexpected exception of type [' . get_class($exception) . + '] with message ['. $exception->getMessage() . + '] in ['. $exception->getFile() . + ' line ' . $exception->getLine() . ']'; + print $this->toParsedXml($message); + print "_namespace . "exception>\n"; + } + + /** + * Paints the skipping message and tag. + * @param string $message Text to display in skip tag. + * @access public + */ + function paintSkip($message) { + parent::paintSkip($message); + print $this->_getIndent(1); + print "<" . $this->_namespace . "skip>"; + print $this->toParsedXml($message); + print "_namespace . "skip>\n"; + } + + /** + * Paints a simple supplementary message. + * @param string $message Text to display. + * @access public + */ + function paintMessage($message) { + parent::paintMessage($message); + print $this->_getIndent(1); + print "<" . $this->_namespace . "message>"; + print $this->toParsedXml($message); + print "_namespace . "message>\n"; + } + + /** + * Paints a formatted ASCII message such as a + * variable dump. + * @param string $message Text to display. + * @access public + */ + function paintFormattedMessage($message) { + parent::paintFormattedMessage($message); + print $this->_getIndent(1); + print "<" . $this->_namespace . "formatted>"; + print ""; + print "_namespace . "formatted>\n"; + } + + /** + * Serialises the event object. + * @param string $type Event type as text. + * @param mixed $payload Message or object. + * @access public + */ + function paintSignal($type, $payload) { + parent::paintSignal($type, $payload); + print $this->_getIndent(1); + print "<" . $this->_namespace . "signal type=\"$type\">"; + print ""; + print "_namespace . "signal>\n"; + } + + /** + * Paints the test document header. + * @param string $test_name First test top level + * to start. + * @access public + * @abstract + */ + function paintHeader($test_name) { + if (! SimpleReporter::inCli()) { + header('Content-type: text/xml'); + } + print "_namespace) { + print " xmlns:" . $this->_namespace . + "=\"www.lastcraft.com/SimpleTest/Beta3/Report\""; + } + print "?>\n"; + print "<" . $this->_namespace . "run>\n"; + } + + /** + * Paints the test document footer. + * @param string $test_name The top level test. + * @access public + * @abstract + */ + function paintFooter($test_name) { + print "_namespace . "run>\n"; + } +} + +/** + * Accumulator for incoming tag. Holds the + * incoming test structure information for + * later dispatch to the reporter. + * @package SimpleTest + * @subpackage UnitTester + */ +class NestingXmlTag { + var $_name; + var $_attributes; + + /** + * Sets the basic test information except + * the name. + * @param hash $attributes Name value pairs. + * @access public + */ + function NestingXmlTag($attributes) { + $this->_name = false; + $this->_attributes = $attributes; + } + + /** + * Sets the test case/method name. + * @param string $name Name of test. + * @access public + */ + function setName($name) { + $this->_name = $name; + } + + /** + * Accessor for name. + * @return string Name of test. + * @access public + */ + function getName() { + return $this->_name; + } + + /** + * Accessor for attributes. + * @return hash All attributes. + * @access protected + */ + function _getAttributes() { + return $this->_attributes; + } +} + +/** + * Accumulator for incoming method tag. Holds the + * incoming test structure information for + * later dispatch to the reporter. + * @package SimpleTest + * @subpackage UnitTester + */ +class NestingMethodTag extends NestingXmlTag { + + /** + * Sets the basic test information except + * the name. + * @param hash $attributes Name value pairs. + * @access public + */ + function NestingMethodTag($attributes) { + $this->NestingXmlTag($attributes); + } + + /** + * Signals the appropriate start event on the + * listener. + * @param SimpleReporter $listener Target for events. + * @access public + */ + function paintStart(&$listener) { + $listener->paintMethodStart($this->getName()); + } + + /** + * Signals the appropriate end event on the + * listener. + * @param SimpleReporter $listener Target for events. + * @access public + */ + function paintEnd(&$listener) { + $listener->paintMethodEnd($this->getName()); + } +} + +/** + * Accumulator for incoming case tag. Holds the + * incoming test structure information for + * later dispatch to the reporter. + * @package SimpleTest + * @subpackage UnitTester + */ +class NestingCaseTag extends NestingXmlTag { + + /** + * Sets the basic test information except + * the name. + * @param hash $attributes Name value pairs. + * @access public + */ + function NestingCaseTag($attributes) { + $this->NestingXmlTag($attributes); + } + + /** + * Signals the appropriate start event on the + * listener. + * @param SimpleReporter $listener Target for events. + * @access public + */ + function paintStart(&$listener) { + $listener->paintCaseStart($this->getName()); + } + + /** + * Signals the appropriate end event on the + * listener. + * @param SimpleReporter $listener Target for events. + * @access public + */ + function paintEnd(&$listener) { + $listener->paintCaseEnd($this->getName()); + } +} + +/** + * Accumulator for incoming group tag. Holds the + * incoming test structure information for + * later dispatch to the reporter. + * @package SimpleTest + * @subpackage UnitTester + */ +class NestingGroupTag extends NestingXmlTag { + + /** + * Sets the basic test information except + * the name. + * @param hash $attributes Name value pairs. + * @access public + */ + function NestingGroupTag($attributes) { + $this->NestingXmlTag($attributes); + } + + /** + * Signals the appropriate start event on the + * listener. + * @param SimpleReporter $listener Target for events. + * @access public + */ + function paintStart(&$listener) { + $listener->paintGroupStart($this->getName(), $this->getSize()); + } + + /** + * Signals the appropriate end event on the + * listener. + * @param SimpleReporter $listener Target for events. + * @access public + */ + function paintEnd(&$listener) { + $listener->paintGroupEnd($this->getName()); + } + + /** + * The size in the attributes. + * @return integer Value of size attribute or zero. + * @access public + */ + function getSize() { + $attributes = $this->_getAttributes(); + if (isset($attributes['SIZE'])) { + return (integer)$attributes['SIZE']; + } + return 0; + } +} + +/** + * Parser for importing the output of the XmlReporter. + * Dispatches that output to another reporter. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleTestXmlParser { + var $_listener; + var $_expat; + var $_tag_stack; + var $_in_content_tag; + var $_content; + var $_attributes; + + /** + * Loads a listener with the SimpleReporter + * interface. + * @param SimpleReporter $listener Listener of tag events. + * @access public + */ + function SimpleTestXmlParser(&$listener) { + $this->_listener = &$listener; + $this->_expat = &$this->_createParser(); + $this->_tag_stack = array(); + $this->_in_content_tag = false; + $this->_content = ''; + $this->_attributes = array(); + } + + /** + * Parses a block of XML sending the results to + * the listener. + * @param string $chunk Block of text to read. + * @return boolean True if valid XML. + * @access public + */ + function parse($chunk) { + if (! xml_parse($this->_expat, $chunk)) { + trigger_error('XML parse error with ' . + xml_error_string(xml_get_error_code($this->_expat))); + return false; + } + return true; + } + + /** + * Sets up expat as the XML parser. + * @return resource Expat handle. + * @access protected + */ + function &_createParser() { + $expat = xml_parser_create(); + xml_set_object($expat, $this); + xml_set_element_handler($expat, '_startElement', '_endElement'); + xml_set_character_data_handler($expat, '_addContent'); + xml_set_default_handler($expat, '_default'); + return $expat; + } + + /** + * Opens a new test nesting level. + * @return NestedXmlTag The group, case or method tag + * to start. + * @access private + */ + function _pushNestingTag($nested) { + array_unshift($this->_tag_stack, $nested); + } + + /** + * Accessor for current test structure tag. + * @return NestedXmlTag The group, case or method tag + * being parsed. + * @access private + */ + function &_getCurrentNestingTag() { + return $this->_tag_stack[0]; + } + + /** + * Ends a nesting tag. + * @return NestedXmlTag The group, case or method tag + * just finished. + * @access private + */ + function _popNestingTag() { + return array_shift($this->_tag_stack); + } + + /** + * Test if tag is a leaf node with only text content. + * @param string $tag XML tag name. + * @return @boolean True if leaf, false if nesting. + * @private + */ + function _isLeaf($tag) { + return in_array($tag, array( + 'NAME', 'PASS', 'FAIL', 'EXCEPTION', 'SKIP', 'MESSAGE', 'FORMATTED', 'SIGNAL')); + } + + /** + * Handler for start of event element. + * @param resource $expat Parser handle. + * @param string $tag Element name. + * @param hash $attributes Name value pairs. + * Attributes without content + * are marked as true. + * @access protected + */ + function _startElement($expat, $tag, $attributes) { + $this->_attributes = $attributes; + if ($tag == 'GROUP') { + $this->_pushNestingTag(new NestingGroupTag($attributes)); + } elseif ($tag == 'CASE') { + $this->_pushNestingTag(new NestingCaseTag($attributes)); + } elseif ($tag == 'TEST') { + $this->_pushNestingTag(new NestingMethodTag($attributes)); + } elseif ($this->_isLeaf($tag)) { + $this->_in_content_tag = true; + $this->_content = ''; + } + } + + /** + * End of element event. + * @param resource $expat Parser handle. + * @param string $tag Element name. + * @access protected + */ + function _endElement($expat, $tag) { + $this->_in_content_tag = false; + if (in_array($tag, array('GROUP', 'CASE', 'TEST'))) { + $nesting_tag = $this->_popNestingTag(); + $nesting_tag->paintEnd($this->_listener); + } elseif ($tag == 'NAME') { + $nesting_tag = &$this->_getCurrentNestingTag(); + $nesting_tag->setName($this->_content); + $nesting_tag->paintStart($this->_listener); + } elseif ($tag == 'PASS') { + $this->_listener->paintPass($this->_content); + } elseif ($tag == 'FAIL') { + $this->_listener->paintFail($this->_content); + } elseif ($tag == 'EXCEPTION') { + $this->_listener->paintError($this->_content); + } elseif ($tag == 'SKIP') { + $this->_listener->paintSkip($this->_content); + } elseif ($tag == 'SIGNAL') { + $this->_listener->paintSignal( + $this->_attributes['TYPE'], + unserialize($this->_content)); + } elseif ($tag == 'MESSAGE') { + $this->_listener->paintMessage($this->_content); + } elseif ($tag == 'FORMATTED') { + $this->_listener->paintFormattedMessage($this->_content); + } + } + + /** + * Content between start and end elements. + * @param resource $expat Parser handle. + * @param string $text Usually output messages. + * @access protected + */ + function _addContent($expat, $text) { + if ($this->_in_content_tag) { + $this->_content .= $text; + } + return true; + } + + /** + * XML and Doctype handler. Discards all such content. + * @param resource $expat Parser handle. + * @param string $default Text of default content. + * @access protected + */ + function _default($expat, $default) { + } +} +?> diff --git a/plugins/www/webservice_soapui/CHANGELOG b/plugins/www/webservice_soapui/CHANGELOG new file mode 100644 index 0000000..34dc2cc --- /dev/null +++ b/plugins/www/webservice_soapui/CHANGELOG @@ -0,0 +1,6 @@ +1.0.1 (2008.06.09) +Fixed. #74 Incorrect min version required + +1.0.0 (2008.05.27) +------------------ +Initial release. \ No newline at end of file diff --git a/plugins/www/webservice_soapui/LICENSE b/plugins/www/webservice_soapui/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/www/webservice_soapui/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/www/webservice_soapui/configure.php b/plugins/www/webservice_soapui/configure.php new file mode 100644 index 0000000..d1ec19b --- /dev/null +++ b/plugins/www/webservice_soapui/configure.php @@ -0,0 +1,35 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$_plugin_name = 'webservice_soapui'; +$plugin_field[$_plugin_name][0]['version'] = '1.0.1'; +$plugin_field[$_plugin_name][0]['min_ortro_version'] = '1.3.1'; +$plugin_field[$_plugin_name][0]['authors'][0] = 'Luca Corbo '; +$plugin_field[$_plugin_name][0]['description'] = PLUGIN_WEBSERVICE_SOAPUI_DESCRIPTION; +$plugin_field[$_plugin_name][0]['title'] = PLUGIN_WEBSERVICE_SOAPUI_TITLE; + +$plugin_field[$_plugin_name][1]['type'] = 'file'; +$plugin_field[$_plugin_name][1]['required'] = true;//check for uploaded file only when adding it. +$plugin_field[$_plugin_name][1]['name'] = 'webservice_soapui_testcase'; +$plugin_field[$_plugin_name][1]['value'] = ''; +$plugin_field[$_plugin_name][1]['attributes'] = 'disabled size=70'; +$plugin_field[$_plugin_name][1]['description'] = PLUGIN_WEBSERVICE_SOAPUI_TESTCASE_DESCRIPTION; +$plugin_field[$_plugin_name][1]['num_rules'] = '0'; +?> \ No newline at end of file diff --git a/plugins/www/webservice_soapui/configure_metadata.php b/plugins/www/webservice_soapui/configure_metadata.php new file mode 100644 index 0000000..192eca2 --- /dev/null +++ b/plugins/www/webservice_soapui/configure_metadata.php @@ -0,0 +1,31 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/* Environment configuration */ + +$_plugin_name = 'webservice_soapui'; +$conf_metadata[$_plugin_name]['description'] = PLUGIN_METADATA_CONFIGURATION; + +$conf_metadata[$_plugin_name]['soapui_path']['description'] = PLUGIN_WEBSERVICE_SOAPUI_METADATA_SOAPUI_PATH_DESCRIPTION; +$conf_metadata[$_plugin_name]['soapui_path']['type'] = 'text'; +$conf_metadata[$_plugin_name]['soapui_path']['name'] = 'webservice_soapui-soapui_path'; +$conf_metadata[$_plugin_name]['soapui_path']['value'] = '/opt/soapui/'; +$conf_metadata[$_plugin_name]['soapui_path']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/www/webservice_soapui/core.php b/plugins/www/webservice_soapui/core.php new file mode 100644 index 0000000..2d77b1d --- /dev/null +++ b/plugins/www/webservice_soapui/core.php @@ -0,0 +1,73 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +@require_once ORTRO_CONF_PLUGINS . 'www_webservice_soapui.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +//---- Start plugin code ----- + +$loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); +$loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + +//Get the params required by plugin +$testcase = ORTRO_ATTACHMENTS . $id_job . DS . $parameters['webservice_soapui_testcase']; + +$cmdLine = $conf['webservice_soapui']['soapui_path'] . + DS . 'bin' . DS . 'testrunner.sh -r ' . + $testcase . ' 2>&1'; + +exec($cmdLine, $stdout, $exit_code); + +$attachments['txt'] = implode("\n", $stdout); +$attachments['html'] = implode("
", $stdout); + +if ($exit_code != '0') { + $loggerPlugin->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . implode("\n", $stdout)); + $result = '0'; +} else { + $result = '1'; +} + +$msg_exec = $attachments['txt']; +//---- End plugin code ----- + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/www/webtest_selenium/CHANGELOG b/plugins/www/webtest_selenium/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/www/webtest_selenium/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/www/webtest_selenium/LICENSE b/plugins/www/webtest_selenium/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/www/webtest_selenium/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/www/webtest_selenium/configure.php b/plugins/www/webtest_selenium/configure.php new file mode 100644 index 0000000..c24c665 --- /dev/null +++ b/plugins/www/webtest_selenium/configure.php @@ -0,0 +1,50 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['webtest_selenium'][0]['version'] = '1.2.2'; +$plugin_field['webtest_selenium'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['webtest_selenium'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['webtest_selenium'][0]['description'] = PLUGIN_WEBTEST_SELENIUM_DESCRIPTION; +$plugin_field['webtest_selenium'][0]['title'] = PLUGIN_WEBTEST_SELENIUM_TITLE; + +$plugin_field['webtest_selenium'][1]['type'] = 'select'; +$plugin_field['webtest_selenium'][1]['name'] = 'webtest_selenium_programming_language'; +$plugin_field['webtest_selenium'][1]['value'] = array('perl' => PLUGIN_WEBTEST_SELENIUM_LANGUAGE_VALUE_PERL, + 'python' => PLUGIN_WEBTEST_SELENIUM_LANGUAGE_VALUE_PYTHON); +$plugin_field['webtest_selenium'][1]['attributes'] =''; +$plugin_field['webtest_selenium'][1]['description'] = PLUGIN_WEBTEST_SELENIUM_LANGUAGE_DESCRIPTION; + +$plugin_field['webtest_selenium'][2]['type'] = 'text'; +$plugin_field['webtest_selenium'][2]['name'] = 'webtest_selenium_identity'; +$plugin_field['webtest_selenium'][2]['value'] = ''; +$plugin_field['webtest_selenium'][2]['attributes'] = 'disabled readonly'; +$plugin_field['webtest_selenium'][2]['description'] = PLUGIN_IDENTITY; +$plugin_field['webtest_selenium'][2]['num_rules'] = '0'; + +$plugin_field['webtest_selenium'][3]['type'] = 'textarea'; +$plugin_field['webtest_selenium'][3]['name'] = 'webtest_selenium_input_script'; +$plugin_field['webtest_selenium'][3]['value'] = ''; +$plugin_field['webtest_selenium'][3]['attributes'] = 'disabled rows=30 cols=80'; +$plugin_field['webtest_selenium'][3]['description'] = PLUGIN_WEBTEST_SELENIUM_CODE_DESCRIPTION; +$plugin_field['webtest_selenium'][3]['num_rules'] = '1'; +$plugin_field['webtest_selenium'][3]['rule_msg'][0] = PLUGIN_WEBTEST_SELENIUM_RULE_3_0; +$plugin_field['webtest_selenium'][3]['rule_type'][0] = 'required'; +$plugin_field['webtest_selenium'][3]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/www/webtest_selenium/configure_metadata.php b/plugins/www/webtest_selenium/configure_metadata.php new file mode 100644 index 0000000..ebc6d81 --- /dev/null +++ b/plugins/www/webtest_selenium/configure_metadata.php @@ -0,0 +1,35 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/* Environment configuration */ + +$conf_metadata['webtest_selenium']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['webtest_selenium']['python_path']['description'] = PLUGIN_WEBTEST_SELENIUM_METADATA_PYTHON_PATH_DESCRIPTION; +$conf_metadata['webtest_selenium']['python_path']['type'] = 'text'; +$conf_metadata['webtest_selenium']['python_path']['name'] = 'webtest_selenium-python_path'; +$conf_metadata['webtest_selenium']['python_path']['value'] = '/usr/bin/'; +$conf_metadata['webtest_selenium']['python_path']['attributes'] = 'size=30'; + +$conf_metadata['webtest_selenium']['selenium_path']['description'] = PLUGIN_WEBTEST_SELENIUM_METADATA_SELENIUM_PATH_DESCRIPTION; +$conf_metadata['webtest_selenium']['selenium_path']['type'] = 'text'; +$conf_metadata['webtest_selenium']['selenium_path']['name'] = 'webtest_selenium-selenium_path'; +$conf_metadata['webtest_selenium']['selenium_path']['value'] = '/usr/bin/'; +$conf_metadata['webtest_selenium']['selenium_path']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/www/webtest_selenium/core.php b/plugins/www/webtest_selenium/core.php new file mode 100644 index 0000000..9c5576c --- /dev/null +++ b/plugins/www/webtest_selenium/core.php @@ -0,0 +1,110 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +@require_once ORTRO_CONF_PLUGINS . 'www_webtest_selenium.php'; +require_once 'cronUtil.php'; + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +//---- Start plugin code ----- + +$loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); +$loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + +//Get the params required by plugin from argv +$user = $job_infos['identity']['username']; +$pwd = $job_infos['identity']['password']; + +$program_language = $parameters['webtest_selenium_programming_language']; +$input_script = $parameters['webtest_selenium_input_script']; + +//Replace username e password in the input_script code +$input_script = str_replace('${USERNAME}', $user, $input_script); +$input_script = str_replace('${PASSWORD}', $pwd, $input_script); + +$path = dirname($argv[0]) . DIRECTORY_SEPARATOR; +$tempFile = ''; +$tempFile = $path . 'webtest_selenium_' . + $id_job . '_' . time() . rand(); + +$fh = fopen($tempFile, 'w+'); +fwrite($fh, $input_script); +fclose($fh); +chmod($tempFile, 0777); + +switch ($program_language) { +case 'python': + $python_path = $conf['webtest_selenium']['python_path']; + $selenium_python_path = $conf['webtest_selenium']['selenium_path']; + $export_path = 'export PYTHONPATH=$PYTHONPATH:' . + $selenium_python_path . ';'; + $cmdLine = $export_path . $python_path . + $program_language . ' "' . $tempFile . '" 2>&1'; + break; +} + +exec($cmdLine, $stdout, $exit_code); + +@unlink($tempFile); + +str_replace($password, '******', $stdout);//hide the password +$attachments['txt'] = implode("\n", $stdout); +$attachments['html'] = implode("
", $stdout); + +if ($exit_code != '0') { + $loggerPlugin->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . implode("\n", $stdout)); + $result = '0'; +} else { + $result = '1'; +} + +$attachments['txt'] = implode("\n", $stdout); +$attachments['html'] = implode("
", $stdout); +$msg_exec = $attachments['html']; +$loggerPlugin->trace('INFO', 'cmd='.$cmdLine); +$loggerPlugin->trace('INFO', 'id=' . $id_job . + ' output: ' . $attachments['txt']); +$loggerPlugin->trace('INFO', 'id=' . $id_job . + ' exit_code: ' . $exit_code); +$loggerPlugin->trace('INFO', 'Job ' . $plugin_name . + ' with id=' . $id_job . ' done.'); +//---- End plugin code ----- + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/www/webtest_slimdog/CHANGELOG b/plugins/www/webtest_slimdog/CHANGELOG new file mode 100644 index 0000000..466ee70 --- /dev/null +++ b/plugins/www/webtest_slimdog/CHANGELOG @@ -0,0 +1,11 @@ +1.2.2 (2007.11.19) +------------------ +Use init.inc.php + +1.2.1 (2007.08.02) +------------------ +Added info for the minimum required version of Ortro + +1.2.0 (2007.07.24) +------------------ +Initial release with i18n support \ No newline at end of file diff --git a/plugins/www/webtest_slimdog/LICENSE b/plugins/www/webtest_slimdog/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/plugins/www/webtest_slimdog/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/www/webtest_slimdog/configure.php b/plugins/www/webtest_slimdog/configure.php new file mode 100644 index 0000000..d07657a --- /dev/null +++ b/plugins/www/webtest_slimdog/configure.php @@ -0,0 +1,43 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +$plugin_field['webtest_slimdog'][0]['version'] = '1.2.2'; +$plugin_field['webtest_slimdog'][0]['min_ortro_version'] = '1.2.0'; +$plugin_field['webtest_slimdog'][0]['authors'][0] = 'Luca Corbo '; +$plugin_field['webtest_slimdog'][0]['description'] = PLUGIN_WEBTEST_SLIMDOG_DESCRIPTION; +$plugin_field['webtest_slimdog'][0]['title'] = PLUGIN_WEBTEST_SLIMDOG_TITLE; + +$plugin_field['webtest_slimdog'][1]['type'] = 'text'; +$plugin_field['webtest_slimdog'][1]['name'] = 'webtest_slimdog_identity'; +$plugin_field['webtest_slimdog'][1]['value'] = ''; +$plugin_field['webtest_slimdog'][1]['attributes'] = 'disabled readonly'; +$plugin_field['webtest_slimdog'][1]['description'] = PLUGIN_IDENTITY; +$plugin_field['webtest_slimdog'][1]['num_rules'] = '0'; + +$plugin_field['webtest_slimdog'][2]['type'] = 'textarea'; +$plugin_field['webtest_slimdog'][2]['name'] = 'webtest_slimdog_input_script'; +$plugin_field['webtest_slimdog'][2]['value'] = ''; +$plugin_field['webtest_slimdog'][2]['attributes'] = 'disabled rows=30 cols=80'; +$plugin_field['webtest_slimdog'][2]['description'] = PLUGIN_WEBTEST_SLIMDOG_CODE_DESCRIPTION; +$plugin_field['webtest_slimdog'][2]['num_rules'] = '1'; +$plugin_field['webtest_slimdog'][2]['rule_msg'][0] = PLUGIN_WEBTEST_SLIMDOG_RULE_2_0; +$plugin_field['webtest_slimdog'][2]['rule_type'][0] = 'required'; +$plugin_field['webtest_slimdog'][2]['rule_attribute'][0] = ''; +?> \ No newline at end of file diff --git a/plugins/www/webtest_slimdog/configure_metadata.php b/plugins/www/webtest_slimdog/configure_metadata.php new file mode 100644 index 0000000..fac05fe --- /dev/null +++ b/plugins/www/webtest_slimdog/configure_metadata.php @@ -0,0 +1,35 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +/* Environment configuration */ + +$conf_metadata['webtest']['description'] = PLUGIN_METADATA_CONFIGURATION; +$conf_metadata['webtest']['java_path']['description'] = PLUGIN_WEBTEST_SLIMDOG_METADATA_JAVA_PATH_DESCRIPTION; +$conf_metadata['webtest']['java_path']['type'] = 'text'; +$conf_metadata['webtest']['java_path']['name'] = 'webtest-java_path'; +$conf_metadata['webtest']['java_path']['value'] = '/usr/bin/'; +$conf_metadata['webtest']['java_path']['attributes'] = 'size=30'; + +$conf_metadata['webtest']['slimdog_path']['description'] = PLUGIN_WEBTEST_SLIMDOG_METADATA_SLIMDOG_PATH_DESCRIPTION; +$conf_metadata['webtest']['slimdog_path']['type'] = 'text'; +$conf_metadata['webtest']['slimdog_path']['name'] = 'webtest-slimdog_path'; +$conf_metadata['webtest']['slimdog_path']['value'] = '/usr/bin/'; +$conf_metadata['webtest']['slimdog_path']['attributes'] = 'size=30'; +?> \ No newline at end of file diff --git a/plugins/www/webtest_slimdog/core.php b/plugins/www/webtest_slimdog/core.php new file mode 100644 index 0000000..c71e3e6 --- /dev/null +++ b/plugins/www/webtest_slimdog/core.php @@ -0,0 +1,100 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +//###### Required core code ###### + +$current_path = realpath(dirname($argv[0])); +require_once $current_path . '/../../init.inc.php'; +@require_once ORTRO_CONF_PLUGINS . 'www_webtest_slimdog.php'; +require_once 'cronUtil.php'; + + +$plugin_name = basename(dirname($argv[0]), DIRECTORY_SEPARATOR); +$id_job = $argv[1];// Get the job id +$request_type = $argv[2];// Get the type of request + +$cronUtil = new CronUtil($request_type); +$job_infos = $cronUtil->startJobEvent($plugin_name, $id_job); +$parameters = $job_infos['parameters']; +set_error_handler("errorHandler"); + +//###### End required core code ###### + +//---- Start plugin code ----- + +$loggerPlugin = new LogUtil($plugin_name, ORTRO_LOG_PLUGINS . $plugin_name); +$loggerPlugin->trace('INFO', 'Executing job ' . $plugin_name . + ' with id=' . $id_job); + +//Get the params required by plugin from argv +$user = $job_infos['identity']['username']; +$pwd = $job_infos['identity']['password']; + +$input_script = $parameters['webtest_input_script']; + +//Replace username e password in the input_script code +$input_script = str_replace('${USERNAME}', $user, $input_script); +$input_script = str_replace('${PASSWORD}', $pwd, $input_script); + +$path = dirname($argv[0]); +$tempFile = 'webtest_' . time() . rand(); +$tempDir = $path . DIRECTORY_SEPARATOR; + +$fh = fopen($tempDir . $tempFile, 'w+'); +fwrite($fh, $input_script); +fclose($fh); +chmod($tempDir . $tempFile, 0777); + +$cmdLine = $path . '/script.sh "' . $conf['webtest']['java_path'] . '" "' . + $conf['webtest']['slimdog_path'] . '" -f "' . + $tempDir . $tempFile . '" 2>&1'; + +$loggerPlugin->trace('ERROR', $cmdLine); +exec($cmdLine, $stdout, $exit_code); + +@unlink($tempDir . $tempFile); + +$attachments['txt'] = implode("\n", $stdout); +$attachments['html'] = implode("
", $stdout); + +if ($exit_code != '0') { + $loggerPlugin->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . implode("\n", $stdout)); + $result = '0'; +} else { + if ((strpos($attachments['txt'], 'Failed') !== false)) { + $result = '1'; + } else { + $loggerPlugin->trace('ERROR', 'exit_code=' . $exit_code . "\n" . + "Message:\n" . implode("\n", $stdout)); + $result = '0'; + } + +} + +$msg_exec = $attachments['txt']; +//---- End plugin code ----- + +//###### Required core code ###### +restore_error_handler(); +$cronUtil->endJobEvent($plugin_name, $id_job, $result, $msg_exec, $attachments); +//###### End required core code ###### +?> \ No newline at end of file diff --git a/plugins/www/webtest_slimdog/script.sh b/plugins/www/webtest_slimdog/script.sh new file mode 100755 index 0000000..29cf4ac --- /dev/null +++ b/plugins/www/webtest_slimdog/script.sh @@ -0,0 +1,25 @@ +################################################################################# +# Ortro +# Copyright (C) 2006 and following years, Luca Corbo +# +# This software is published under the terms of the GPL License +# a copy of which has been included with this distribution in the LICENSE file. +# +# Script for Web Test using Slimdog +# +# File Authors: +# Luca Corbo +# +################################################################################## + +JAVA_BIN_PATH=$1 +shift +SLIMDOG_HOME=$1 +shift + +CP=${CLASSPATH}:${SLIMDOG_HOME} +for lib in ${SLIMDOG_HOME}/lib/*.jar; do + CP=${CP}:${lib}; +done + +${JAVA_BIN_PATH}/java -classpath ${CP} -jar ${SLIMDOG_HOME}/webtester.jar $* diff --git a/tools/create_package.php b/tools/create_package.php new file mode 100644 index 0000000..b1d10c7 --- /dev/null +++ b/tools/create_package.php @@ -0,0 +1,256 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once '../conf/init.php'; +require_once 'Archive/Tar.php'; +require_once 'ioUtil.php'; +require_once 'langUtil.php'; + +$input_dir = realpath('..') . DS; +$input_dir_plugins = $input_dir . 'plugins' . DS; +$output_dir = realpath('..') . DS . 'build' . DS; +$output_dir_plugins = $output_dir . 'plugins' . DS; +$output_dir_ortro = $output_dir . 'ortro-core' . DS; +$output_dir_ortro_full = $output_dir . 'ortro-full' . DS; + +$exclude_list = array('build', + '.svn', + '.project', + 'create_package.php', + 'plugins', + 'tools', + 'packages'); + +$ortro_full_plugin_list = array('database_check_tablespace' , + 'database_custom_query' , + 'database_custom_query_report' , + 'file_create' , + 'file_ftp_upload' , + 'file_retention' , + 'file_read_file' , + 'file_search' , + 'file_size_check' , + 'general_custom_script' , + 'general_windows_remote_execution' , + 'notification_jabber' , + 'notification_mail' , + 'notification_sms_ftp' , + 'notification_tibco_rvd' , + 'notification_tivoli_postemsg' , + 'system_cpu_idle' , + 'system_file_system_check' , + 'system_ping' , + 'system_service_check' , + 'www_check_uri_response_code' , + 'www_testgen4web_simpletest'); + +$file_ext = '.tar.gz'; + +if (!is_dir($output_dir)) { + @mkdir($output_dir, 0755); + @mkdir($output_dir_ortro, 0755); + @mkdir($output_dir_ortro_no_plugins, 0755); +} + +/** + * Creates all plugins starting from svn. + * + * @param array $ortro_full_plugin_list The list of Plugin to create + * + * @return void + */ +function createPluginsPackage($ortro_full_plugin_list = array()) +{ + global $input_dir_plugins,$output_dir_plugins,$file_ext,$exclude_list; + echo 'Removing old package (if exists)...'; + @removeDirectory($output_dir_plugins); + @mkdir($output_dir_plugins, 0755); + echo ' -> Done.' . "\n"; + $dir_contents = scandir($input_dir_plugins); + foreach ($dir_contents as $category) { + if (is_dir($input_dir_plugins.$category) && + $category != '.' && $category != '..' && + $category != '.svn') { + $sub_dir = $input_dir_plugins . $category . DS; + //echo 'Entering category "' . $category . "\"\n"; + $sub_dir_contents = scandir($sub_dir); + foreach ($sub_dir_contents as $plugin_name) { + if (is_dir($sub_dir.$plugin_name) && + $plugin_name != '.' && + $plugin_name != '..' && + $plugin_name != '.svn') { + if (count($ortro_full_plugin_list)==0 || + in_array($category . '_' . $plugin_name, + $ortro_full_plugin_list)) { + echo ' Starting to create package for plugin ' . + $plugin_name . " ... \n"; + i18n($category, $plugin_name); + include $sub_dir . $plugin_name . DS . 'configure.php'; + $filename = $category . '_' . + $plugin_name . '-' . + $plugin_field[$plugin_name][0]['version'] . + $file_ext; + $tar_object = new Archive_Tar($output_dir_plugins . + $filename, true); + $tar_object->createModify($sub_dir . $plugin_name, + '', + $input_dir_plugins, + $exclude_list); + + //Add the language files starting from svn repository + $dir_lang_contents = scandir(ORTRO_LANG); + foreach ($dir_lang_contents as $item) { + if (is_dir(ORTRO_LANG . $item) && + $item != '.' && + $item != '..' && + $item != '.svn') { + $full_path = ORTRO_LANG . $item . DS . + 'plugins'. DS . + $category . DS . + $plugin_name . DS; + if (file_exists($full_path)) { + $tar_object->addModify($full_path . + 'language.php', + $category . DS . + $plugin_name . DS . + 'lang' . DS . $item, + $full_path, + $exclude_list); + } + } + } + echo ' Package ' . $filename. " created.\n\n"; + } + } + } + } + } +} + +/** + * Create the Ortro core package + * + * @return void + */ +function createOrtroPackage() +{ + global $input_dir, $output_dir_ortro, $file_ext, $exclude_list; + echo 'Removing old package (if exists)...'; + @removeDirectory($output_dir_ortro); + @mkdir($output_dir_ortro, 0755); + echo ' -> Done.' . "\n"; + $filename = 'ortro-core-' . ORTRO_VERSION . $file_ext; + echo "Starting to create the ortro-core package... \n"; + $tar_object = new Archive_Tar($output_dir_ortro . $filename, true); + $tar_object->createModify($input_dir, + 'ortro-core-' . ORTRO_VERSION, + $input_dir, + $exclude_list); + //Add the init.inc.php file + $list_v[0] = $input_dir . 'conf/init.inc.php'; + $tar_object->addModify($list_v, + 'ortro-core-' . ORTRO_VERSION . '/bin', + $input_dir . 'conf/'); + $tar_object->addModify($list_v, + 'ortro-core-' . ORTRO_VERSION . '/plugins', + $input_dir . 'conf/'); + $tar_object->addModify($list_v, + 'ortro-core-' . ORTRO_VERSION . '/www', + $input_dir . 'conf/'); + echo ' Package ' . $filename. " created.\n\n"; +} + +/** + * Create the Ortro full package + * + * @return void + */ +function createOrtroFullPackage() +{ + global $input_dir, $output_dir, $output_dir_plugins; + global $output_dir_ortro_full, $file_ext, $exclude_list; + echo 'Removing old package (if exists)...'; + @removeDirectory($output_dir_ortro_full); + @mkdir($output_dir_ortro_full, 0755); + echo ' -> Done.' . "\n"; + $filename = 'ortro-full-' . ORTRO_VERSION . $file_ext; + echo "Starting to create the ortro-full package... \n"; + $tar_object = new Archive_Tar($output_dir_ortro_full . $filename, true); + $tar_object->createModify($input_dir, + 'ortro-full-' . ORTRO_VERSION, + $input_dir, + $exclude_list); + $tar_object->addModify($output_dir_plugins, + 'ortro-full-' . ORTRO_VERSION . + '/www/template/install/plugins', + $output_dir_plugins); + //Add the init.inc.php file + $list_v[0] = $input_dir. 'conf/init.inc.php'; + $tar_object->addModify($list_v, + 'ortro-full-' . ORTRO_VERSION . '/bin', + $input_dir . 'conf/'); + $tar_object->addModify($list_v, + 'ortro-full-' . ORTRO_VERSION . '/plugins', + $input_dir . 'conf/'); + $tar_object->addModify($list_v, + 'ortro-full-' . ORTRO_VERSION . '/www', + $input_dir . 'conf/'); + echo ' Package ' . $filename. " created.\n\n"; +} + +$usage = 'Usage: php create_package.php --ortro-full | ' . + ' --ortro-core | --plugins[=plugin]' . "\n"; + +if (!isset($argv[1])) { + echo $usage; + exit; +} + +switch ($argv[1]) { +case '--ortro-core': + createOrtroPackage(); + break; + +case '--plugins': + createPluginsPackage(); + break; + +case '--ortro-full': + createPluginsPackage($ortro_full_plugin_list); + createOrtroFullPackage(); + break; + +default: + //check for single plugin or category + if ((strpos($argv[1], '--plugins=') === false)) { + echo $usage; + exit; + } else { + $temp = explode('=', $argv[1]); + createPluginsPackage(array($temp[1])); + } + break; + +} + +echo 'input_dir: ' . $input_dir . "\n"; +echo 'output_dir: ' . $output_dir . "\n"; +exit; +?> \ No newline at end of file diff --git a/tools/ortro_sync.exclude b/tools/ortro_sync.exclude new file mode 100644 index 0000000..e5df5ce --- /dev/null +++ b/tools/ortro_sync.exclude @@ -0,0 +1,4 @@ +.svn/ +build/ +tools/ +packages/ diff --git a/tools/ortro_sync.sh b/tools/ortro_sync.sh new file mode 100755 index 0000000..df65989 --- /dev/null +++ b/tools/ortro_sync.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Ortro_sync script +# It allows to update your Ortro installation (only php code) starting from a SVN check out. +# author: Luca Corbo + +### Disclaimer ### +# This is a developer tool, please do not use it in production environments. + +### Environment configuration ### +ORTRO_SVN_ROOT="/home/lucor/ortro.svn/" +ORTRO_INSTALLATION_ROOT="/var/www/ortro/" +ORTRO_SYNC_PATH="/home/lucor/ortro.svn/tools/" + +### Please do not modify the lines below ### +rsync -rl --exclude-from=${ORTRO_SYNC_PATH}ortro_sync.exclude ${ORTRO_SVN_ROOT} ${ORTRO_INSTALLATION_ROOT} +mkdir -p ${ORTRO_INSTALLATION_ROOT}www/js/lang/ + +cp ${ORTRO_INSTALLATION_ROOT}conf/init.inc.php ${ORTRO_INSTALLATION_ROOT}bin/ +cp ${ORTRO_INSTALLATION_ROOT}conf/init.inc.php ${ORTRO_INSTALLATION_ROOT}plugins/ +cp ${ORTRO_INSTALLATION_ROOT}conf/init.inc.php ${ORTRO_INSTALLATION_ROOT}www/ + +cp ${ORTRO_INSTALLATION_ROOT}lang/it/js/* ${ORTRO_INSTALLATION_ROOT}www/js/lang/ +cp ${ORTRO_INSTALLATION_ROOT}lang/en/js/* ${ORTRO_INSTALLATION_ROOT}www/js/lang/ diff --git a/upgrade/upgrade.php b/upgrade/upgrade.php new file mode 100644 index 0000000..d380ccc --- /dev/null +++ b/upgrade/upgrade.php @@ -0,0 +1,125 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + + + +$current_path = realpath(dirname($argv[0])) . DIRECTORY_SEPARATOR; +require_once ($current_path . '../conf/init.php'); + +if (!file_exists(ORTRO_CONF . 'configure.php')){ + echo "Upgrade error: configure.php not found!\n\n"; + exit; +} + + + +//$ldap_auth_enabled = false; +//if (file_exists(ORTRO_CONF . 'configure_ldap.php')){ +// require_once ORTRO_CONF . 'configure_ldap.php'; +// if ($conf['ldap']['login'] == '1') { +// $ldap_auth_enabled = true; +// } +// unset($conf); +//} +// +//include ORTRO_CONF . 'configure.php'; +//require_once 'Pear/Config.php'; +// +//$c = new Config(); +// +//if ($ldap_auth_enabled) { +// $conf['auth']['default'] = 'LDAP'; +// $conf['auth']['fallback'] = '1'; +//} else { +// $conf['auth']['default'] = 'MDB2'; +// $conf['auth']['fallback'] = '0'; +//} +// +//$conf['id'] = 'ortro_' . md5(uniqid()); +//$conf['env']['job_timeout'] = '0'; +// +//$c->parseconfig($conf, 'phparray'); +//$result = $c->writeConfig(ORTRO_CONF . 'configure.php', 'phparray'); +// + +include ORTRO_CONF . 'configure.php'; +require_once 'langUtil.php'; +require_once 'dbUtil.php'; +i18n('template', 'install.php'); + +// create a db connection connection +$db_name = $GLOBALS['conf']['db']['database']; +$db_prefix = $GLOBALS['conf']['db']['tableprefix']; + +$dbUtil = new DbUtil(); + +$dsn = $dbUtil->setDSN(array('phptype' => $GLOBALS['conf']['db']['phptype'], + 'hostspec' => $GLOBALS['conf']['db']['host'] . ":" . + $GLOBALS['conf']['db']['port'], + 'database' => $GLOBALS['conf']['db']['database'], + 'username' => $GLOBALS['conf']['db']['username'], + 'password' => $GLOBALS['conf']['db']['password'])); + +// Update the database schema + +echo UPGRADE_DB_SCHEMA . "\n"; + +require_once 'MDB2/Schema.php'; + +$options = array('use_transactions'=> false); + +$variables = array( + //Specific ortro options + 'db_name' => $db_name, + 'table_prefix' => $db_prefix, + 'user_language' => 'en', +); + + +$schema =& MDB2_Schema::factory($dsn, $options); + +if (PEAR::isError($schema)) { + $error = $schema->getMessage(); + +} else { + // first run with queries disabled to make sure everything is allright + $disable_query = false; + + $previous_schema = $schema->getDefinitionFromDatabase(); + + $op = $schema->updateDatabase('../www/template/install/ortro.schema.xml', $previous_schema, $variables, $disable_query); + + if (PEAR::isError($op)) { + $error = $op->getMessage(); + $error = $op->getUserInfo(); + } +} + +if (isset($error)) { + var_dump($error); +} else { + echo "Upgrade done.\n"; +} + +$schema->disconnect(); + +echo "Please remove the www/template/install directory.\n"; + +?> diff --git a/www/css/jquery.jqplot.css b/www/css/jquery.jqplot.css new file mode 100644 index 0000000..86ec256 --- /dev/null +++ b/www/css/jquery.jqplot.css @@ -0,0 +1,135 @@ +/*rules for the plot target div. These will be cascaded down to all plot elements according to css rules*/ +.jqplot-target { + position: relative; + color: #666666; + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 1em; + height: 300px; + width: 400px; +} + +/*rules applied to all axes*/ +.jqplot-axis { + font-size: 0.75em; +} + +.jqplot-xaxis { + margin-top: 10px; +} + +.jqplot-x2axis { + margin-bottom: 10px; +} + +.jqplot-yaxis { + margin-right: 10px; +} + +.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis { + margin-left: 10px; + margin-right: 10px; +} + +/*rules applied to all axis tick divs*/ +.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { + position: absolute; +} + + +.jqplot-xaxis-tick { + top: 0px; + /* initial position untill tick is drawn in proper place */ + left: 15px; +/* padding-top: 10px;*/ + vertical-align: top; +} + +.jqplot-x2axis-tick { + bottom: 0px; + /* initial position untill tick is drawn in proper place */ + left: 15px; +/* padding-bottom: 10px;*/ + vertical-align: bottom; +} + +.jqplot-yaxis-tick { + right: 0px; + /* initial position untill tick is drawn in proper place */ + top: 15px; +/* padding-right: 10px;*/ + text-align: right; +} + +.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { + left: 0px; + /* initial position untill tick is drawn in proper place */ + top: 15px; +/* padding-left: 10px;*/ +/* padding-right: 15px;*/ + text-align: left; +} + +.jqplot-xaxis-label { + margin-top: 10px; + font-size: 11pt; + position: absolute; +} + +.jqplot-x2axis-label { + margin-bottom: 10px; + font-size: 11pt; + position: absolute; +} + +.jqplot-yaxis-label { + margin-right: 10px; +/* text-align: center;*/ + font-size: 11pt; + position: absolute; +} + +.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label { +/* text-align: center;*/ + font-size: 11pt; + position: absolute; +} + +table.jqplot-legend { + background-color: rgba(255,255,255,0.6); + border: 1px solid #cccccc; + position: absolute; + font-size: 0.75em; +} + +.jqplot-title { + top: 0px; + left: 0px; + padding-bottom: 0.5em; + font-size: 1.2em; +} + +table.jqplot-cursor-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; +} + + +.jqplot-cursor-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208,208,208,0.5); + padding: 1px; +} + +.jqplot-highlighter-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208,208,208,0.5); + padding: 1px; +} + +.jqplot-point-label { + font-size: 0.75em; +} diff --git a/www/css/layout.css b/www/css/layout.css new file mode 100644 index 0000000..9b6305f --- /dev/null +++ b/www/css/layout.css @@ -0,0 +1,30 @@ +/* + +STICKER - A valid, easy to use CSS sticky footer by Ryan Fait + +This is the basic CSS you need along with the one extra empty +div and the wrapper required to achieve the effect. I suggest +that you leave the * { margin: 0; } code in while testing and +building your site because margins do have a tendency to mess +things up a bit. Have fun! + +Copyright (c) 2006-2007 Ryan Fait +http://ryanfait.com/sticky-footer/ + +*/ + +* { + margin: 0; +} +html, body { + height: 100%; +} +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -12pt; /* the bottom margin is the negative value of the footer's height */ +} +.footer, .push { + height: 12pt; /*.push must be the same height as .footer */ +} \ No newline at end of file diff --git a/www/css/layout_login.css b/www/css/layout_login.css new file mode 100644 index 0000000..5bc34a4 --- /dev/null +++ b/www/css/layout_login.css @@ -0,0 +1,30 @@ +/* + +STICKER - A valid, easy to use CSS sticky footer by Ryan Fait + +This is the basic CSS you need along with the one extra empty +div and the wrapper required to achieve the effect. I suggest +that you leave the * { margin: 0; } code in while testing and +building your site because margins do have a tendency to mess +things up a bit. Have fun! + +Copyright (c) 2006-2007 Ryan Fait +http://ryanfait.com/sticky-footer/ + +*/ + +* { + margin: 0; +} +html, body { + height: 100%; +} +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -4em; /* the bottom margin is the negative value of the footer's height */ +} +.footer, .push { + height: 4em; /*.push must be the same height as .footer */ +} \ No newline at end of file diff --git a/www/css/no-theme/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/www/css/no-theme/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..954e22dbd99e8c6dd7091335599abf2d10bf8003 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEr#)R9Ln2z=UU%d=WFXS=@V?HT z#xG*`>Yvsgk=}99w^d^D^d*@m74oMo<%#FcopJf?u00-~YVKV2wzrI*_R6;UORMea zBFVSEnN~eiVA6V&z`E)YLz5Aok^D)In}Yn=OzDpgR5Wv0XfT8pOkmV{sKAJ-PO9#T zZK}IXj&Q-V!U)!LcB_3K0&C*{ literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-bg_diagonals-thick_20_666666_40x40.png b/www/css/no-theme/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..64ece5707d91a6edf9fad4bfcce0c4dbcafcf58d GIT binary patch literal 251 zcmVbvPcjKS|RKP(6sDcCAB(_QB%0978a<$Ah$!b|E zwn;|HO0i8cQj@~)s!ajF0S002ovPDHLkV1oEp BYH0uf literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-bg_flat_10_000000_40x100.png b/www/css/no-theme/images/ui-bg_flat_10_000000_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..abdc01082bf3534eafecc5819d28c9574d44ea89 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQY-ImG zFPf9b{J;c_6SHRK%WcbN_hZpM=(Ry;4Rxv2@@2Y=$K57eF$X$=!PC{xWt~$(69B)$ BI)4BF literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-bg_glass_100_f6f6f6_1x400.png b/www/css/no-theme/images/ui-bg_glass_100_f6f6f6_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..9b383f4d2eab09c0f2a739d6b232c32934bc620b GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour1U*q978O6-yYw{%b*}|_(02F z@qbE9)0CJMo;*v*PWv`Vh2h6EmG8IS-Cm{3U~` zFlmZ}YMcJY=eo?o%*@I?2`NblNeMudl#t?{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/www/css/no-theme/images/ui-bg_gloss-wave_35_f6a828_500x100.png new file mode 100644 index 0000000000000000000000000000000000000000..39d5824d6af5456f1e89fc7847ea3599ea5fd815 GIT binary patch literal 3762 zcmb_eYgiKKwx-=Q?Pdi0+w!yaC|_1uvA>yaxz|iX3eBv#HR0ASmSVIKMS&kf`CSAV4g0DJLgPkRO79xj%J<(hH6`bTGj zrr^$JeiHJI?;s&<5pRw-^kj}=E;X0OX+pgz+f5GVt0NQv_gbu0>-8J+F$O>HpW?Lx z+YFO`CV&6VV9fsEwG#js0_-|v*!ujZ*M=jfo457?0Do-z<^}+8bI+qk+W~+$zz%Z& z;L7&@&ns`l8Ofh*WdU0pO%RP^?Xa_h7I}7K#}4Xt`s%-(m-enaPWX$O&- zX~a1aOzn?!r?5wJVBNPJ_o8-(9Fz<_c1LYGxUl(E+Wdx?wkNHH2T%eWq9Kz00h#RB zYKI~=a<9_QqC^n<>hyWlS66waWgyAP#t&TfTWP=Sxa)ukRY%j7WH}(@r=B^W_;b&M zRzPYsb*j^Kou%%`K6VP+dKtR@x~qEHq4rXMxoX-gcSf&->lMY%TMXF!Gw_A)(tp6} z2A%kN3twbr%KyUrrmw24V3d%wzK<-q(M;MTr41}un`P!!xejADEv_CJ{CTif907B& zEP`pDJIZHVgnmxh$EZnBOUxz~Ap+ZzKbFmg39_n-)$wY!Q@i~5aGmHbN7&*gkq9zWgV|2(Zhxl zoDqJp&MxW(qX#C@oF8L)*r$RdSjVFSc$%z?*9%YoZ6sOZ!vtxXtBM<*r82vyC}_Eiz1PJ2L$bttko`=+fH{Ne@G#lMDxkKt_y)O(J5&Ak)w-I znm!vzYX3$kLDG$hOp-KJg~7}M;73BFWA{!a61fe?NJkjR_}Xw+*`O0=AGg7&dUA`A?9`whW zM{fkFf`G`P^9j*|-q9KLvS<191z9a^mK3Lss}W8O=sZ}N$V4Fh*SWF5NbZQ>p{0>$ z0pe}d$*s!y*R&NSXbjmld6{4Y;O89MuDTK0Hn0C?QdL9z1qGegXs! z7$MIGkPkwdHF2os-Z-e85B?5An>yc|m<}>!Iirg%H-%F11XY{{>@kgL>a#6fM9JzBE&an&F>eWh|b0^kJ zNBM5*nCa~(xwn~rG~>GSG9mz3h z9F~64y}giIrz^lfl|_5HpUsG}?Wpr*&f?bS=|9biqivN)-a~u>uK<{Lfcng{663QL zLXzO@*N5)q4C=j6E8nC+P%lEwI#~0wkt;M4Y8!+DYzN2rBuYao1*HRIa^NC9nFeep z+ns5$X9Bh48S-`ss!k&!J#Ddd=j1O-9}?`v(B|>R7wD97BV;nK~quUHx^mj^G6K2GZ1*uSN?iLm!7vHB7_1^TGbKhmnK+K`GYA zocp2=on8LxJH^`7^1ch0ft(MTU$vJB!R@gQ^R`qoX>(=iY#u++3K>oqSpG={?#YVw zp3m99FXk^~<6#X9X1oKYXEH%8t2btG65(u0zF-J)^>8dj0Evc+9_Bd^Y)k9AfW~FV z%iDV(ClS6)TC7eVzh{ml;p4cx8)$TV&qhRWp+dqiw>i32?1;5d>HLrNj=^OdJ<}L) zWxqw8aFI<~_TkMDQHS?`z+KQ?+{ASoy%}RBu6i9?BXbh%OEx1OuZ}?n(VjrT(!B1; zQ!#WA0NBx=^6rJrFVsDCuT4)OTGzZ3$Z4Yqz z&c9+7%g!%zxtv#p2fhHbo98KBwfE&Y(&2#=}qEEU`ECEjlCp=X^_tIoMx>%kBT5k)^c=zyV5w3 zc>DLKY6%=y0igWi9B@4hB}bR6K|+jYBt+}i6Ld|b`*s62c6Ge?zGYvdW)=p90~$Ad zxGB>c<3Dy~hPJ#vNXierOl41xBn_0L<5NhK6JO-LvtS&Z{xjGKfIC6*9%*?tv*?+! zv;Q{?mHN2b|3DEJO}R9w11ZT5QVC(H0u|0n9cVK_@2r%C<)OnZ(3aS0Ux^6G$ja*< z9R~o~9XjhPL)w@vYi6r;H$tR>wW`0-Z&Qed`X0LZY9-~mfso!@dt?5Q;@|K6$mAB& z$J41&y)<{N;QATPeU}BC{lM_@-LlQ2hjX;}6~qdglT zGm%qJm*F^in=w*?j;@C_PCMnXK5Fd^wXV**pZOdS1KbSJsC~s#R;tmXIMb` zHB>sxQg&E5Yf@}d#~Z9D4R{}ZpLm7S=bY0x#k<=H?=R+=W$=Bm2aU*n z)qgD*0#4>GGlHhQ`bx#k=Njc;+9D@{F5`xI^tMkBf{XIzwB=b9KbuuLF7jMTR~Mwt zN#!)9J4&^V@JRe9Y!b2!;$rCLPWZfG`C;Qz`u~TJdCzv->e`=R8uHX_2{Fp&pWJ*h z#A60&bY(j(^P@t_`_pktBV7{tFVoeNWlNA|zgNr&DMjJ_!k2%2s2~F@la$M6k%hWi z7}}hoDuoaN7?lchVk@4DunpEIS$72&uuF&F;&4uhC$L)6IzHHUryR9emzpxwsRXmj zfc}pI#oRCB7Y1;t=*58Gsv7x3PGuW^spn6V&dWf#?*TQ0(|*rr=EeE1o~y1wyQi%)e*oX6iX@$m0F1RtKUT0vgg!8^fWhYLqS zF@EOpFld7>f^kprb~YwMq=^<e|gw?QFyf8ck|ZC^>)3c`b$^C>jCB4Fne_1e$Cqt=4Ud#K~~8Nfa91W zwk17&D?X?4FRzR+5qCiIqPf0};K4$tW$}l~A?u_E=JSe;*f_DO>r{z=U4_<)dY)M! z7O#mizC+GN&#;)k)vkBUS@fZesb{v?YuFlCPRjsT5bxB4@+sqdq}xvvBhTngZ(N1LUCS-ei=5sgE-Tbc z7HK+A_O23MP@sUoc?I?*ZB|F)&%us|2O$#G7V$6z zq>G%6!cu7OEf+_#^A=23Hd6Db9-yK*NQ#S+kjJI7 zhLiLz{>zKKtHH>H;B-cALzj`>@+-~?X2aP7ypf9WMf8q0m)wS!Nkf+&R&&zEjFOUx zlq^>v#VAq}=)?dKRMe+010g9O;qAiaTA4dV+==mw%i3Re)DwZ$Wd5CK1m4Ivy&&Ef zO8W!SpcgA>zfTGAE!{IPJMhdZ`T4{K#7ndDT8K2&*jf=J8O>H*iDJ}ZK}z|$C3U62 z$nZhk4v$QIYzMaV+0`B8S!=9RSYzi*QG#tp>ZY|lY_`}A-zI7)(tV$B9G-tC#zt8m zre~pD7oIFkmIAM=s zw+Iili%nSC?yks)t~q4lTlZW(#5^yUV@+^KvIuQzZDO^*TBz!j#nX%*uiW|{x9q0w literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/www/css/no-theme/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..f1273672d253263b7564e9e21d69d7d9d0b337d9 GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l%l7LV~E7m7s zyI`Y7$F!Dbe>W|wjBOHW$ygS--u6f3W(K|!ygPL}3f&#$lo`@lzd7`Pt~sI)y9#FRI%lI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3Rqvn`1P1SiomLXkg776;)RSXXXV1Iqu_@e2%8dEPZ*NvG6-d*$oWlBXKKg zV({l@ll0gM+F;pm#SBg*2mQ!Rn_HBhT&5w_d`jyG6+_vuxMHXoKj|Yh2EGJ-B`N+E z$pmy>sA-*C0S`BfHv`&Y>Z626r?uZY8?`zzbXj7u1}` z;TS<~e1eY(jD4j)wElgyeR*V7`qdhf3S5Vcdq_R*a&F^r|9|M*i>!yeL)xMH?-6M_ zJjl&7(M|RQJ2z;fI7;E!$?Pfq$usWpjLxzlazT~K6v`ft@@P32;&o$5@b}Yj#d~r) z9^2%vhdyIgOXOGiCNOR_sjx3j8*01pUqQBn7r}I@E53HUy&DusRETO9wG~Rdfx=Ta zwD>0smtXx6l#X>f`lTc3c!pmLbwTP$Zfe7s__87<&i+s33P`Udim99RAA$T_Y7T3^ z>vV9wL8Sc0x! z_eRl4cEFZ`EXPfL3omdIIY|MS@P4-79I_Af%(!ONP=msk&*mFs^(0gOj->4HEJ}Ca zL(HZSEXEQH#fbJDfQ^RQnvtlx$kD>NeLhPB+yUp!E5O$&?fP1}JdI;l4(=H(hEfAQ zNRU;>uU@{f`2)^*UI^NA8VHraDlXrE*?OWOs z7D#P(ftiy|@ab?=t923@#mR}=S6GNj1 z?mTR4hby}vE*2>Wg7-X!KAz3vwvJ)qVMtB~**$wrQ^&0>;8UR6E7imZV-)iH?Tt~> zX-EGVhMYWVxX}dU)MQaN+jv0*8;3JBy*az#1aW|^_4%i?mlU$yRTy>-wCJJVC==P> zEx=B7cZ&E7jJ@{Z{CG+0A-lAG;ovs3FALs8|JLq?o#M-to~~wx^JI)GhP%l=X?-mS zEbfx}Nj)D74<>(1{)gt2^%v7UAlLYp6gO$gsv=`$#2)3F9ed8@mcK6i!h@mGQqU}e zyItCAfl~4IqG~(AU2lV?`)nu#S5+1BrCJv>QmoI?LyuLj8e^o>li?U6OMey{r_T(* zY8RG<@x>cK$(nNMlhy)E`{;|c6$@%L*hZEYs{mUmt$8-u8m?YV3{83m{YAwB%6Y{L z6k9V^jd0tnd%q4+xwp&Yfr#>WqoooH9K5xYM|V_s8{16~N?TcuYd@6+y1_aS;c{q^(Kyv6DZcFd zd@RkCqyC{5yX5E=oHd-`WBQ0I>9_&^<}<7793`JA=$mRuSrr}iQyzxG9T)%=Xp2g4 zkFI*p1^XIjQQE0yQNGyZNn{h@1;N1>r@)!(21u5LGg2Ob1==Thh`ZXost~Y05y+XE zrc7k%zx|Fxe^LX9HhqjcV~P|W`3AXYj%WAaFNz@uZ-xRmf!NHrNh4zKSO1WrwFL6P zXM}G=*p9v_k=mUmpg-$Y6I7Mt4@y2D+ys?c;_C@aVePnKabqAS%y%AoFzKI#JaeQxo%Il=}>GqqqxhG8cPyu>P?R=}Ol7vhvDcW{Z8i0Zn zzm^YCS5qT4m#*SycTaxzIpnMMHwFrEO>lJzqr0i6lGn6M7x;$7B7Iy)6renY$OiZc zMEFF-;Ff)@RWrYEodz{P?avD?^RtUsN$GEP>xrgxlbtd22`L1q+Vm;zyBzLIj#2fp zQZS2sUF)*%MR5S(jid&TIT<2`Js!yUdi}%lzzxkuKjf|bHvGZz#1l5%O0plla6C28K&%)=R}0F6xRI>HvM|=4x#=-to|lSN^N9P6&xIP z2dq0{CX-Xc&YJNeXXD#dn;c9feR-*P_CfUEp8(wN{z!yEZrI*MPs**fh@b|xe*S&i zHc8i5C2XFuJ)xhg7K~%2H`zsX?JhZT+>};UB5HaE$E92V@>aXAPbP zjHGY7LH_&c+;-7yblDf5tKrky!+N>Vx>?)QZi1hm1Aea(92RyRiFczw&w7)GT*KddVhT(T~0Egdo9qyLRosyG6?!=QbqPzk^x9!b!;O zjEYZ(YM2+oYg-TrJTt9??(26|bMF?&#cgl&%SzC;-tOToW%SoAmvaoExO%bz%?xjk zc(|{^J<~z4;>Loltn&Q#cD-zLlA0oFa(P1*5{sdl$v0#75<`$?CT{uv?urEF5%l#% z1*lLBO|PYH2z}OUCDP!56T6(s<{oG|TOAmiP3Z95>EKzFu=~wRiHd}%-yn`p^?J6( zih27|xpMpU0(-^Ma=J7`xm^&DhSqXkjnQt=LQjM?m_ss!!0cIcfgCXk7TijCGz5At zUKx0OZ(Pc2owm3zR5RS0N)Y#iMfl$WQCVB&sa%OY<#3FtYF&H{`S5{&n#aQKe2Se9 zB?KD>qbcT%&$2w0lfgg>hoa-{bj}D!0GrB0(o9%dP6Pxsw8y%(rU7O|*#fSHYBm2h zyytq$C(2?`j}W=ORiP$Y;41*}G=Y$(2OhqHVfd_b2NmhSboLunMtOr5!~U=jF_g7g zx!U^R$M++HtM%nJWA0HW6A->{j|_B;D@i9waP$)>{6HyW zi?%Q-uGS3xs5_COdmgZjld7Pfo4dBxil@eQDw4^F*Vcb}d)bfW?|OD#N(nd^;T^jB zZea;L9}obXL9cH4o}9qQv(@ovFw_meU5D94g#m>tZ>F(pY-+sVc~p1lWWYncfsZBD zlLUulh#8ZKbJZaXx~7T%9*9kCI?ptUWNtB6zk6wB?Esa@U>adq3-GJsAap@@buxd8 zEh*0kH65g*0pwfcCE82`98Gls@jB5(U`@lWMLxq4sPDlmq!Rv*Vp(zSX$437XGBPqZRXNva3-1V4LK`FF19js@6mZK*48gf-Z-ZNB zLM=}?fKd18YCyN<3I%#wqeFjR9^PLn0C|nbyn1-&Ph!re@O0EEp`97_ouN^T>luaA zQbRd68s2B-M1Q}bL`59M`{jC(<_`P4m+_LOgr`2Gt(Rm4y+wDaGcvik0$;t-0c3C{ zKhx0TB~7CpakFn?r9>!&+;ccIO!hd{$-sX1k+O&#=VmV@?^gOz?c=kZ*8x}L)H)dP zYzhfqNU`(IVUtd)A!)GN@5UL@&OX&+@1C?lb`+!>)>=w1JnE$X>Lw#Yjk7&t)#5>X#Cjs|&jQ!X46aWn?QOjkKm*1G ztbhAifM)AKF=tIbp&vSIPqX&9FQ`BEN|??$UXR)85VQkj*P`!)ht-9)fQ|t&EI}c) zY_Dp0Km2C(q8potDF7er6kZ;VOs*dAVznYFU=Tj)$Gq2%pheYQJdTMt)xV?d0aA0f zf!9BB;E?X!!FWTWHx>8q_1{a`32+aVn2QqF4@>>wO;ea#m&96EhNkjIR(#vwq%yr` zfH0w))fHpM%M^W;nW$_)tb@EVVvhrYi*g_wUlF^|U`HFf<~&JOeBOMX&56=R~^VwL+|j!Ca?>Tx==&$#g^C#2+mS?tyG29g?7BC;5|* zhNhNJ?*-LgdlM)3Jx?L+w7;FK4mFXC;;XzQ429NM`AD>QNUJVX`T3s9}m~hbK7csE0P(!l|C~FWjU=g#?C}12ipKQAA~kz3%msO zg2N0*dRqd|SG=WcPVM-2UAcd>w1y8d%zsl=9Z^nq83TK_9xPH=!{}}AuqY7aaFPnP l;BjQ_^4`vQQuBMqxOYB4T*@HG=I>V@U~v|0R%wcf{y%IJ0Z9M= literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-icons_228ef1_256x240.png b/www/css/no-theme/images/ui-icons_228ef1_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..10e3631dcab364a0a1ab81862d678fd032908dd7 GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmPmYTG^FX}c% zlGE{DS1Q;~I7-6ze&TN@+F-xsI6sd%SwK#*O5K|pDRZqEy< zJg0Nd8F@!OxqElm`~U#piM22@u@8B<moyKE%ct`B(jysxK+1m?G)UyIFs1t0}L zemGR&?jGaM1YQblj?v&@0iXS#fi-VbR9zLEnHLP?xQ|=%Ihrc7^yPWR!tW$yH!zrw z#I2}_!JnT^(qk)VgJr`NGdPtT^dmQIZc%=6nTAyJDXk+^3}wUOilJuwq>s=T_!9V) zr1)DT6VQ2~rgd@!Jlrte3}}m~j}juCS`J4(d-5+e-3@EzzTJNCE2z)w(kJ90z*QE) zBtnV@4mM>jTrZZ*$01SnGov0&=A-JrX5Ge%Pce1Vj}=5YQqBD^W@n4KmFxxpFK`uH zP;(xKV+6VJ2|g+?_Lct7`uElL<&jzGS8Gfva2+=8A@#V+xsAj9|Dkg)vL5yhX@~B= zN2KZSAUD%QH`x>H+@Ou(D1~Pyv#0nc&$!1kI?IO01yw3jD0@80qvc?T*Nr8?-%rC8 z@5$|WY?Hqp`ixmEkzeJTz_`_wsSRi1%Zivd`#+T{Aib6-rf$}M8sz6v zb6ERbr-SniO2wbOv!M4)nb}6UVzoVZEh5kQWh_5x4rYy3c!871NeaM(_p=4(kbS6U#x<*k8Wg^KHs2ttCz<+pBxQ$Z zQMv;kVm5_fF_vH`Mzrq$Y&6u?j6~ftIV0Yg)Nw7JysIN_ z-_n*K_v1c&D}-1{NbBwS2h#m1y0a5RiEcYil+58$8IDh49bPnzE7R8In6P%V{2IZU z7#clr=V4yyrRe@oXNqbqo^^LvlLE?%8XaI&N(Np90-psU}7kqmbWk zZ;YBwJNnNs$~d!mx9oMGyT( znaBoj0d}gpQ^aRr?6nW)$4god*`@Uh2e+YpS@0(Mw{|z|6ko3NbTvDiCu3YO+)egL z>uW(^ahKFj>iJ-JF!^KhKQyPTznJa;xyHYwxJgr16&Wid_9)-%*mEwo{B_|M9t@S1 zf@T@q?b2Qgl!~_(Roe;fdK)y|XG0;ls;ZbT)w-aOVttk#daQcY7$cpY496H*`m@+L zeP#$&yRbBjFWv}B)|5-1v=(66M_;V1SWv6MHnO}}1=vby&9l+gaP?|pXwp0AFDe#L z&MRJ^*qX6wgxhA_`*o=LGZ>G_NTX%AKHPz4bO^R72ZYK}ale3lffDgM8H!Wrw{B7A z{?c_|dh2J*y8b04c37OmqUw;#;G<* z@nz@dV`;7&^$)e!B}cd5tl0{g(Q>5_7H^@bEJi7;fQ4B$NGZerH#Ae1#8WDTH`iB&) zC6Et3BYY#mcJxh&)b2C^{aLq~psFN)Q1SucCaBaBUr%5PYX{~-q{KGEh)*;n;?75k z=hq%i^I}rd;z-#YyI`8-OfMpWz5kgJE3I!3ean6=UZi!BxG7i(YBk? z02HM7wS0)Wni{dWbQMRtd-A)_Az!t>F;IwWf~!*)-Az4}yryNkz&9)w>ElA80Oc`6 zHo#9H!Y3*Qx9n@Jn)!w6G^hb;e_n8zpIyXCN`JFkPc)^Q?2MsLNFhMgrcZI-<#1ne zjH;KFf?4eAT9mQZ}ZfHLGA#d%s;SZK4p0FwZT2S^{ zQ2BG1xJsbK6?yrHTjJi|5C0u=!|r!?*4FL%y%3q#(d+e>b_2I9!*iI!30}42Ia0bq zUf`Z?LGSEvtz8s``Tg5o_CP(FbR0X$FlE0yCnB7suDPmI2=yOg^*2#cY9o`X z;NY-3VBHZjnVcGS){GZ98{e+lq~O$u6pEcgd0CrnIsWffN1MbCZDH<7c^hv+Z0Ucf0{w zSzi^qKuUHD9Dgp0EAGg@@$zr32dQx>N=ws`MESEsmzgT2&L;?MSTo&ky&!-JR3g~1 zPGTt515X)wr+Bx(G9lWd;@Y3^Vl}50Wb&6-Tiy;HPS0drF`rC}qYq22K4)G#AoD0X zYw$E+Bz@Zr^50MAwu@$?%f9$r4WHH?*2|67&FXFhXBrVFGmg)6?h3^-1?t;UzH0*I zNVf9wQLNLnG2@q>6CGm>&y|lC`iCFfYd}9i%+xkl^5oBJ?<;aneCfcHqJh7Yl5uLS z9Fx-(kMdcNyZejXh22N{mCw_rX1O!cOE&3>e(ZH81PR95wQC37En4O{w;{3q9n1t&;p)D%&Z%Nw$gSPa!nz8Slh7=ko2am)XARwOWw zpsz0~K!s{(dM$NB=(A=kkp>T(*yU6<_dwIx>cH4+LWl282hXa6-EUq>R3t?G2623< z*RwTN%-fgBmD{fu*ejNn)1@KG?Sg*8z3hYtkQJQjB6 zQ|x>wA=o$=O)+nLmgTXW3_6diA;b4EY{*i*R%6dO2EMg z@6g?M3rpbnfB@hOdUeb96=~I?OIA3@BWAGmTwiQ{x5Cqq<8c10L!P zd@Qk^BseTX%$Q7^s}5n%HB|)gKx}H$d8Sb$bBnq9-AglT2dGR2(+I;_fL|R4p$odJ zllfb0NqI)7=^z~qAm1V{(PkpxXsQ#4*NH9yYZ`Vf@)?#ueGgtCmGGY|9U#v|hRdg- zQ%0#cGIfXCd{Y)JB~qykO;KPvHu|5Ck&(Hn%DF~cct@}j+87xhs2ew;fLm5#2+mb| z8{9e*YI(u|gt|{x1G+U=DA3y)9s2w7@cvQ($ZJIA)x$e~5_3LKFV~ASci8W}jF&VeJoPDUy(BB>ExJpck;%;!`0AAo zAcHgcnT8%OX&UW_n|%{2B|<6Wp2MMGvd5`T2KKv;ltt_~H+w00x6+SlAD`{K4!9zx z*1?EpQ%Lwiik){3n{-+YNrT;fH_niD_Ng9|58@m8RsKFVF!6pk@qxa{BH-&8tsim0 zdAQ(GyC^9ane7_KW*#^vMIoeQdpJqmPp%%px3GIftbwESu#+vPyI*YTuJ6+4`z{s? zpkv~0x4c_PFH`-tqafw5)>4AuQ78SkZ!$8}INLK;Egr;2tS18hEO5=t;QDmZ-qu?I zG+=DN`nR72Xto{{bJp||`k}-2G;5#xg8E~xgz22)^_Z;=K|4@(E&5J)SY2of=olcw z5)@L)_Ntcm!*5nEy0M9v0`S33;pO4TN;>4(Z+19p_0>u#e-vE zXCU(6gAvu~I7Cw(xd%0e59MNLw^U37ZDbsBrj%eDCexw8a3G`nTcXVNL6{B7Hj@i& zbVB{;ApEtHk76q08DJ48dSxd$C(;$K6=FpU<~l9pVoT9arW^Vu{%Bcn4`eIpkOVC| z$)AKYG_`ypM{0@BUb3^9lqi_c?ONH|4UJMJWDowMVjacycX7}9g={O7swOB+{;+?; zjBo!9?+nd)ie#x5IbFW-zBOo0c4q@9wGVt5;pNt`=-~Zgcw#*`m($6ibxtZ`H=e=} zF#GZ~5$%AUn};8U#tRem0J(JTR}d4vR(dgK2ML~lZsPhayJ2h1%sD4FVst| zKF)+@`iNzLRjg4=K8@**0=5cE>%?FDc({I^+g9USk<8$&^qD~@%W0i4b|yMG*p4`N zh}I!ltTRI8Ex$+@V{02Br%xq#O?UlhO{r8WsaZnZCZq0MK9%AXU%MDLT;3=0A9(BV z9VxxxJd7jo$hw3q;3o?yBLmA=azBUrd9>-<_ANs0n3?-Ic*6&ytb@H~?0E(*d>T5n z-HiH2jsDf6uWhID%#n>SzOqrFCPDfUcu5QPd?<(=w6pv1BE#nsxS{n!UnC9qAha1< z;3cpZ9A-e$+Y)%b;w@!!YRA9p%Kf9IHGGg^{+p`mh;q8i7}&e@V3EQaMsItEMS&=X plT@$;k0WcB_jb;cn%_Idz4HO$QU*abf4}+wi?e96N>fbq{{iMEVj2Jd literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-icons_ef8c08_256x240.png b/www/css/no-theme/images/ui-icons_ef8c08_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..35bb8efa9c87eed9615e64354e12d3578c604823 GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~Gm-4?Ri0! z=XCBlBk#y3ckd3H9{>P6u@+_~_8~8qoKxH;>v&3G9I3&t`X4Ip}d{q6{tlN0;DW-1vv4SW^s<|J=>}*lDlHCB{1+Ib% zYR=Xiay0Ikq`)Ro1 zJ-Ho^ZSvPcpE0W?@~eCk7`K{K*cYb_wcYryAX~zVU^>+mU%TGk4T>ZxM74|B3MJk^ z;i(&1{1b-Dul@*1$GRQ;(vfsL!!L%qAoV0Swc$*BSrHRw|EF>Vq}LL~)Xn-&gZx}- z4r{;bba1{wsra*Z7WBR;GutRvthNWQMdVq(jO9no!K~4$yrWrt2fgepCELYMe?C4~ zg05fpM$t)jz?On6$4!0`Iz z6WQP`z)p2{iueqSz4qb!cuDIayR?4c;5M``3*JQk*6xO#;>(quu4aexWQ;3@yU9Lj zeJuzq?vnaRJs%7YCVx!+hvt;^7t=i;*Z7wdH)+bMB4cI59_5=Id(P#Szb^d3gQ3z= z&@6+yUD|7bQt|epYCFMQZ-b`$Y$ya*RTcB4S{F1@tk2Rzk5#W4W2DoQ;TR)Je-<03 z&kVt87nX+c#T!A%nsVur)&flX=!>-#3u-mkMwS<=09z@oc{bV_u3k+HO?n6YMa2Tj zdBqD9TQgRTaNDeVzYbM@2IDaqX|xR2hdc0$4#76%fKXW~?ia8xP$GUOLvafI)-CGX zU%C!VZ~ct9x69;#i1K)&r4kDqytR`@cT{*A+f5KkTUm~4Ka~c$!8#D(a%hp!IMpU8 zzU=&bEX|dp{-GATs>Gpp+yC7&tin`%i}6&>|c9)`jl7yuP$ zi%M{hu6oY}`x<9a+NowyzS!hRWE0^9!NC}(z?tg?NS1{&QXYW?+9!F4yV|{~5U@WH z$eEg^Ol0Z5{fj_L@?ZAA9l-On%@rkBH-1$iH z{My55UQB9Q94WhF7fiF9=|x1a_dhdYWwuTh)K*!`5=lp^^o>Xmtlq>&F|iO-tl=9L z25ZFv#62K&2bqAq5nhbGi5anRd~bis>!kPT_M5l4CrtQI0eVgCe5NGrw@11~owK&kHW|vx`_s>2G%HiKcXuoiX$YDFmq6^eOJU9PUew zQT4J?FpGU%>$2}faRA|sqy~>U86t)~9?1E6{loIW4b4YCU*!}L#+PYo87b5dIdcFSAZs4|Mcn)(o!K;=$M@o0d z3*6H!=$##|wTr?qzkl1y9;io?j$x*8L4O{d({Yq5eax{w7LFZDdjv z92|BBtUF>RlT*Xan(-oM#JfHNXd?YFW`2?X2Yo`0H7X(m&N(4LB zNesn$;3*^T6z>*TCPaHwT>BGVtmf2$O#TvU%iF=j>6xr6=96i0^kK=>=geydWFAFl z4W0&!q;I=H{`=|NcF}Bf*%zOy;nUi~db!cMS>27`Oe5lC#_^fXU7>iUKz&=vcTJ!i z$yQ!IiglVcX8h7~qGPP#x$^Ns|L}u*4d^F`ncC(`p8R?3eMQcRFCCatH1Ky)GES|P zV{*FUQ9cWDcYm?Fu={Ag@_E|SEO$nF$tGRVkG<}MAi;RMcJ08sMavxLHYC=+gIU4C zNyzPticg1Xm>0rpTM!96Gp&T~>vvUi?-t0#ZEy6;O3=36?%^$E^w%wya}1%lda?q| z3~!HkxUa%J(?PM~#)7S^^8EL9y=-)nnj&g)c|#Twi=mpyH)Hn_Ly%@BZu$StiUj5n z^z}srs89_}ucdAXeb#Ix(%^v;yPV4A9%wpS9T=NU=+&T@a9l)^c8r(QeT~PlPs@Lo$WH>{)by95D(O+)8;g z1bQ!C8F+nfT*_;mwzx15ch;d_}>CiSzG3*T!}s9aEz&HU3?As@PUAu$HMM> zik%N71RDpVDdvsOvOJcP!9WX#qT}s!&Im{Vo61DeOjue@1Ozp-$GWzr0cJ$m0bU}A@ zGJlILDbENs9i*cHl`9aLY;z!MSR0 zgIi}pEl)UrQ1|I-K)2=!1$tYfLw{c$-d`#Jd5y@tdU)qgV$P@Vbkr%Kof-C>p;3(M z8HLnRLpe7Z-e=}Sf4`wbMI6QZ<$96k4*R{A@sg&5r#_{vmt+OKMR%z)GP$_|U%k=+ zWN;=w)6nB3O`{!gvu|RhL@0&ab2v0i_Bhqaz<&3UvWOk$W-lf0R{Bxx7g z4;Nf&7bWE)vt8rZ%me47D1?-34=1Vn$<-tH7Iv?QHE@(3cCzJk_lr&4^#1T1qfH>ZJenO-6keN920S>e@oi~ zq~>k|uYcsgA>F%!@rFciD(>I)-%HsEa1WN4ixSumOa0+ZQav&UE5xdY}M;p85JX=yBRC2nocyKK2 z3`8D$FrqpghiJ+p_n_wRpjf_LiloE`?WI8k$4rG*nOO)9@2(v-iW^$p8 zPN*Lpguiz3QA}k#11thXuk0k}M7rX&Lad0vT&IOxY$^K5bVJ|7A1w>+fovrmlAvWL z`IC@_rj}3SNGskZpxh)dZ!to%o9%57*Cg+iH9(k{P^}J~IeqIju9s&O|2%+Y#pu z(K;lHbw;SX8>BGDV0hkHA|@5WYoROr&7G)YZv2&%lkzB18*I^ zBc(T-hj9cRS(lIn{A3|zWMCOf?&oknk2ZbVzD39#Gjl%&Z}?!8b+FfrJX^M&dKk)!rbpQYW literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-icons_ffd27a_256x240.png b/www/css/no-theme/images/ui-icons_ffd27a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..baebb63e3fc8fbba697afca858abb3f55bd0f08e GIT binary patch literal 4369 zcmd^?`8O2)_s3^p#%>toqJ#RmwV2==ic*rz7lOw=eaq=H~;_ux21)-Jpcgw zdj+hrf&W^P<%Qk9Zpqf#;p`DH{D0?MO(X38EgThOkGcd9ft_Gsvu%HvtuEu>hrEpz z+`UV*H~;{6<1Ech9YS9&xum*JHt<3EEXwC%pQ=T8(yv*azO(Vv>;9Ne zWscgLks!;lEy|HU1k2)Yfo*W&VC0Z4(6 zACA@7yT=5wfS1BrVl{bLz-K>bVl0}J)K-ON=7oYd?_-yIkEY74{CJGPmLm|)p8QK~Pve?}UyncR3i9*1%n1buaFqo= z376)Dfz6l;*GuFIun45X%&2Fx#i+)wS@-dhQ%t>#V};R9R11H!`Pt$gW&1(E3v4Af z)PmRX7+!vSf}aYEdu1@Z{(ZG$d1O}R)f$ruT;~|~lz!ap($4Ae|Im3BSr7Y$b;9=F z!_#$n5u52^o9v19?$9O)q~f!aIa30YXFL)ZUFE~%!fMqiqyrA=*?KU{=gyKC;IHY1 z^Wt$jwkgm6ea5VjEU5NNWZY_2WnY{&(s38Kf@qB>=FqLF{M!BYZg3PqF}g#{PB`fX z5=Y(87ML(ve)UI4CeHonm#&o483A$R1?eYwX^m$R%8Qv;hd)&-ApO>8re5}c8szU< zdsz2fx0CA)QZ<0RtFZ4)x%ozgQjG(6Ei&KcWt;$Vj>86}#y6VXf6&LyQo3F8^ylM) zCFuHfA0(Y*4{R;WcG?uM^adxBlNEu9?`I3oA^MTeOlnt+G%5TAY<|JkPqGZ|NXZdr zk$Qt4VmF03Vy(bXv{?TE*m$_T1%bSa7%iIH=eL5x9I-xpg8W@FZm(r3(m8kKVO}xf zNOjg5}oKVV$vg`vHtflyg=9=hNu0vjCj)*;C14W9%hYDS_fx${~9c~@7$ zp|w3x{>Od#Rw$tgpWfH|52X83bQfocGTm;RAeGClN=!&*B`%u9m+R0<0b8f>@o&LL)*~)Y*;h>TZcPlia$?gx`rLbn>nr&;V$>2 z?X?iFq+9wY^?V2{g#0n(A6in^UrhIc+!9_=++`@MN{p2e2c%z4+&R}<0eY|t4~EOi zK(h><4jJzSO6A*&Y8`kF{SBJlv*A!|b#?5Q8a>cRi2+M5Jx-%~jFCZ4fuW790$6OF zKQn}CTv-~&7jFcoXvt?x+6XcoVlLKIE~wXHnpj?}0_>!<=hk8}*k8c@AjyQCOrM(^XZ)H2J{Zt<80qa6UDxk&2<5b(^ zg!1$AaWps1hKJhhQlnci)(D2L*(2`cyP1|lx z2T%|a*9ssS>gt4+vQ;eY?#b`Ihx|1GCO~2C3GOZtR1fu3%9^&>0zXka%GZ@d0V<#g zY=ECYxNmeUcG=HHE$a*SX;357;k?kY0K2HQw83VNzF2Ax*#%9XkcNY5%${Pu%VWRf z8rLiBLJ*GIAL4ywXpoP zkjm$93DqFWD+&scw2AC=XoD7V@pgB#ff z1orLPrQG6_G5IPE_yO)ZFqWCoY#-gdyX3@qQ$|G@&xLyIwTVaV39#I~*?umFC&3V< zVxWduAf-43jX#&emUI@}c=r6FM_Y;Ih)XMN*FASstmGSnh zlW2;~;8RBaDZVYRY^cttgw7|Nc+&t88*2ye1ow|3yus%?RF9~K|jL9bw7 zB*b=R<)=e+^b3)-Er=wJnO;iw^S`RKcMIg|zBl@1C3stZ_wbeq>g$&4Ifih216h$~ zj&p!N+*jq9>7-cmV8GVa`2l;o-nP2Q&5^Zve4z_TB~Y!Dn{j(dp$KzR_kw?CMH2l8 z`ud_GRJfL=-&#M6I%~cXW%$6EU0!u_4>X;l0gTJRclzyg@~%qS|K_7aM?o}h5XPta zyxQW#ef+50c?0@Eed6i4-I`)Nu5d_WTLquyXpdNt7hDI-DV2(6_Aa_Yju?dt?q$51 zf_)dS48FcMF73TeTU;2fCHAG^CA>Hy18#w+tgZ7@?xfxd7}`v&KB1O;_&`wIb76Nr z)!vs9iizi-DdmsPvOJcTMMH~*V-oCj&j?Bao6AMhO<7t`1O_*D#JRPl17^h70^G{7^M@{m|6w0y zsOYeCi~jC2bMjD6>%16#_~pUZM~mQ(??;AK8!BwaJfcq~!u{SJ8S0r-kxr6es3%a^ zfpX{;ZDCYGy#@SHZz5IiJYX9uT}eMTcWti?M~&-JB9q~-ZT|H2u^%hg_3FBm8h9|m zH+=Wq!V-8sFc3I{THW$HIe}JStLN2ZXc&UK4|9r(0*hAOOk>vA)cL^k$eyyvz=!&S zA4_c}@s7(7b0!n(ri&kPOA`e=5TDv~nQ0Qu+G4JL_twhZ0jiL}G(1ro@T>D6Y(Z~z zvS5oXIo}vL9jvPf$qE$N3R7Iv!Q@{yXS=pOvTx+z2cX(^zjgj%e`f+0lxOF8K?^3WmyoP68J-qWLDfd%E2J)2f&J6p`@F?2t zjAB}uk-R$%=R0#^V8BSSGM?h|a=ln+sI;|v)W-74P$clI}+k9vGM|0=}Nn{t+LN zj}0lakCt|o-L7?N;e~Ng6hlk5iOCxN@(pnQh21OSjhtnNU2M5M1L9M6{gyu8ceP{y zosxEY6x>Vum>Rd8geZq~R+0?QdYQj{la-~$+nup)^&~uEJrVS0fqP~K+pnAcw!s>p z$-xF}c>7t9X6H$%&?>#{ijD zpwK$DS9N?JezSVhO-#iVfe&_yE)%0tY6iVotqF=~xUa@BpYe z15p4UjHpe=!<+NTy~sIS7&k+wwQ?eOBlD0ewG{0*nE?%f0T~tFl4Q3J!flauS==b& z6Bm;P^Mp z{Py4Q&hV_4XtqYN^W_`w+k)rhb~b?0`@olx-tL`?jy^Al6YC*)T+WVdbJCH!2^5B) z`IoOrC`Z)XJnS$mL4=?W$fNVTni!v1yl-gmvRvcKS&Ye9DdoTK@2m}iSvDQDm%4E0 z@TJD7c1V?!URM7+t?f3)%{X(6JXg}#9TvGQyX6n(^Yt0NX;>vDPcr~mICPooLWA_` z<1A>FuXr|C)dtDr*PQ++Xs5WePWUB&gBj$zZ#BIY%?jDdm>GhyoYoyWicarmhKc`c$I#boY<8)GFoD+9l*|GVoqwb&K)Dihj}mz*mp! zOzn%{WgLM=)+OZtKUqkbnHa{B$2siJqfNi|Z;|rH%stM*8b26kAMCYY&NHwP)6l8y z7UVx_^sgR$Z8w!~foS63FCP_d7NQ@4m$W&a4+pb@c6L8rWcYppH@1D~kD>t|gtcG_ zy#@C|!VO9KTY}G5e57qp?F4jRxqq~@h6^?-cvD>ySwVLl1N*ccEK*p*>Fw_@ND$?4 ok_xuubz<%I+0K1Z`+LWvZ$3~$+A!Gm?^hpSc@||}WrmLVKlf*soB#j- literal 0 HcmV?d00001 diff --git a/www/css/no-theme/images/ui-icons_ffffff_256x240.png b/www/css/no-theme/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..bef5178a9054c16582876bac57017f783272e750 GIT binary patch literal 4369 zcmd^?`8yPD_s3@pGj_w+*U6H7%U0QjR77J*QjsAo%D!YBW@O1;scbQ1jjT!5jATuS zWGpjA6KRZ{!Pve&pXdAh70>I3`<(O3xvulR&VAkQJHZBdk&9iF9RL7uS(uyI0RX_` z6tKz)Iz9;&mv)cCl8u%9`J?|OmP*JO$AcpS?T}Xh!q8L9tTyeBv(%*ReGzw2qI};t z;Rb@H=9eUIoYb&WiPetBc0TAE>N#yD-qsXR@u4{7ZRLA~1Dxy%JD4f0(CuYGwdYLk z1tagsXZP=qm>&QDJh2vLCiWq(mz-1FrW$y`edgtJG0#=QJ!m&9&)(a3?)h-syE0q# z?P#FI_!jBN4~${;{MO;g}UQ zG3d+lNqVdW?d;i5#SBg*2mQ!Rn>(amT&5v4d`jyu6+_vuxMGMIKj9N32D$`#BPsq4 z&H!{>s%@KE0gW_Hv;f*;8lr>_pIAQ@fn70`iX)lM~b;0%IthmkCNRW;1#Bl3u4aW zZ~`YcG08^(#=g-XUjMP$u{=5}{br3p0j{%8ct}0%c5dfz|9@!Qi!6tI!`h+yA7E)Z zJn+pl(M`4lJ2yy^I6~pY>FjC#sdMh}^se$@VnMaaG{PQ>@Mt|4=5=FE@b}Yj#d>l( zp4jAXfV^PTNaR=hCeZIRtFSH37;3xmUxT-X7qRQqRDSDzcRwf+uMpKCYAcj@3xTC< zXz@=PF2DIJC>`r|^jk;L@f^Px;*!*}+|Y8=w%lx^Lb1jkv=)(P{W_K(F~@F=ROKDZ>ObgXV=mn;e*Wv}!4hQs zrZ<8{umiRhWI1l~TX=zzh)D{-gb%X?7vTMf7sj=#h8iTkd{*Bet7n<|_atRUW)ZrB zA7eI!*kdd~5R_>D0mx{$y#+vl@{K^-vOyaIe((yk@a6=@v1a!}7`F@zfM zQG%>GcJ=D5&7V-ti$ajzvp|RpDi@Xi9F7T!erF$O`Ic9l6iF8EO6t6kPu$fJw{LAv zko)2mUjktP!+r)G=#*``Y>=s1k2>FwDKC$IziTEBlvM`7O^fX_t^h^yKlqX|CG2Bh|SzC!9 zu((_57v*9wG?@4)`5#(R)?dx^GP%aTCb>zIRu$psmmUq5l`+lI zxjUr27D$!vE~|Fn-1Ro7x-W)9FxAyDUu$%kMvL{Cdug%i)#LPZS~3)6Wa-araSodDkF`W;re(7n$aoPt{f05OTqjG_6JJD?_?-WBj342T{x!u z!1T_qm`%Z@#d)$x-@+guJbmlvUZ;FzsO|+=&8EfVPMP z_vq>mTPZbRE#{)T2 z)0FYd19#sOXwPcF(WXx^=S<+#78l)kf~V1H!O_3 z4Gj?Y0M{R60`^9EQTirk_@;@y{b{e$-e)^*-{qb(;X?%IHFxl>vPj}Gt)!^i&1nD< zT>M5pSY1sG-%_@Uq253J!{?B%#@`qy#5Kv)C5-H$oJn5OGF{*s5sUP3A&`LbC_F3R z7ZBzX6@yv!wN}mi%5|2h5n_K)aG9S?#7atkvqw)frHAN@qD@M{m}*R)V}8hCzUCO! zEGq>w+t;@(`(73Y;ND7V@R$?9V(62BoF(fYmj`cYKKUtc?YH3%lE)+m_)ujFAMdI^rB5-61b< zPq(0NcBIZO3dQ*GeJ^{k0ZBNCo}!zwU7ZsV&Qe(SH`w&+#X5xg53~52C@HlQ3Dre+D993b|o>mpw^$+9QG*SqJ#{ zZQCVXW0lZ(%J#Sct~wBgk=|?<)xEpq$Z=a*SqaC9eCoN0L+huQP=HD}JC-RF z$$IcPJ?{+f7Dy&UdrVyWGghqj%z{k*5=-m5p~D$+);05~v^d&`JxUSbH`%)~AK-(8VFJ%N;5 zR)7fAQuSKvhmq&aRw4}^IkCy9Z0<45WUB*XvvHliJDohM5_W%hNl}qt^;`If=|0c4 zSTS#33RmucUSOYCT28lyD7Om?+}KvZt1;FiTIdPW260HH;26D&F5n}2!Gc>EkA^_s z@_6YwwOca*Zc?wrzZv_-(s#+gkOFVoepysi#JD+0b zLkdC1u~QZECT5wR%E_Q0g~QSDb~@(-B!JE3B55Yft)~Kl8arZL+tL7JQPzO#p;|3} z3?I1O@rkln)Wb!tZ&j*^7WfK)Jx##GnZd_z*in4exkHLHU^?5aYNNcN%VB@nhUv=M z%-te?`b-_&)lxezhaG->^zF$a=+lSMq1A>8n{oH3(+M!&cSi=g##MyV1Ss+u1bUzp zvPE4O6IW{iebSvw(Y*-R#z#_;hn+kZWH~6X4 zdJ5;T3^rphFs?edA=gw9z$3BgO=ohGNahw}^@o>c)(%ja2%_Rfv;e<54?-7oSEur~ zSd;RM5HmqK8bH29UcAj@z|nLU5UUei1kyC@UgR?@h4>!4fh%D@TRMPWii}iDN2iQY zFht4@vE{ZbQc9#s8)ho>XX2<$ ztO^NV39<9eVN*`4A!+P)-%rq`oqcM?<%9T!e^-3S4NQC(j(?nKP%th1D$d(=xG>n0;ZiL*Ut)#`zN!g4C`?*bQ@jOo`&d)HtE&|qf; zHoW^HK(+NCnX{yy(hnW6r&{|w6x1JoBTVC*Xh3as3feJc*CFqPht-F+GMxZqSTcpw zvA(I}{rHE)i)L&hrT~1jQ+RbGGP!2Zi^U4BfP(p`pYUEkf)v$w@i-=8RF6m71El6| z18;ufz`)&mg0Y5pZwlt$>%W(>6W|^!F&8DUAC~&lo2oFkE{V3T3QgsYto**gNnv=A zf$Ty#t1HHiS4sLRwtb@EVY>xwsiE_Z5ToJp}Xh$8t;XGSfDO7s4uy|-Z>>OAg zbTFzq69;R~BlaTZu%TRZ?bgc4ppA?}&XiJ=!&EvX7z(6Ud{30wJ_xfx*k*DejZUc_ z9fX%S`6#B+UjPVyP;9axa^^ST&$zm{x0UlfRJsaQuQRM*`NL2GUNMy z%X`DKo+4T5MNU_5eP|1slik?>O6>z*M|in)E;@L>8kt-V&gFD+Xq%IY*o`OA1;$XgSWr@q5g&Teiy|FXrjdeNr)s4DMzCuwdva=cNXz)u)+| zOdqiKXJa6fgYEEhhe#cQ z#X3Dy-tw!2F}kh^eD+L&*G%`%wv;NR(%L1&T_WPa)iWtx@pX%FBNhE3|ADt2+nLfA z&O<)}jjl_`0)8Glw^^^OcVYH4D;?KucQeFNcHJn09tQU8ehd1~s;Q?2n`ZABDD{3%msO zg2N05dRqc7SG=Wc&g}SiUwe48w1y2b%zs;56H!5P83%c{9W0Vq!f5U9(Fi8e;S>dA l!Q;r%?Y*7ztoF~2ao>D^xRgPV&GAM literal 0 HcmV?d00001 diff --git a/www/css/no-theme/jquery-ui-1.7.2.custom.css b/www/css/no-theme/jquery-ui-1.7.2.custom.css new file mode 100644 index 0000000..9d7aa08 --- /dev/null +++ b/www/css/no-theme/jquery-ui-1.7.2.custom.css @@ -0,0 +1,406 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; } +.ui-widget-content a { color: #333333; } +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } +.ui-widget-header a { color: #ffffff; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; outline: none; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; outline: none; } +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; outline: none; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; } +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); } +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; }/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { padding: .2em; zoom: 1; } +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/www/css/style.css b/www/css/style.css new file mode 100644 index 0000000..f52228e --- /dev/null +++ b/www/css/style.css @@ -0,0 +1,378 @@ +/* body */ +body { + background-color : #FFFFFF; + font-family : arial, helvetica, sans-serif; + font-size: 10pt; +} + +.ortro-body { + background-image : url("../img/page-background.png"); + background-repeat : repeat-y; +} + +p { + padding : 0 0 1em 0; +} +/* header */ + +.header { + width : 100%; + height : 62px; + border : 0px; + background-image : url("../img/header-back-white.png"); + background-repeat : repeat-x; +} + +.header .img-ortro { + padding: 1px 10px; +} + +html>body .header { + background-image : url("../img/header-back.png"); + background-repeat : repeat-x; + background-color : #369; +} + +.info { + font-size : 8pt; + padding-right : 1em; + text-align : right; +} + +html>body .info { + font-size : 8pt; + color : #ffffff; +} + +.header UL, .header LI { + display : inline; + padding : 3px; + margin : 0px; +} + +.header LI { + color : #000000; + font-size : 8pt; + font-weight : bold; +} + +html>body .header LI { + color : #CEE1FA; +} + +.header LI A { + color : #000000; + text-decoration : none; + padding : 2px 1px 2px 1px; +} + +html>body .header LI A { + color : #CEE1FA; +} + +.header LI A:hover { + color : #CEE1FA; + text-decoration : underline; +} + +html>body .header LI A:hover { + color : #fff; +} + +/* sidebar */ + +.sidebar { + padding : 0px 5px 5px 5px; +} + +.sidebar ul { + margin: 0; /*removes indent IE and Opera*/ + padding: 0 0 0 0; /*removes indent Mozilla and NN7*/ + list-style-type: none; /*turns off display of bullet*/ + font-size: 8pt; +} + +.sidebar li { + margin: 0 15px 2px 0px; + width : 140px; +} + +.sidebar a { + display: block; + padding: 2px 2px 2px 10px; + border: 1px solid #fff; + width: 140px; + background-color: #fff; +} + +.sidebar a:link, +.sidebar a:visited { + color: #000; + text-decoration: none; +} + +.sidebar a:hover { + border : 1px solid #963; + background-color : #ffc; +} + +.sidebar .currentlink a, +.sidebar .currentlink a:link, +.sidebar .currentlink a:visited, +.sidebar .currentlink a:hover { + border: 1px solid #369; + background-color: #CBDDEE; + color: #333; +} + +.sidebar .category { + padding-top : 1.5em; + padding-bottom : 0.5em; + font-weight : bold; +} + +/* sidebar installer */ +.sidebar .install-step { + margin-left : 10px; + width : 130px; + padding: 2px 2px 2px 10px; +} + +.sidebar .install-step-current { + margin-left : 10px; + width : 130px; + padding: 2px 2px 2px 10px; + border: 1px solid #369; + background-color: #CBDDEE; + color: #333; +} + +/* title */ +#ortro-title { + font-size : 12pt; + font-weight : bold; + padding-bottom : 1em; +} + +/* content */ + +.content { + padding : 1em; +} + +/* start footer */ + +.footer { + font-size: 8pt; + text-align: center; + margin: 0 auto; +} + +html>body .footer p { + color : #CEE1FA; + background-image : url("../img/header-back.png"); + background-repeat : repeat-x; + padding: 2pt 0 0; +} + +.footer A, +.footer A:hover { + color : #000000; + text-decoration : underline; +} +html>body .footer A, +html>body .footer A:hover { + color : #CEE1FA; +} + +/* tables */ +.ortro-table { + border-color : #bbbbbb; + border-style : solid; + border-width : 1px 1px 1px 1px; + background-color : #ffffff; +} +.ortro-table .c1 { + padding : 0px; + border-bottom: none; +} + +.ortro-table .c2 TD { + padding : 2px; + border-bottom: none; +} + +.ortro-table .highlight TD { + padding : 2px; + border-bottom: none; + background-color : #F9FF93; +} + +.ortro-table .c3 TD { + background-color : #FFFFCC; + padding : 2px; + border-bottom: none; +} + +.ortro-table .c3_marked TD { + background-color : #C0EDBF; + padding : 2px; + border:0px; +} + +.ortro-table .c2_marked TD { + background-color : #C0EDBF; + padding : 2px; + border:0px; +} + +.ortro-table TH, .ortro-table TD { + padding : 4px; +} + +.ortro-table TH { + background-color : #CBDDEE; + border-bottom : 1px #bbb solid; + border-right : 1px #bbb solid; + text-align : left; + font-size : 8pt; + font-weight : bold; +} + +.ortro-table .install { + background-color : #CBDDEE; + border-bottom : 1px #bbb solid; + border-right : 0px; + text-align : left; + font-size : 8pt; + font-weight : bold; +} + +.ortro-table TH TABLE TH { + border-right : none; + border-bottom : none; +} +.ortro-table TH TABLE TH a { + text-decoration : none; + color: #000; +} + +.ortro-table A { + color : #2b0c93; + text-decoration : none; + padding : 3px 5px 3px 5px; +} + +.ortro-table A:hover { + color : #ff6c00; + text-decoration : underline; +} + +.ortro-table a.anchor, +.ortro-table a.anchor:hover + { + color : #000000; + text-decoration : none; + padding : 3px 5px 3px 5px; +} + +.ortro-table TR TD { + border-bottom : 1px #ccc solid; +} + +.ortro-table TD { + font-size : 10pt; +} + +.ortro-table TD TD { + border-width : 0px; +} +.ortro-table INPUT, .ortro-table SELECT { + font-size : 8pt; +} + +.ortro-input INPUT { + font-size : 8pt; + background-color: #CBDDEE; + border-width : 0px; + font-weight : bold; +} + +/* Messages - errors, success and info */ +.warning { + border-style: solid; + border-width: 1px; + border-color: #c00; + background-color: #fcc; + text-align:left; + margin-top: 5px; + margin-bottom: 5px; + padding : 4px; +} +.success { + border-style: solid; + border-width: 1px; + border-color: #3c78b5; + background-color: #D8E4F1; + text-align:left; + margin-top: 5px; + margin-bottom: 5px; + padding: 4px; +} + +a.toolbar { + color : #808080; + text-decoration : none; + display: block; + border: 1px solid #DDD; + width: 28px; + padding: 2px 1px 2px 1px; + text-align:center; +} + +a.toolbar_hidden { + visibility: hidden; +} + +a.toolbar:hover { + color : #C64934; + border: 1px solid #c24733; + background-color: #f1e8e6; + padding: 3px 0px 1px 2px; +} + a.toolbar:active { + color : #FF9900; +} +/* Start tooltip */ +.ovfl { + overflow:auto; + width:500px; height:150px; + padding: 5px; +} + +div.tooltip { + cursor : help; +} + +img.tooltip { + cursor : help; +} +/* End tooltip */ + +.fieldset { + border:1px #ccc solid; + background-color : #ffffff; +} + +.legend { + color:#000000; + padding: 0.5em 0.5em; + font-weight : bold; +} + +#toolbar_menu{ + z-index: 5; + left: 10px; + position: absolute; + display: none; +} \ No newline at end of file diff --git a/www/css/style_login.css b/www/css/style_login.css new file mode 100644 index 0000000..c33b8ac --- /dev/null +++ b/www/css/style_login.css @@ -0,0 +1,70 @@ +body { + background-color : #fffff; + font-family : arial, helvetica, sans-serif; + font-size: 10pt; +} +.header-login { + width : 100%; + height : 200px; + border : 0px; +} + +.header-login .img-ortro { + padding: 20px 0px 0px 0px; + text-align: center; +} + +html>body .header-login { + background-image : url("../img/header-login-back.png"); + background-repeat : repeat-x; + background-color : #369; +} +.footer { + font-size: 8pt; + text-align: center; + padding: 5px; +} +html>body .footer { + background-image : url("../img/header-back.png"); + background-repeat : repeat-x; + color : #CEE1FA; +} + +A { + color : #000000; +} + +html>body A { + color : #CEE1FA; +} + +A:hover { + color : #000000; + text-decoration : underline; +} + +html>body A:hover { + color : #CEE1FA; +} + +/* Messages - errors, success and info */ +.warning { + border-style: solid; + border-width: 1px; + border-color: #c00; + background-color: #fcc; + text-align:left; + margin-top: 5px; + margin-bottom: 5px; + padding : 4px; +} +.success { + border-style: solid; + border-width: 1px; + border-color: #3c78b5; + background-color: #D8E4F1; + text-align:left; + margin-top: 5px; + margin-bottom: 5px; + padding: 4px; +} \ No newline at end of file diff --git a/www/img/add.png b/www/img/add.png new file mode 100644 index 0000000000000000000000000000000000000000..d498807f3f7ae0e165e05edfbce7fc1232d78a87 GIT binary patch literal 1141 zcmV-*1d98KP)00?wNSad^gZEa<4bO83umcIZ11KvqQK~zY`wUke6R84JGO`nw`=_4hC`N8@3CNSW7W|TkFIPv|_t2JZlBeN~h)->kc zV)OA=2@)aFBFps@&&`VOZjg?HkCdp4nZv5&!@Skr_3xMH?Ctpcl5DKoTyd|+pff0EoHMea@0s4JZM8ic7Y7HIs1-G<0y172S8`0LDRiJKja$BF>9#E$ zTi?vgPxjHi_*_U#y=GxTSmscg*8r`CCnVgM_%l=z?8Lk;l z>1C3dF%H1AopfO5ZQQ`+^29|BT{+0OjH9E15mBHFKr^!?=D^6=^m%)rY+e+`9J>mj z(k#t!dUt~WG)I~V{|pZeZ5?@`99j`88dvf}%abgrzpu9ZTLmCy#aYp~l8yzPG)9`N zsy=u(^55MIZ#4bv4%YQwJhAy7_u)=qeQGAxKd}Cr_`Fy|WY)*&{IuWqn~_3`n^3kELx{V6p#iP#;Zd>#EqrUd>Ll0m31UkT%B4Jr;JUj-n100_G8Zia2 zKuiG(#1h05YEN1HnOEF(CP3f^V&~HYI>6Jn322`{7X*IIT;}v&rxoI3b7Ot z6h#6c0A(r&Z)?$s;qNn{8PHhU$mH}SBbjU5a(+jUiiR4NLIPC~2@0fQQplOboCPz_ zsR#PRr&MhPP);I^rfHlzt@qpCuppo$7mHwfqg zSRk=rO<7bRAr?q%Tco0FDjJCdJC#d9lFCi$xQ;!ZhsR@kUY_^Ny?5?8EM`(-;z+PS z;z&ojI_K*9egFS=^nLI@UdrPxMt^*&b9_8>diucF$a*$fn!S4CTH-J9`^2i^zX4eG zIvjiR4fl~_&fh%q?4h$>kH_DucB#7L)=w8Rmwps%*y(WgNGT=h>Ic}lWm@2|P~}D+ zimlr>`nDAnueYMpE; z!+Tnglf5S?R#e6&Z0=FD_Puhle1+)F>|OwqVk7Ku)L-&U4%#+wlXp!p^UTxy^32<~ z*LsQ0#z}pgpgF5>zVRAAcTuz1Qsi&AvtSYBw2EX&ot84GRU+3N< z3i3r##a#2Y`uQgW+*U057U_ZtfWvMl+!tb?Ka982i!>=10;B}B345=1+=X0)s_+7L~L z69-)^8ZRQc1LK_`$IFiZeyAdMD!jLJC)1Ey5l)R2S-cmaP?s&w+eKBIt-#H;RYqHl z6maO-6U-~mSq=``-#!7sT>trvsTeOf?|N@8>VHi^(fqJq$5o~3?{0jpe|p4kcIjMS>0x-}Nvsz0E^EYtt+Za4 z)`W7+K(U$maL&So$vMA2S;@q*;^wYyTB^!adP}`oNv{kC2cA|u+AO2SJ3!*)c9~?Y3=pF)1BaS;T0KBOHi&+ z->y(xual0|iLW$jn_K#3x*{VbUAZGvxoWD4=yt}4U(-mGLEm#^N`p&te@Ne`RQ^8R ztT&DHno-z}XoX}%OD#q9FQRp^l7#!)uv~{6{Hyo;$3y?D!hw*(^p%P(wdJOaZNcUa fWHqSp|Fr%I-{Hq7v}tdW00000NkvXXu0mjfc#_i3 literal 0 HcmV?d00001 diff --git a/www/img/arrowdown.png b/www/img/arrowdown.png new file mode 100644 index 0000000000000000000000000000000000000000..4accf927bed9f998040ada65a35695bb758c78f1 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^96-#@!3-ps+W+JLDVB6cUq=Rp^(V|(yIunMk|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XI0Jk_T>t<7-_p_onv&0MrCXRCq913h|0^A-< nECO>F1soiX9N|!6VB%rmQep^;zw7l7Xas|&tDnm{r-UW|t_U_c literal 0 HcmV?d00001 diff --git a/www/img/arrowup.png b/www/img/arrowup.png new file mode 100644 index 0000000000000000000000000000000000000000..c82b76ffe2c9d41a2f38a1c1115013cc0852f522 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^96-#@!3-ps+W+JLDVB6cUq=Rp^(V|(yIunMk|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XI0Jk_Tw7XN{{R0EFVdQ&MBb@01yl}4*&oF literal 0 HcmV?d00001 diff --git a/www/img/back.png b/www/img/back.png new file mode 100755 index 0000000000000000000000000000000000000000..6b06e2c81d491d79ddb806f75bf3a34cbf00a38e GIT binary patch literal 1089 zcmV-H1it%;P)o&Wz{|MOnowd+f)g-Zvk<%lS)AQYKv z8&hKR;`-1aqb*sh4_3B_jG()@Qi@=#zT~0>MbI`jV!;qxvSDj!riCw4cdwUgx_iAZ z|MT{L`k+<|)Em`@df>o0oO6D^=lMP7c@FSjH};or_&O_Lpblx~7no@NezoJSltA-3 z4J72v-dwBk-g}B$a|%6~-Ms;tnZQ3lklg_!Rds1;&c1EiOSc}_cbDhu3zO7)DL|?C zwlYCxrwdX3@a>y@Zyju{Tw7PW&XtwnhSm-oCpATvCvY8Jf0M^J@IYPJo_F4^@#gz7 zFc~4FFMyL)PC80DeK45;6M)G8Hv=p)i7R^}s}LMsU+nXCJk@k(?bA&aYh2kLd^`Y5 zMSz1<8kXB&`I%OIUcOZh#>^!G%?QDHJ{||2U*Q!UDowLkyWd}3zvsz24BK?${XT~N z5U|!O;jdN*&k9TgVsNme69HhDofl|3b~*Cxr;p?;6M_HMk`nKcms+cKKC^eTaXCon z>SwqXC1@cKXA(ox1g!xp#{;D_w9-&g!`NG=ea=Xka@4>g;z0B40H7ZrIM8|uqF+~vmc zfdz0<65JLGfLtJw;J?j9f0r_IBXyPsOyLOZY#^J-nFX?!WQ`O8;Q`OECuNrO*J`?Qp3>>lvGes zK}wDC;&ezws})+y(D<1Dx&8akb%3F!VaGb$l4;?MQ!xzA+HhM84{q=v$qBz)x1q@m zA_5UX6CpUqk>q-{N`A5b`rM%x+FtK@Hyn;v?S8z>_43v%96cuxm`Q>w!dE>(I@UEf z$}Dq)7)&w%W->@}*hnxwl|rj%xiU6>q`AHQ(kp{M&NRH)R+-kay#RebM`BOLKTM(wzvMJpXTencJAjw!kt@(0Fq%{`dAPRq*?PswvYC00000NkvXX Hu0mjfvUch> literal 0 HcmV?d00001 diff --git a/www/img/copy.png b/www/img/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..1eaf37fcda341e21a2324b0552a1cc2e0897886f GIT binary patch literal 1143 zcmV--1c>{IP)D<1N2EmK~zY`wUtY3R8<(qe`n^lP&%|kXbJ?ViVqS@i6od9<14Vk z9Y&)OjmF?YR~UmkRCexwg^47_xG-@ekqs_TH-K(L&}bq;NPy5nTiWS#X71yh^LKI1 z?ab5=bm5nr+`0FBkN@}o9s}L-%Y<}AhnQW4jNgwD0~Rq zE})WoNIj$uybqU7F*v~X*N+_e;O#wcX$d+J47{M;%3Q+M*Q!`o+qiCY+Y=8C_jha7 zYAYzbq40semIHS0KUOd4^OD+Ds;AO)TRQalDcx!Y_O8~YbCXgM_<+noW+C^G$7eHj zw2Oe>dT3inZq8*a#7s+r%m$_02SU3IO!C+}&kV0#zXJ)G4t^o5>7#FORiH+Yr%lU$ zmEd#htM?rJ_`sD-qpOxLRqzV5%D~|-PM%Ews3t3S?-(1pZ)C7X*+%Sz2j}7B17q70 zw(MPrb%XN@DYut(l>3u}YX7oenVkCaqxq5H0lX|%ry9XC@a>O(a^U5sNsGXi z1b|2}YZfF(j4>$oy$pEMDQU%o%2wjN zsTgC1b{>4UudlzNPTc`$&d*X?{}3W#F^2lJ-_M$!(mwj8sTec1dfld71GT|b1PLD87kX*skn&FE401@$4~#pSKnRW z{k^+r7ahlCRw!(s*|sAQ|D;3Fz?P}|P9O&~GvS=b>rDxVkZe5qt#Q`6pHRCwBA zEGaHx`1_S%Rx5)Ab?na*noqBy+Be%E=oaBnN?awfu;m_}13~~wz z4319D+855BHwOxygc$%3Kn#5oCw;zn{pSC-pFaJ6_4fV$PhYr)yJ<49NgRtJV0l&{Q1kk za^WHa!;KpZ|6jdiU_O3~f$`F1hJQfCGU6f(){aintjtUiEX+&{Y^*E{00G1dWEiO% zTI(ywOE55l0`&K925`V?YB2nhl44-GbC-busPK=xJOe9G{5K0HYyXB{jAOHR88v_F)P{BVAPKG}U@<1CI8JG_rW?+2!l!4*pONRf?o`apN zsjb6cU}0klWa@zU00G1-Cc^g!82{n2`gS6U;@k|3K)3z_IRR+;f1u5Ol~ov+uU}_i z272SKrX~XyFBik}Pd`|X@7?kJ*RNl@00M~V)2FY$p4`5?;p~~q|6l!PU|<0{<3Gp{ zV1WKnRAl(0tOPWOm4Wf&M~2_P@L>a*ZDDQ2sHCYK1Z4671Q4@`ARoiGFCQK;un8r} z8alBl3oY96aWhW0005=^8f|^{Qvt<1$snxaeAB9U zwwj*47{k?j3=DUk{AYOg>?6a^XEz!CJv++q`}wIqU!I?R`TotLbDzKd+5rrzjQ|0} zs3ao-j-G#ie=%@y^41Et^f$c`aAaV5c$9(Z#i9Q{U!MN9-aGHS`|f!cm<9#_D%uG#sQd?M0PwVYgOWG1F%xAbLe7{70RSW> zCO);TuyAlI5Cs5ey4D&rj}da}!UzFHEt#U-w29=edxW%)5b|7J?jYvEdLW8iTum@9 z^7Hf6l`R2s+d;^QFHcYHq)dOda(}bg8kPc73gDIHloo)OuC1wUTfGoi5f4N$E&%XP z9rtcYN%v>Rj*~*8@rvb0juQZ=*_z#ja&mWZs(ET*^XAR!ZG~GJmKf7kavl#_TCTN~ zm6dPhILeiL?x$I`SDOsmmh$r*ftBq4`H+Ef9TfoxCSkNtfe4W9QD7_cZ)gYpbfM zpQ!xtyP?d?%;I@BmzEx?{Hf7FZdfGJH%`b^Ga-l0w2-{Kb-&CmBC}z`hUC{jI8pA^ z>Or#<+A8*iV)nTKf z4$f@0*qWQKx4GSJn;;0{#ZA5-f!f7sHi;AXSIF~z%!Qs0|2{r?b`bG8^tHbBl9EdL)(OW@AMf#S))}3B_7nB?_TC-7H{w~AsDD8p6+1SzE(AH{=$X&QHSFb0E6=ih@wa=7K^E^?N)`|+!0T6_ZC42%6XoL zBuWq_0`QEFVZeMFH!s(s`QkY~=o*&x?0!{VvbP|0zcKJyQdb|P8s|HD06&?}rjv6D zg+gmE7}n@?;kjy+`e~Y`V>quj=yZf}3gw$mb(!YbWAIWi+8Y2#51A6931bP8q zqaRJDEz;4kW*;K^M>7|=hm`6?YUQ25U`msf>!K~zY`y_I`#lvf$Xf9LzYy=FI?gxo-Kg))RelTxl_8jBz_ zwIbRn15UBF4yf&jN^Gl^I?h0~GDR&_1RYx-l#aF?TA_3jNDD}Uguo_*1d@;?ORk$_ z18m6k`*vUdh%glFAO2yVnKS3iob%3ep7TEQ9Jn3cxThCv`+cMAS^X6OVBPwk$>3N_ zK5P;zd)wJblx~XCV!Mzn>K; zukDcG;0sc}HBJDx0+>7JCI8&Hg#{@olkj-sC@xMn_*8uV+2c}n)RfxurZk_62*5-z zjI$j+9?&}omK!8^$VL8=qNkjjTl)e3i$X~p&Z{=ip@8Agm67Ra(kBd*l zs@g57?Xu)T$dbm8C6{|G3HC;1`SRkUw=~>VV`IFV>W)1H3<14-HYm7%yS%ZlR}Pe! zaRMCI*PGH3FlB3T`K3g?FcaW$$OTZJpR+^O|GJQ_Gb7B*%g3f`*liH+g`@@MhL}Y*L3>rI`zTxJedC*R=qeWrJ`mg zBS!t>x~2+pCeJULmz6q<%N=D>o`baM2B9O*vu49Jk`q7VU+**LSB)%h23zyXeGB zo33JphSEetS24@bh-oOLBo;F?F%6}-eyy+RtiSSCP2tnkQO*s1D#66`UtCJPXY!Q! z%koIH>m)nU$eo&rrWxoO7&Rasd%?`=X1}D`SqOq z>=#{DDD`mt@T-U5AIj%_a&6|6S=%PeTjG3TrH&aB%psG(HVdzoNJ?5d4yPSm15JUZ zfv$tY0nsQ7cLo^q|B2j;Q%o&-fPS@rYqfQZl)f%6z0t)|yGI@( zZ&H}<)*yCY1j92($G`<*VFfW^_ z<+6oezn8pRo#9A?a92AXPaJM%l-fP7v2wAEw1gmZ9AWgvbxu?#Qxh(fT@{U`=dYam z3D69T-QHv!KqNFYG@Q_%m7ev@^z1B^G1-pYrsHzhX=`cV=f&$NESildFUS6NhLSQj zHNGE`_wC;@W68tn#;7~4va)O+NatNHx|IUjOzjIZR~>omsa1<+EzKb-Rbym$m{5Bw zPMeO)<-~62Bqhe<@wjp5I!cWFxE<6>`zm>7uDcQP*Hmd%?tCZ*iv1pO@sSQ>9f9YX{`NeIw|4 zrrmDOUZ(46g{H+kx~}V*rYWT`*s(QT^3wWS&&Mh6opiZF;u`W zp`$tDqyvei##Cs2AakagrkQH8Nz-X^sOd$eX{r%cZA>VX7k3mZc`+5_9b8y;*#(x} zd-v|$d-{;hkons5q2Jf@%ya(d`9J>y+=^8GHg#u%V#9_Fxh|J0@bXg2Gk>dK0O$rY z5J=F+cu`+hM_a2;1OPxawXE&X``sVEw0&QUe4WLnO`GyAG&RxYix+9%{$1lV6SO7Y z>;(YmbUM?ybLWBpINUc`$wrgZR6~cqE0=Gm0&E|=+3H?yqCKggu1sD!GtV%o8gV*< ztT`dxyJ90!COZ9wt`6pPZLWByZt5VITZ-77t5&XmW9xGjYSF`}28S>*>VaAEV7%=zzITl|0DyU|tZa2( zU!P>R+o}EFhu%<*A*3t@4KD_jil6Y(1q`KgLC>Z~_)t_-ly|AEjh;Sz+TYvLqxAOl z(B9r&U(?BBK4l50ypW-_TV~ZH7&VrgGDu2F%F_D!dQVGpGxc~p^xCy+;TN~Oa0r0u zUJqpf81P@By33iqzpmoKOl6?wREwkQuChKa$t{^|IHrh=C#iJmC~bW2m9_;|bM!xa zSe~3{DJx!gby?>8$Z-Dv#yxIC_{QP$Iiad+4D1Z)SCN|r78Dd@fBO9TTK=cKgxdDw zl0Srbdf-YBcr-b6h{zMuSr9$Z>-C1}>gvjPizTXc%C-`pp%3!w4+T#82ms|bm(0dU32ib;}igy5JHp~vzc|dTt=2>GK1iw~g%sHs$seKe;q} zN#?5$rRT5YqY{WBD;T~0N4UPG@|(^9$KGFByRX(>84(`j0(M<`;+%pN*}JkI&nifW zOPIzYgpgl?Iv_y`OYjCHOjCkTi308Sy2TT%7pj{(hxQ+C?ybMm1!UdAwE5W?ncK7G zr#=0cH8z?$u0rbWhSuSL;PYb8C%_;{h$A6{RWcltBDishTBaFCxp0W74N`pVXN#vA zL<$QF=j7z%Y+JNwQDKyp@A?bTkTgefX2%3Hf; z&6i15t62yJMXgrL5<>JW%d#x<*90l0P!t7V7=Oq;Bqjd%2^V2MZcqhf+-&MKN61}9 zZTneCTeYKVpd7#`fB*pijYh-hd0s7uqI!5}2r5EgnLd3Y%4p;`j^n7Jh~BX=O&}29 zAp{t5y+>e!vSE-ngu3D)`8i?YhWLx9f>AUJhpNlQyhXJTUF4=O@7CRwc}jaCam z5FiLbB;)lW#%!jtEF07u2ddM-ElJ$B6YzHt%brGuQqg$E(Fs5RpxiA7EC5|$mm3-yY)6h9`AQT;CxF16!gXIM1rWD+^X6wu kOG{q|F!RQ@z~KMJpF8P*V^7a;d;kCd07*qoM6N<$g7VkL?EnA( literal 0 HcmV?d00001 diff --git a/www/img/eraser_16x16.png b/www/img/eraser_16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..459d28a2a3f0e6a0f1ba50076ea657171de8020b GIT binary patch literal 806 zcmV+>1KIqEP)L zlif>GaTv#+-`UxAw&Tm(ab`5VD$b`ilayeJZ4UGxWx z66t0TO{#$sHOaD~qGhg`wwGLMTYF(UHs`jp?fkkZ!BUIpf$!b-dA>Xkp9f)#;eU$w zn*kw&u65TR@R+W6ZuGSbAcW8_28{8R0szr{{n5M2Zys};%Yj#HGui2plXFM*?x`}Widhv;kuc$@~5%z!hv#9AgSw}&Qdr#B2h2#H1xAH3P4 z>*-c8G_~xHg7m8gXvsH-yAvQx`yuU^hX|sUZgJEUxjt2+(bQNjpMSJ(Pg7-TZkkxN zy#NR3S67!l@x_Zi8cw-dW6nA( z0El6Lq9i~<2@t1RJ}FCs1S~CT5f4BLiM+sUHkX@Brm4=(&f~#AK)jmgMd|iKjEyK- zEJ%b6i6fz zkT*1!`WyD6s6yqF=TjW@atRof}f2P&AH>jXkwmtqHr`jw6wXGaL%x z@$qqQe_!t<0FVRxfNle=>#(JDI^BuU(b4y_v$H{?(fC}gR<{Cx=#RMn#y$doGQD1Z k766#7QrBzKU-*~$4zEm>LK1!`mH+?%07*qoM6N<$f&|}aL;wH) literal 0 HcmV?d00001 diff --git a/www/img/favicon.ico b/www/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..dd2040d4f20455e679875b2c7cc43536740c0ffe GIT binary patch literal 1150 zcmZQzU<5(|0R|wcz>vYhz#zuJz@P!dKp~(AL>x#F1tKFO8Qa?0bhmHcE<=O-%*sH8eC7 z4i68XvUu@gK5T}0dU}@I*w{Sw_V(5S>OUYLAaK^p%j;ZJR8%NPJr560pNNRahxGJx zHEjBYg@prwc3#%j*7j#+X8z8^#Ppw&lk=;PkWj0%w6rmh|3+0+RWTtU0h@MU_zM*A z^73AgmzOsI+W!lv=syet&HDkwpY`3}5 z;?l3ItSk(4>ujLjzl@BG|5;dAFwEfK;FyFO9Rlndt6*xJ0v6|t^&ik9;;?FL7-obLiL9M z^&bcMiI0!(vyqVz2bxki7Z|^cK->)st3aTC-+=T3{bUE^X93;w3z!D3#>K_K)uS`S z#l-`Zl$5>#-FzJsZ@_r@3G}ZBNF6YZm;=*7Mo>@?&Uj2oNnun30-(BApm+r8??<W6{{8>=@8ADv%Z~mJ$)5fH z#KlKoK03a7@9qEM+79gQtT&gPo-|gSM&^Rs(+g_`&ex z;bVs1zkmG&@c{w|V!$_$KYuYi`}K>##zYlp`(K9F@4qrUd;JH@{s(l;?|=UozI^`5 zaPstZhEJb9F#x>-HV_~HhjWYrAP59e^xyxM6jX-An2oTbA+8jY-@VKR+y|kTQqRQ1 zn87{&D&gRA$BvFQLm{5rTKfQ>0D>3*4E4`IL;eFH9}hbND=Q-dGb01Tf1r!L|NF(j z`12 z@&hRPpJCzZJq*__U4a__5J1pCgv9aBAAcEMz5EGu5zuB}lzazi28x3W`14!<#qn7=*akf!_HB=70YV(F8N-`}gk*OpHuG{#Rf?ego=)!~#G7L1WJ0tjNjr!TA@UcO;?$Gsl>91cufEcLhKO@73*RL7=eg6d1#mEZM3lKnzpuphg_qfNz_+N;D z@izlEHwQS8{Qdh6Yzrt!gVewh&eyLWfvNB_kj45An3tlscR~|X4V!LBE?x|^e|g9DVy1PnYGes_rmp&Nu^nq zCZ(;=wQAHqrp*62Z^W8cBoO3?sl&7X7iiPup03c3M zt2B&D{1Wh)C>=*y#sW{M)AIm=!u(=EUHu%U$jw%4Q2;!?RQPXOHIrip)S4{-1xo-( z3c!OH9|1Tm18`;nth)g)`}mc8FB1UR_mfnL9cKskPa!0yE?f{&#l>99S8Y*`1I*D-Q6wR74SAlf@dld5=wPtWr0qJYH~9HBq9<_)wLdd3Kq>IIRXpKn%%hE}1r zwl>5}iEh@_`L0)2QxPYB^*==T@g{PD&6U`pLE5A{lBUr-H&>OE@JjZjr+bj4ECkDq ztIQxlKgAKuip?kt&9YT3O7w9!u8zjWFGNmGj=6%=3H#5E4z4lB8I8tl`Z-|aXFf^4 zx)>q#T3NT`gireIwcTzv%G_8xu!{GC#O!jkxW5tF|^pycZ@UeVRCgt(cWz$wvD z6vvluJNx<`vwsj$>FqAj zZcxYKpewi8)Ux1^kZgfid=L(2n$2dL$LC#d2L`mSxj8cR)T+BC(@HoHXqe%>naks? z;PUzUTpS0gr6rEKc5P>0#q3xgbC!Vcquccq)mcM|^jbehc9>SHjhvI!P*IWm;j8sB zBK}Q|%HPnn^p0*YD8ofF&%!LOEMnvxo tw9c@+6`TrhDwRb=-g11Y^byV#$RIN6e(AXfZ9L|~A!$>J>X9;2{~yY6bYuVk literal 0 HcmV?d00001 diff --git a/www/img/forward.png b/www/img/forward.png new file mode 100755 index 0000000000000000000000000000000000000000..9091c4e0e99adb3f07152ab4c42e0a1c8f4b9fa8 GIT binary patch literal 1118 zcmV-k1flzhP)jKWXcMS zEYZLqFtLW|dcoc_P^eJIQYKo|(x?XcMU=Em=mnLeZQ8<2W}4!j$7h>+o;@%3bKlqL z!|a3T<^sP&=i3G6;&+{M{m=ive?8QQvToQgfsCF{$UaUz|J}aPk0~@Smo1y*J!l>!Q=`%?0>j9&+JP0T61DKzkwr zS~!!km^rh?yzlPHs>Y_h>%ZT7@~)`2b{*;EN3RI*T=Uhk(wrMD(-09sg@8tf$)GyV zF;Qr~>@+DafJY|e@cz5ga+^1IEZn@Mqx$UGwM)oe3b{x{wGE&3zP0#{;<6GC1e8*M zLJ3rrz&*se|1a8ZuJGN3!*(sCF=5f(mG$C)n@zXw%_32JP%VC40vY9=*)~%{4 zoISLP01-_X1o){mz6FRz0ip%aC^cBAh#u^*77~_2CJ; zre&fO7>2?y4V3z)V#O#&F}D^*I|f^K91l;Qj_)28kPS2wDsou8U>vq%VcI5^Wnq~n zwr%mr!2u#kpHM@Iqj=&bo9Q(sJ9l=`@@ePK=gy@+91`FMLU&(=vSODh6Gx#?pcIBu z6c;$;xdxvfIL|;LWPE|a>kk%jbEU=ZJtuf}@$UVxNOBpx+&(1WbaY_*%I1!0&oO0i zazSY%NCp*iW{j(u-!Psq>r+40i0kUS@F&x{mtG}U&PL(*I^kQL>jYKX=QG_lZ;+O kAU|Lk+c>c#=7S^xk507*qoM6N<$f&sJ;2mk;8 literal 0 HcmV?d00001 diff --git a/www/img/groups.png b/www/img/groups.png new file mode 100644 index 0000000000000000000000000000000000000000..d21f84b9afcb38fe3091844ac8e430a4c5eccf89 GIT binary patch literal 1771 zcmV;P)Z{Ey%U;i*gZG=*kBYpp!d+)i@IroDvLc6p>ShsEnx!|cOv)@b)6Ui(80wr>0 zYf6NA#qp8n7?*QodkgDuE3T*`{zge?|5wxGWb6bdcUyR-VnWGZB;%{0r<`|(678AuD`oM zSmAzQv^I_?I^usX8PW9!S02OsVGG+okfpTy+i_J z+!gx;LDo`pa3-daKcO+qc_CPeL(R13F?hDYHFWFgo0Sn zVbX4wJWA15?LB>AyEN^E>N%Ug`&eUX#$>!|4yvNkQ14@Ek&oVMe!2sGJaZN>IooE{ z)XW_(p(=9mx{0S3ZpfPJ^|+{@uQw#s2RdnF%tuXf&*OW?C2bI{ObNC zt=B#~vu62+|5H%kccPwOE5aAOxnFMkL|@{zh5Nq_WH@q;3>5dBa))&Fzee3}UJ( zM20zWv?&BM0Vs>UU;Xxkq5@CcjF74vM_aH9EjE#`%g5nkt+Z2)bM{gf`AbSKpWb^w zTK2~U!A0{ceHm&FPMeGKA3esJZ%(8rTfuDu(}G9}K5N%mw|LAI=TKN~+(ZUjs z!{tygY|qd#s1Ve^p@JnqGoV{{;BkBAsNC#1`M1@51vuT6C?adt$}4+aCDo%cRj?~y z0r3>{g%S)0+rszoQdL$#<*I$Y8B?m9UY9eSGR2VpX4rpX*E?{%?w;n`ws`dDoT9P? zg(VY8gq7mzrOVeFu68$l+7|7LrxAQry#M3rvzqtUT}(!LgfMj>w15x;O+o|@38Qt7 zIQpwcJ7yKCGXd#-d)_7PUyi5p+w0Gj*FH5>QoJD9!PLPBf!;?t8757dW3TK9s25zH z&s+cGM8^YVc|wZ{?c$~IxmVwO`_)^$Z+ry3_Z+Zq8Lnwdmz|!mctsVcAjt@k#xhf+ zQ#!F&i0~;tC68}GE-FR>gdT@P453FLog#AaLSpalU)#CqYDW8g6CgbSi0aLyUk5N8m7JRB(s0L55q7y^}8S8ey|c>vz?4s7;EGw z00EW|SeA*1$B=>n@nQX?Ye4@90i@hbsg* zopy$k5(!g6OMy$dbJZ<~r6q!zL|nEL)Kt5nCraB}u3uBr4S_&QLsxCf>)BPF@{HBF z<80HNUL{|3%1&7}E7z z==%yxX7SdIWe?XrS2C|6KQk{wcG&HxiZpVL|1-d}Na{(VLospT&xiZF&h7rdGMaWs z_n&jw0b|D?WmYIQd#+-$yCg+Yg+LOfX_?8mVVPPC25v*_IuHWV{|4Z77QU5{>|+1` N002ovPDHLkV1iLISY-eJ literal 0 HcmV?d00001 diff --git a/www/img/header-back-white.png b/www/img/header-back-white.png new file mode 100644 index 0000000000000000000000000000000000000000..85b6f31cc04ef976751b81409f5ca5d41af1541d GIT binary patch literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^B0y}%!2~3i+*t#XU@Q)DcVbv~PUa<$!O>_%)r1c48n{Iv*t(u1=&kHeO=kFbIXZI8Ktav43uM#EOCt}an8@p zP0cG|a4t$sEJ;mKD950Re`C>0j>8lG~zK zAu1qn>-2Z8v}3uZa!rX6Z4k8o$lCs$vez}-_b?=1VAF|?NRI%T!QkoY=d#Wzp$Pzu Cnn5H0 literal 0 HcmV?d00001 diff --git a/www/img/header-back.png b/www/img/header-back.png new file mode 100644 index 0000000000000000000000000000000000000000..78d09930205c3e6b0e4dcceea618f56d356e1a46 GIT binary patch literal 1868 zcmV-S2ebHzP)YXiK5(KqYMnZ4pLe6tRD-ltg|%{?%r^}Z=A|Xd#p8Rnr4*4UyQwNnaN0bszGw4VvoR6g0n<*rbBh7Z=B0Qbfr3N zpJ$cCT8O!KqR>%+v0I9}VUNE(Z=!9P$U}6cb)e2sfU;PJxM7aIR)w`?lEHYS(Qli| zQ-icmf3a|!%1L>vW01f;aHBjJ#irykCvHaGT3( zn8$gg(o%u5TZ_6raiUFquRn03HD{YQYn@1Vt4MjPKysv9i@RHixq771J#L_Koy~8W z$~9@6TZp++g0f3|tZJ9XG-#T8rPOYj$wYLgLv*G-Z=yqVr*@#wO?<6(q0wfO!f~F> zHfo$ygtJh9vTK*eP=T^gfw5+k!aZ=IXq3cEe64$?)H7z8_yJ>|00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-Xg0}%`*Qgd`*000BuNklE!r`=zI+N~L(I zQV4Pi3JQ8|x!v%bmLm`*kx0TMVYm{fFf=F08Yl4f_KuIoUE@v0JDx18e0Y|X_Icl4 z;m<|?;p;_@kpb-%ZRnO)QM9jXLkZf@J}~z=n$6RW)Au_f(>KjG&C`8Q-kY)nK}qRN zN$D+LQl3%{F11ayE-nm4Z4;yEt6GN3xpNE#oUN*=)>ZGVuHLIVtE>7_r~5`%1#UfV zJw0xB0-3Z}ghr#q(lRq+aWTRIP8pdp&RZO00f+N;83!y;QBjw>u2{ORV6a%Cy1Fh~ zAWvK@7Uvai8`@hgWTV8tu48^EmmtwL&NXZhFojIFYpNANg|b%#42B|{1{}i z4%wrK?B@;?+zy!xBDOD_h}aN8I61NXuyUexBkC-Ge?F#Sg5D188o+ru~x;f~?93S@nEQNDkTyq`^41t&RKa(_F&%IG5Xo5vHP}E2g5?S46MJgg$?2 zssc0`wX;Uktx;>#YPGZ4xm(?>0mG4FhGQF#XCKMlm~A+2$Tpw>pTDn^{{#OtpMScP z&*ztx^8eTeb#-1yo!5D9*=jik=OVI?;>wCZ#6Ct+S}U$P6d2;YTmp6LOVH7)u>*q zQ56+!R@D?0sZ=$aF@dn)fUrQg40oAOC_GR=0z`iBV`Ok}B)MR_2qS~R;~tL{9w?|p zR*(iP))^M7xtYacZEN0!f`J8TerbMo&U}06t~6|y{QSUow{My+Qjb=j=DYiQbQnmg z4-ZdD3Wx9kw4{M>tgv`-Obi~*CLBAPfQ=-xlatx(m>AR;Hv1(uD3xrAQXWoLQoAS& zyOheq?*TQFk&!V&jeMR#Q6tpI40Sh^0W)*(KOX1$0saFP1=vmsV|O0_0000bZp literal 0 HcmV?d00001 diff --git a/www/img/header-login-back.png b/www/img/header-login-back.png new file mode 100644 index 0000000000000000000000000000000000000000..6b0e5cb2510a6e00dfcee98eb783504412fa5b74 GIT binary patch literal 5451 zcmWlY`9IT-1IOQvIkq{{@sTba9~C8^=#v~p`4o|Ke5CM6bh!Fhsf5(ra}T+%x!D|J zj@@o%Z02UOHP@VD?j!R3e4jr&|A6P?^}1trTldU z`t%wmnaS(n&GhqUxq^i%8v9cknLac*Ilnw2Sa3#GhZHo^1}8j|iFxFn&*>C+PD5Z` z<993_mPkOB(OBGR6p>|RFC%fE(#hE7Aryh- z{vDrM#Z0YcP`Z8$kI$nU`V%WVLJFD+>-uIFSLc`4f(n{OXGOg~X6VC$q47EA*qUD6 zOl8|}Tv_|T=v)%6Gpwiu-8hg#>Tc>CB{I0x?Ht^HJyS{HMXlqr%dcZ_0lAGarL?Y* zseEehlyG%yMif`xJ|kLf>Kh9!Y7Q-Iu4Db^<z~sQTh^Xd z!}yk6pH$V^(9QQsBfH1fzKp`9R53gf@Q#s{GmEPUl^t_SYfe$PInjTvi>iZ<3V1Bu@X^=Cyz~D@gn7qzmflFL9XF|wePyLu) z9GP5TPYOq8mgbk%U1DqAB@@GnTf)&TE^#$v25)R`skwJ-PPF|jqORCJJ;T+ZZtaDG!Kd#aNo7@Zb%vL|PkR$XGN^GH3|mLcKt z`pGRx;Qw6szyALTKxPl{dZGO)eE-=1Qfm~ay2HUZ6m&0){tEq~#U2H9)J}FAycMW= zEBvTgfY2{a!-jZ+#29y#8BF!cV#ip<>u zMRw`0nL*d~J?^!5ma6CHdL_QQj8OF_<6zB9uZ3lXB`9G=*4Aq5azz5<>Layx)}_<~ zXXy*Jgbyo~em6J6xHX7(ImX*1j$>!@S+Lr z!_+|e{jSUm{F?Nc|2dQMK0-rM!c z`X(uU4&@K5pFMsk3xTnr{83LVR~J^oY;rZ0%M%-JCy^^lqIB zKYe!-6?T3(@KnU5Xc@S6PmyV~&JJ?CGrAQ3j3NNZ;+!C00^u0lbH)XFZAa$(T`bW|s6k?y%tdvuIgB&Ao;&nP^wDm7n;ohft8@LfleIhWTWl zRr~rYrSLa@ar)~__iZ!hw66=;!0dl?iPO0;jyGNMVs6u47wDUy19DLz>a+4$(R!}M z(K*l1;H*lvdT~j>p2{4ibRbo|q~zbYIWb914w-x z*>kB$$u7Q9QUg=6OutY!|DJxScL&>X#oQ=}skcb>JZQ2**6z42Z4c@&#C=)qR(dR^ zv(M;`u&VF={d-sXEN{K7>bF@OT|53L@M6u-3tPFG{?||5tq;1_3fGTAs*cqTdgAQ8 zMm}FcT^)f6ijd{vjG{#D$RJV{6z=jkutwd3?p=Sz6(EH$0D zL>5uC$09EAbQdjGc}6D;SE;&-U)F}6EXrN&{W->5VR|}IuAa(Ul-r)K&7#T(%P-aK zEaDXEt{Ng(O}`fFviA12R-W&z*53FfhlGPnjKzFW^&mZ#zuXs;-bF_+6_2KqKe{W+UX)gpqFJ&bQ_ zCH@il(jr%xLA$L}_8{uzPSc5hUx-~}S44YSjGqwc-qGjXjQ&^!ocM`vGX(b_1E4QY zE#XZ~j=ztMfu4ansG8n=29Jxcda0)2-EQK#9G6&fMonmZS9z%Edts2V%6tV~=le;y z_%oB|U!~A3T9pzDE(B_xG@@S~x|Oufe|71bZ0BWBPZFu`_sbFO<}$kb#luV`b-WJW zbJ5e@*LopP2jgPl{;)S?xTHY0&5ZdzwKp9hf=esOaz0tS~QFEbQ zi|pQgz0H-3Dg;mI@@A8rdr;V~3Lc^Y|<|rR?{!82S0pjLq z>C?*2^0!r@_DujPCqXXqImSKvzOUwMT%5Uc-{+yTNp9Y0TCt@Uy*G1vweW_Ym{sWA zz6>hA$n+liVG_NsKrKPSDoR}ywJlz3S&g>JP?ttO>o4~Ch&c*0KftM28zuK+-Wa+) z?R6c%CVnh+v3HXKV*QDkAIm;6H2ztmTT_|+C7%*ZPM$d#Mn05?^0r6n%<5$wJ_ zCcg&zcj>=g9UR{FdMz=d4J0tO8$INOZ~0yGeY~&T{_QkRA6ZAbKgj6J=2Kt60zvbIr4ms?Ipkd%EPbQjrVJ8qYhXo z_t`af5c}y>f6Npny<;o8qKQ|6M8l+2$oy;PhRBN6u;BeAvRWT(_Ny+yL-prJ_qpXr zsQ!Y5-*I~lKI*#ti?S~}<$Ij+(*)M^w`fjlb~VrKV3$yBp4Hj3<| zti44u3Ar2>d*RjZCkOy2*(9-oJgMnP=rH|Nnb>sU^+l%?kn?L}v7Vh*I^`*Q9j@1L z>EqC;tK}&mje5`2jm|fQ8^c}BOwTM(#?(P&J(kAw%^W$(vy*T>3D4G}bY`ury25Db_Vh~kKQ{=Ca&6hm! znF={Bf* TkGaPGHIW-Up2BFBfY$YxyqH&2H?@Gz-Ay3HN52Qc2uB@Z`MW9{o-RZ$w zNvksu9Q5!$@|d@(gY}=;&Gs3<{Igbk)o|AS$M#?wPwE#+?6;kUpS+*HHtO08MWJ23 zqe=Wt+J^M9IcjJ8>W{6?=U-Q{>UNZ>_}jn3Z$YB#{B)h`KrsH-y^W?Wzs1n!KZo0> z8#s?&>!iBfna_1w;|hBlbEChe;ep3{{J;GwJpIcDF27L-NSMOG{BIjm-?rPn!I1La zC_u3Y@D{-jY{Hdf{P%zM--q{CF7iL5>#r)KpsE{iM%Vw8O~5&ufZIsvt1yZELjf0t z0xmmCYAOe6nFeYl2mWajXut|IaF8^BNf??2URMq>916ID2)YUc-8Kr+K?MG#9IU1o zY@ikV$R^0zH2ATz_)}W2olWpRG9mwL20NLCIM@Um+Jtk{$Y%Q-jvWfm(v2vig;#x!DAkQ1 z4@Hm>61x0|dgaJ+)5sS_k@pm(!WAQ%@R9f668BItZ3u~QY-B$zav(X1j*sj^NNDoK z!-42Ao2aqPD86!ZziIS@bF=^-J?$);$QS>MFTNxbBT$YJ=*Dd7#?0emmYrh+n_`I~ zG0CS$iEBtHGo$+o2}8=6A-xo1LEh5)U1CpY#U6BtRq>8Jo)UZ13>jJq5k4uu*aMEW&lFwGs*Y>0k?_@+uayTJ5 z7?k%kHG3vG=WuGta4JSN z)x93z8>RBKQgMe3;z_Jj?A>CIyTuvm#fjm- zBpfJ6MJIv93tiFqspuk~;-XnJdK;|@h!=%pWMG*0s?w^e(zsbneK>}S#>lWR1T?0R zjiGE~>ev`_)silC>F&Fwoj#?V+n9cKNgq*?M=a&BO9#MZquZt2XQiV)Wnx~~d zqNEtB?5$S$f=aoNUM40gd&@7~axLFtm+h)x9g*dZtTG9GtfVbg436EUV2xK(QYto#F0 z*|rCRqOs5p7%mqJMQefEP`K-ExHT5;Mg-0%qG}C^GsRSPs6ulUs~>P6xj;2tvD!+b z`fm;B(}?Pa=GD1Cje|aTi4Razp>%i+1uH+r2Xgtq93OZ)2hgo*DL`$bq5>UOLx;(~ zz(8NS)lgUvSw0|dg%3#s!fo*poSKLZe7G+@M1v4V!iPqHWZ{Gq5+MRZNS-5PkqB84 zpwyrEJYQl_8WD{lrjUqv9AaJ?v>gtrv?W#PlWNULL=uU7goN)Pm0FP+HAohUz(X7`+m}*;qzv!*Qd-O@?4J}ahEfivlq0Dn zNNPD!VV*;sj-bwQz;pU_Tu7Y|BUO#128qC~D5)TnRA)UDI9e}8rgkFhf0@@qcEA$p z;BstzP(8HRNTwPIu0}Q-{?Z^$ZU{nxRYn?$t?G}KNU2FKm@8yeek9~FEr|2Xgp;hSB!0{vT8nM2hKNwm_{~NsY;lUoA0MLUq&^X8npNU zEl-ZNSlNLu^PA$7 zk|H68EAk0ftI54^lWcuwGJ$8%=Eg5n;qXNm` zLz$C19TOJJp-AS;2y@7eiM3*KwYspduE`5s>mzboBeLrTU29*uR*pg>E_PM0`mjP8S6**8d52)|o3gLQ)2t!CJB(7xxSu)7E* z^~OOa#0Y#Q3Vd;oD|`8^jHaK|6|U^bd*I8$ZuQdMEBC-}_`N3gz&cT2lZ-x7ZeN~* zT#+L9HlxqXzR&Dfe;!sLPqn`Y=zp{;_wcP;wrc-FiGUS z!RTFC23#tRGMw@jl3Y5R7Bw7qk)13Y&ZP{cGlpwahf^tRh6AJqHSEl1V|EqFcG<<0 z;o8#SJr*a8!HGM@q3kL!SezP%k>>vf4ws_Yb875InvQXM47q*w+yOuCPzIMx;f`>* vymPx;{xRN|A#cK-C-CDBfVVBp(wO=;;v1RCwBA z{Qv(y10?_;fLK684mV?ZNF2iiW?{zvA3id%aEXY1xpso{{+=E8jg_n=MR`wowwi z_wajjL}5jws)?mCd3hgIxd+KwtwjH5qIfm>3vDRoK~s zOGT~Nq$C(bxTP7qQ(|h&gR>bJ{(fd)_{6|q>ggaQ!0}_z;pHpN|7ZGn8>AN?fS5o8 z7Z(E`!yg6)LG5qM4rT9U*o3$kxP`?T82Knu7 z4=)&)8GihG@l6qI06+kN4Y+xi;mqqx3|gYH5cO=_cNp&Oe!%eUi{KxIAJ16+{QM8p z{FC9!hsO*zPMvsn_l3}U2Bu$N0{{XD?1k%37;<*3Vz>@+0Vg{n!;u9KUL{oN%suow z>ety*HyCbRKf`eI;$eo9C$BT?{+!F$`ev6A!#_wg0t65PC>?|X8M&Mc6(4s2xi5MD zuWz;a)-mPDyIZgR|37f;&Ho)SLH{@VI{jaM;`RRvkN^Llx$e^sc8x0*AiV$q!~{za z@4ho^es~e+hQI$9M8!BbHFVeoxwsh^bTx$;)MT_7lteWcTuek5B!n0k^o=;#t*zKw zK>7dzhy`WH*Q2R|?_2}pNZ!24@ayqo zhKG+oF}!DyVE7A6{qKJKV+ZL42p|?%NdErM@D>;m89p;J+}wTl>h8;n zFUfh@I|)kh37^o)U}0orWcYvd<)4qwKfJ%Q|MtPxmmilhFgP;+1Q6T+pzYU}O<;(= zap`aG`Ca#-{xY1nbb9I!F`#>Z?qC20Cop^%{(S|ie9pkY@`8bh1FR1qfEX#w&Hw=h Y0Q@vmxS9<$k^lez07*qoM6N<$f-q&tssI20 literal 0 HcmV?d00001 diff --git a/www/img/immediate.png b/www/img/immediate.png new file mode 100755 index 0000000000000000000000000000000000000000..b789c544623e3f93314e2690ef1848979a9739af GIT binary patch literal 778 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+AuIM&GB?`45_%4^ymM7duE;|Mn+8< zy0((j=CZAGyYzqOk$-=Gf0owxGXJ5yG&{5X_B)_woi?D@I$%isV1gB`mVnK~F# z7P3FVC-V`}O~J zQ?dVtTW`iUU*dv>I?^bRJijfVR8XM;|9()v~bol!J^$kw* zCI0P?JMqEZO=gXysO6pnu-6;TI&|K(;hB8jhrQ^&!Jm5T)`#_b1R{#9n57zCGIA)0 zFqbh;{uEi;_WM6S^W3}aSI(UMAbB^fgc%fW4Rg=%7~U6>_*b_g`N#YN=Ra_+(CcJm z2Wy-%rJ{4pr5)z{R3QjR~Fzl9RV3AWFU8GbZ8({Xk{QrNlj4iWF>9@00Rt3L_t(|+GUeXXk29& zg`e;5&Ye3m$)rilq(+TRjHFsqtJYRfCrS&Ix=_=FE~G_-ZURN?!j-FR6bT3-h+PyB zOSDqdU^c~IwYVs)MTHbvL#9nSA%8PXCYiZ&@AtV#6Iwm1m&4)kayUouAAB(~e&p=M z+5X&?*b4_Vr=o@Gj$O zBslfcWhSQzU!ER5{N@I)0B#f)S_eNI8#^+P-}~Io4&pc>VKiG?Q&UF{R~@=8Q*; z)ID80p3h%8_uWbT@rkil|C|wz3+K2#w+etmaQW&Ydmd@!?|&93%vDfIgL43M=F(i8 z$mG8nJ>M=~e)rTTJ>A`d>4aQQLRw8l=v_?ybvkvDRp^y*j5W#f04pJbb1R+2OuH4+n1DsMw z;eoX{Yr$Et4&f;Tg3GcQM+?#Nt^6-m2A9OWDWCD+D%Fq-TvVlkH zwt*Co4Gc}Gb-uyZq>_g1Ev|Cx^{0nq{+aD7Pqgq}TgK6t^k@t``Z^nUZFdWE7fJTcZ~^P_~g$Ar_1t(_O17!jE7bVa72-%9@Utiogutc>>qyr(D?t> zxPi&Z$?kK1%)T`>Tiu^Y2fF~Owc4*8t>$cgXYSLE`#b0E)c*?=RUdD@rmGhK0000< KMNUMnLSTaJnX07# literal 0 HcmV?d00001 diff --git a/www/img/kill.png b/www/img/kill.png new file mode 100755 index 0000000000000000000000000000000000000000..076b0effba0500d6ecca37f983e5a088c4b0f71b GIT binary patch literal 1311 zcmV+)1>pLLP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iFV} z5Ee80-Q@NF00f^&L_t(Y$E}r1Y*bYk$N%R(I*;4inLE=?Erpo@nW|}|%7O$;2n4M$ z8cmFekpwg@*qLa8D;7oC_D;w9nmIFb zpT`Al8A=O_`Xyh^=A85U&j0+sbAUC3x%cMC4t901*TlEKd`x)vtzkahIY(FvAbIrW z=zAn0WQ6$ zmfT}G=|~Vl7-KB#U6&P-J#jg~Gx6}`6_)}duLH4zPh+>pxMx2*8=g63;yVE6?sb9< z00sf{0$_}>c>vcFNoC8>=Ip^om3aEx)hj289mc@i3{_9vl<`= z;6Nl285Kn_PbrlcV*p^rVzKh34Fl4ahaTJ_@jjV;<>l1ppB#C09Wc4IA3LAlF1$&k z*nx|eg5Q5W?|!@-AOIL085wzJ-@bhhq*AGvWm$Z=T*m3sr%@~xW4*n-84?CKcI+pj zY8tYeHuizzhG)a@%(3hE_P3cJOv$aC_j%-Dt--c;0z^eoMtAMn_5PtlhYE_KpjNA4 zZf*|ocpQ;P1ORa3#tr_$_&99KhU>Y3ZQIufP-Fm(lmr#@kwh|ZIl>zVwfQi)rGNm+g`SN893=BXN zMKqgDG@DH{8Vy*M1x?eSX&PMDy-lWthy+29TWrWX0Fg+90O024<}fxkhHN$q-}ljO zx0e9AuHURgmOJGEAq2kfgHkH33g9@dDM^wc%W{9UT3vDtV+@Yt!1FxBVlhaPbjRiZ z&}cM5N~sNitq5qfTD3$X@mDI9>JNedK@i+(4p9UlWGNRk$3kHM07@wZFuh#=&O4|O zLjL4=en&c;hU>cbd_)N$;5ZJgRx7kDYX-p7-2kd-nm@$j@#nJH?4}?H;QRhRQTZG>T+036A4X zE|-I;si|KXV}}J=Qx~@@5CjpF$qB!k&o_{wp{0I7D VH4uON#2^3w002ovPDHLkV1kM?Ph9{2 literal 0 HcmV?d00001 diff --git a/www/img/lock.png b/www/img/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..38642a832428fde74f4c15fdd037bdb9c056b189 GIT binary patch literal 1358 zcmV-U1+n^xP)BrUeQQ1%g7bErLNIq9H~}2nY$Z0xfbW(|hT(bUJg+oVlLa z%ZI~EJ7plUlAW_JYyJOPd;j}v7-2SmnwmN(E1PZ&}rV8jZ@nef6ClPnV>S^{z_EpV*gjy0ZT|PJq}y=ON(%EdpAUOBW^%LseBB zpSEe!-u&d)4p3cP-!fyy^R4CO@9HHbWko4(P16J@1Z+!}u5V0{OLV2A)tYrU%Lzd9 zC2K|mn!NxHYr(679tAB5fk+A|W!ttLaU48&y2$t1vmg}LjZ2=DSaDXBi%Qyae8C%l$R%r84Ew(?7v;iWLL-R zt)EPGZ?5n4r*hK%{XpFAzRc9O2l(ldtGr7QCfU<$IgK~iqP=c9 _cplqYrtE+#^0eQtVO=JD~?si$o9 z>K%syfq*Pq_GKOL0^qKxIVR1`cLkV~CNltC4;5>g#+^Gi&H`RQZ*T9Tpdc5(ofgot zyEJ!te#bby^D-aK(PuS%Te9$aRms8$j&AhM%j{S&<+Y@aYyg+{%$K>V-vkL}tS{IR z!acL02xxNxboa-Z+kYwZ)+s^$?gki}I=Jo!3Gik>*CNoXVQRxi;RH~of&l}ZHcJlC zge8q+3)#{GtnzJ^ZX)R#B4$ElR6tv&_H|8N-b$wmr)enJx-?f1+B00a47O`m-5WVM zSt}+@DlBumb6-?S*)%Qa?d=`B?(+@SH#J?na^}nrQJ&SdZ24|^L&G0~Lqod6<8cWD zH0kW@5s#-syxx8Zg+ekgFeFEh{_0<|X4@A)Rwf*0rpdKyt3IAHr|8(CMe_)S3~Fo7 z>Q}Ee{&Mf$%|9Iuhh9`vT2@><Bmd3jmb?RNYReKE7IwKwokJN4dIw=01tAZg|J z)VPiBESgHLyB%mBximggrISYVCx_!>LN^AdUFvbH1HK3D0pT=)w(b~Z{X^u2_5UX| z0U~jDpuUfkcMCrm}#IIK&f>P+%$~WG86IQ)HSD z>+MUPWkNj)7Dyzluc^}KO=UeLaRp(!b(@FNN+&SF%J6t|@+39}yBV?wlRzp7ETf36 zzA}ZjAs4}jJ@P~qEtolBe74i^YSdH{l!)V5Z-2~Gv9>{@t51t~06&oU4~pfU8h|}J QEdT%j07*qoM6N<$f*uoY7XSbN literal 0 HcmV?d00001 diff --git a/www/img/locked.png b/www/img/locked.png new file mode 100644 index 0000000000000000000000000000000000000000..83f88d841613c4dfa4d4dd1222609abfbc679743 GIT binary patch literal 854 zcmV-c1F8IpP)*dp;)X@`kEF1Ch)fMj$c)k;DeWJG zLP0@fy;OuzFV#a2QAAQikPktSLE*j>R8kbAWdtgfu34^`uF9Hh+sip=EiEtW0TAI@K@tuTt`%m;NU+Jt9|D+FS9j{713C=ag~Pp)hbH8mmI z4c#Qx=O_Kp&wK^o+d$;2J1vw;#Dr)Zq9(tlg#au$`RVG_`&mbi9zRf7xhqGK(uO@A z_l#ph!*$u~orv}He2IF!<5p9X>v6Is0ce_jVr{UR8_QlJRf|3WsjIdFgR6PRFs$b>QyI=jg9ray|3E=y{xR}v}wkS>go*{ zisIY{xPj1L5qfSEpPtHGad25dN#W0c3i|NtxwEB!Bs(mC@zA2Z3m4AioBQKn`qa?9 zO=tTq1Ey{8?oNeRw^g8|uKQmIFb96n{Z>$RemEZ(u_H{3>R2Nh$hs{C0hRzG4yq1X z3`?_^7 gBtEWMUO)xJZ!7>@A={z8UjP6A07*qoM6N<$g123Pp#T5? literal 0 HcmV?d00001 diff --git a/www/img/ortro-logo-small.png b/www/img/ortro-logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..e28fd2fb62b858f8f6efc199ef0db68692ef4c11 GIT binary patch literal 3175 zcmV-t44CtYP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iO4| z3N$MZ7kU%`01M|yL_t(&-rbseY+Tiy$3OQmbLVAG#^c90cATe!V+AtQqy@zkmTr;~ zsU^E9w6N()WFMxjs#RhCDD=J6R;nsQtL{P^g+7GZ4cmy8W!r^Nx-EpIO@O>Zg0sf4 zO~&y|=H>Cc?%aF&$Gv0UxW+a~988aNH8W?<>wA8`-}ijaZ$@Dr%gs06yt=8WY24@Y zbtIF?QRcZQ^EtRI%QvLc>Do*t^H3-hI@i|Lb}k-|3*L{VzP|qRKA$h?^?C~)kEgh3 z(W33|I}q*d?OG%fxxwvrABjez!sGD>Ns@%y?LM+>*)sq821rv=(`Qsw9g$@@uW4GJ z*XupucDwVEBngklBSN9j!_M}%-FBN43Wa=;NMvbydwbihx85o(n3!3;diAk&>(+g2 z`}Xav`}gl3l4V)Zb-huNB-u1g48y36Mx(uczh8vIVXd#P@6)+l?ulZt_|KZAMO0ON zF&2vz7X+A*kr89ns#V8^hldm6;eolBh$0Nvf) z?&HUg-(i|&XDXHIESJlhoZpv9C9fn&%|Zx-5Y*PzKA`LRMwiR=*ZF+@X<*GlVY6s3 z7(50DK)Bs*QFXC*dV;~=UE8*8+tSg|F%k?0?|skNZ1d*LQn6UPE|bYTlgs7W0W?jc zQmM?^SJ(BQhr{7t$g=#CP$=|DEEY50Gi$WAwswZY;ax75EA4i>Mb#=^uXk3f$g*6i zudm;@Alz!%vSq7%KHr$CszTE=p{l9?Cf?5m#^dq4)X~x5UJzhvYHGfqX_`x&i)n9|i$z;CdcDu`!N~LfS%P0z7ulH?5QBJzu?iU&w8t#)M zsbrd_RxB2;Uoc?0y1D|ou5ZwFJt%}o*VNRs8-{VZ`n{%UNRotUnp#Us%MU`K&}L23 z9{2nG_X38dX?3lwtsPsoY;nKmU@ly^5Z$n0LrpXq)uPep2EX6`TOq{HCCL)MYu2p! z-z{6VWV^b$r0(u+&&bG#arW$4v3&XR|MdBMr?T1XL+Nz-)s~i)k6i9rE?WUCUApwZ z+O=zM@%el%m&tYp-||v_4W1THEY)71A#!c+VAMmqedhW`L^Hh z|9*3Gv)<6qkXtZfva73$UAuODIuHotG))s#Mr&+r{KQQCcI?=3=bk-#u3Jz!fW?a! z6AT8+9*<|c5W**fkk+nUizG>pCK8FW@6_+mp+hJ4?%jKSL4k?IVr<^LIaya%_xwHg z+!G!c72K_vl0Wyn|Cc%Y#J8b1cqPBTUscn&xOqhk3KH(IVXG>w251K#R|$G5_Yo=c6HUhn}2 z1S~JXBahgzp-ndVaSuEI@H)gk4tcNDr@0!eC5TtBRxewV#U0~IK&uJkufedR{$Aia z)ibGL$7mRQz3^pVLl5-N8O)u)EAWXH=zIYR1J>@A70}usa2L31pnE5%_d&&kw-Yeh z1S zcbgW>8=wSXi4V>lhTDs9+%~&10^N(@KW?|gW&;od%(T^Jwd5dyafp{~Hn;6O=L>Z~$xsmIFU9;CEFZb~*ME{QI@A z@xzmGIXjpe;V;g>`lImJbl)F<-(;+bZkosiz~Q9jT1y;t7jzK1<^Q5=u_0J-&|CyL z4u>5>uQ4ES0)9Q+yeW9>Ak;O%-^~e3FZgu$m(#E-Z=Dl=QVQ@&KO})@weCEePC>q8 zpB-5Al(0ddPXSYc)*R#&IPDlZnu6r>@XB=anvi-89vg=TdL8aOlVx@c!18A&4*%&@ z#xVR^K$p!*3`0B)g9TXpkR6LdkSKsTon;EJGzWt(IYV=W)nO@UOiNMwT5+(kbAx2jR&W49qs5 z0cZQI^W=Jm3mhH?Umik^%UHZ@y*gdYRe+}C#le3~0?zG+vvUyg124jpMc4$~aS@nD zz$M^Y{ZKv%56|(6WA?*;7aU;9a3~I<2yG75s)8AH1izMt#uyx`*5zSc%5t$e{m?WF z4|gtz|ee zZXLYwgRuNYxMeL2eh?B~5MKN8r$Rx7jJ*a7TTPU#ah7I59k(p~W%VWKkRTyXE_|hA z1CXZCffFyoDFYfL@XL<*B}=+AOt%ix z7O$q&PEyC=K`d!~$yw0>_=-cq9I1!TOm(vpv7lg%u9^+`%K^KhbQE88-p zN>C};in$5Y0{p*|f^|Eivmn6OS88W^==hkO&>V+c8M0;D1IiG{!-<*tzt>JCagYIf{Zaq zG-Gp>EDHq;js=S{^d%=#O!M|9pLzfDoXu7zuEsonR$#7HslOVN{1E_|sx*n~Y6t)T N002ovPDHLkV1n~32%rD} literal 0 HcmV?d00001 diff --git a/www/img/ortro-logo.png b/www/img/ortro-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2a387c7842f785416a79864acb1f9eaa2038fc3a GIT binary patch literal 8487 zcmW++1yodB7p0|Jq;r5F1Zkujh92n#=@e1ALjbI;!Uthp~-T~!_jlN=KP0Rac1AoBruj{vSbbTr^K%R@^X0f80)A|t8kk#U^q z>rAxQb}G&`+?V92$6w!7Q@tyI9*%gvBvEXxfJw(0l0bRU-R78+0GV1@ua z3*Q?7O=mGp48ASc2Neveq-SCCVidKB{%qvsEJ!t^jOWGKk?q3|s_r7~Fg2K36L-@o zpNqe#X1CqdT~DPtwp;gmICA%|92dh%pqw}SGHU4Px7O8N({>aS z5SZuke}0T2iAa!a?moPJmTR!#8pPrsnB%+)Djt>pp7gSU@ z-X6@B6&bMTG@DHkSvosc6}7iN?=97=I{9CZr1B)UKiw>!{?e~2T~S<|!qC&kGUan| zaiKmsJ?)q}b`u`U5^Wi=s;wX=Cr=X-6#R>h7M%XY#U*KWW(J-u=6jzqTVrKPx8ijB zJsvc8&%(?sp9F$%ynUO<2#Ke{m48`j`a-2WY{$q{x1TENeY2LptQJbC^S!4FZaeKP zNUWM6?2a4I)g>wKZ?3i1_hixgtp* zc&5h~ut;8Y!UL>0P1+4Pz~C?i{HK|jnXf-)gREmILzEA9f+xs63d z{pR)Sw}QU+S9Trir`Tx0`E$uIm?4mY{@|`0PByl(vYMKUs!^*iMvcyNh|Xj{S-?4EE0%9DT&>4qoQH$-hKN;MMY(ujGEf7uBd2lDk1_? zAOHmMl#ii)vhw$T0Y_~*3pxu@5|fZjEdpbHUO+`NG?7iG8IMM6Wny+#Rz+phuw&i- zi-}3L^$?7u2XOa7hK)w^$h?bg_{Kbq>I-S=U~^YV`< zX(idv_;|9cnz4?KyQ`VmrrtJJO>OP2Uai$r_x5=!m-Sdiw%^^b$ruc~ybniUWyAAk z(Rz3N<@xqvt<8H^VBLr3sIbZKmxQsg@%QJB5{;rh&@hm0l}`??uGa#Bt54kR^GTuM}jOVKtIMx3{x1z{tpWd^lg}URaF59fk~5dP5zv#~CEE zNMrkAJ6-5I?y!D;@8!8a^|J;9anaJ64FTgQ&*_i<)z$0$hV|x={?*^(V^OEa%F@!( z+}hg9^~e|dItH97YD>ED051{4<<1Y201{Gn&#g&!*G8Qe5kB?A+#)gL5bA@GG zY;1K+&5&u&$sv)O1#=W6#Cu?Dk?w|d{T97ZT@*5wzG#P)P^;$L;Bj|i_6QNq=$zG7FJfww+#&q>n$GVTT1<`)}?WD zih>S6>G>LeHUB<&7Z&jR><0j+=MlEKX?AgOA$2L1ecGU7__?>Bj7CM5m!JRnBRkpB zYc}l=+aTS-qQb&I>*N#^9Rij^FiA-K4p7bJQ>UYhN=XG3=E5w5PI8($IxT-jQfvSI z4kvO70KB%0T0PL5cDy_XRZ|wVw0KK&h;VZgYDshIR&DIAwz$(cI63+KIc`|@>nJN5 z*3;D;xVwxf`*O0<#7IR&wW=I+Z?I&3cdI+4L~z53ixN-g z{q^B0fQUO-^Bs*su@ zIb*OhyGi>af6FR$adB}NBz|ja3l<9^fihvXt5e?qET0TZOnkcA=n5Wxc=AhMr)gIR@)lP{LQ1Kr6qgR5-*AAy#F)#x!b8>7_e}0 za{7fmfQpLhA}jkXBR!o>M@Oe01OaS^9utN+S{xEx-|~f5J8yPZ0t=9xr36g5Mpa9d zqX7gtIv)F<-zbkCIH`y1Kd+wukY*r^J0PE-ucPR!~)S_6V$>qoFX7Fa`sFZe%3;WCwMr zmIc_8#?+qcIo=ufG zIi_oS+5X0h6BAYK08yL*%w}P2tzlq5adZ$dkX;}VUl56G&j)yYMr=MR|ibzs*eQ!Nph4HAFk($vfojH(~WXFmsYm z-LPqw+o+Pz0ocy}RaREE9J`b>NJ|e$uWF7`7Lc|8J$08BLMX^`^v%4Q*^}_-6awEdE?l(nR1$#!4Rz1wkmq z{T{oTzU(EbrE*)=HhVQzSD)Y5^aJQ(U}pZlwq{(Ynu!Va)yhz1Mn*=~)YPo97>tjy za%oyUQMtEFAN`|O@33ezU8wS4=IMF&320WLjlGZS=6`<~CHsvCtox0GTg$2o1QKqj zu1?#s>O>Zcg@v{IaMGgIz7@f?()W~So3OOBWCUQh9T2$PI{W#d-QC>_$A(p={yQfI72<)yu*~{g_)6UM$hO?lJon7-ymiLJs_n#m2q(s~YB^4FE z7N(}1pU*bBSc|6b;y{pj;@7W5y@8@0x6o@pZUSa!n(|XE;@OHdIBkD8iRA6TZ_eNl(-7XgO_=ep0!KmwBh=6Z22nkJjP zg2Umzj|zbqq&7M2*$o>fpdUV5Tmr39oqfN%P-acfW^A^{7RKFqKh3y|lr8$h#qRLl z-28k$<&;lX5UM-l{qG-dIE?{XcD(^?lHHG&7y<9u|A|$8jL5}+hO&CX%eS61KKl%y zk~^}5To1zd;hqILJn#l&fB_P?G3$CZJ@z)g(Yd@kSgvq>{WevT7L@7cNb$t&ee@2y$Gmo0`r@r#oTHmzC4k$PUH(f5O>LVtXeJWTFG=ntO3Nxzrv;b zNBU0*Smes$BFifz#6>_;REspSxXeQ-vC(!--+=}A_i>w0;5sMAS3PJSTx-R4%!fWwEdMn?pQTY5cki@K49k?4+i+uoVL z2WNqw$nb@24A}?$QHJiKAt0>s8wlS%P^DAIbXfIlaKa6bQuV@9zKbwV1Y_2nRc-WB zps+&4@e_H~p(L@mX}P+}7!@cRIcX>8!4ct}zlG69Zf}6bVkJeK+?FyRa*TkSNh*8L2ngGBeE0KU>Fh!Joj~~Uaq@GLR6OE&R;d6#cGLY z*tI;At%rr>K3wFwEn@#Na<>tek&<5)v$F10G2|PDVz?aC{x!>w7oh%X9ghZmS@)RF z7rYwPr?4RMrOM+^1y%O>3Iap5ic+7-&%zx*MfDVWe>9145}dq7;E*?)CEjn9mIFUr zPS{c5!t}!w?v1pS6-TNb6v`8!wBd=k5}gIExx@m(UtjhsJxhgb!#=O3Y2O9rIDDpi zEvBfD-a67NWzve;Ap+Z4!>JayM5ko6EtHS={EQ2e`Y0lUx@$H`P0mS&COXgWB`=B5l>V%C3u(`&d!@=0<){ zSNJHH^_+5VAFcatrdgL#vP57M#p!!J=1+kYrtO<>sSn|V0a4;X^$CiBN(_NFzHQpq z4N-s9f}oi~&;x3NnBYC@&JLLc2+5KA^5{YsJqErk(x(CebT|hFxPKuielzOpYMgRd z!jJixyyssCt@539uYH6!HR^cdVULPaVKqb<}hU8HO@YRkvoa^o3d5lp=ke=1#) z_3FGd>eS!XvzqZDp;GbHX<^13_l8TSc5*YN6=iYD4O@#kD8hjTn-i-WkR<8!5s`?~ zjxK)4IZOPvwefCYfp4_&Ux)c)*-6bJkn`gmYv|2C)E2Rs9pWV{NQ&yod_Db1{X*pUfiF@`CQD(kKA&DV8o89j6RynV2;maNaJ9;x5ga>? zy!7B+@rZ#`Hi$8fIC9Bx(nA^&LLNYpJ*{XMTrV=;`v3KNo|8|~^_>?M6i{wwG^b1m zsdw`#av!|^;6cqujw|cw+hbmDPI4tPMJ=}#*^4c!Sf7axeshG47f2KsG8af#0;Qk( z63KG!M7*c^z|n`D*D+6@f@gb3yA@gpY2a}NqaS|#!x%}-?`n*b=xf#ggXHtk>k07W z1t+_#s#`j1XZAmFa3q&WcF25ns+3MnEprX5ksCm zK_>PB%(c)pOF_UOag>)2|82P+S#^26Hbpb_PpVn(O&3rxE)0LV7Vl&otzAc5;eu|c zSC($Dxad&uj0h&jB?a=@k0iW9H-+toTe)pT1`H4;zh&1yKze@7s6rD6%3o6V2AfPi z-QpkJ`K$YAAl)xSr-Ki>7I7W@kx$+U+j|#Axgp-rC1xaxu>yKCn zVu)?uPNLR94c>edQ=}cUShoGlEa zQ43K`k9^%9K*5kwMiS_|OrQE5v3Aych8nS_vflX2yD?wk$sSRj-?UNA^*cp4ClTco z>(9>HoIQ-QN2?56M|vOPby3Be*`L!)=Ol%=?mg5`MJ=E+^chZEnJKX3Wx?_$Vt071 z+9n0MxjyT=EVV?43`Gb*xf+XCp8`Wd2F>j`MBb zcnOrtrjx z;wWzF5Zl)n{Lu}9!W?n8*s@Re#kpr>aHrQj8`gM zwhF#3Og-5%hjDTbH6^0*2II6YdDfY?fvd8iedgzTA(4V;A{D+%%0Wrz*bs67s2giO zl859zmf}Zvc<5>Bc>n-anwgl@lDXNrX}G5-_C#=;%T>2ps!5z zF4c7->((6WX9C$Msrp>ZbGeUo7@bOe&hwl(RI1YH&sJnTV+sSIPXzJyay2Pw)MWZs zAS#kuHL3ZZ#$V|B!?^BQsq4DMt$vq5rBEfb!b1FW^C)iqN*fbgPUDIlTiL2LlHn4m zVvh#$#rDq3PmC31zC?NiaeOsm?mPW0*RAmhzffz-%gkX!W)hFG+%7>oo~LinuT7i4 z)kd6N#P04*pnjYJ<~p`tN~QQI^Jl@DQ$rtVx;Q}u_<^0oXPmDhR(U92nIWbHL>S)2 zcqTXKN7MIYn{+knBKvctjH`L6)N#ek=p1eP=NN)NYfjRZ0;UHi!3YLd`m#95Dm1jB zeKN$pf*BT$NX|!%9Lgjk6ZO7w9$}FPU8)4a-)M-Hdc5IJ%?Q~kF@!D_F)W3wdgfWA zb(oRRvdD0-%K?yW(fc`)GYv1bV72UFQZnf&l}j}^B-@fNSZr~QSuhPI#_%9{0S`yZ z*Cx|wWLN%gHYCS9vxY7;Tdw6z5WIv*ej3dR(tw<{&o$=`x9kYtzl-Kr{PPN}FD336 zNetqkONp^P#VRE;`MoC=)(YXJ^k9Bu!f<_W!_1Dv6_s@5`++_+D?80X@zsn)y4)Bp zqP+GggHMj3IV+mz$_3h+7R_izLy}pr0W`B4aig+ilBsylezx19OAKC-O_b!p$84<)YyWfs<>mA=1kI)mQ4@U)%R z{Q40X=Fg2{%qO&!0Gb&@;ZiIcsNze*BaH*vM3#NcxZWj{jWg)qb7biaPu-O^pQN03|Z)%bZ37=e#Ql-WpP-6mWYfe4j(=A-t;h*{33972?cg} z>PbV26gpZrR9(wjJwst^U*l^~(4C_odB#*cH=-HivaRwIg|$J2B&OoWKZk9m&xmdq zFe)C6&k;jE)FE|^zalR4w@|l2h4<(aG6zCWkgrW$LHfE#)cWOnXy)RauJDlE!CK6} zVpQn~7ZSmg47+n({3+I+kdp>`aFDrh1o){+iD3|RgRgv^iB*c+5*#G$O*T@2<4<_w zPH+JYiFb-);`!$~SZ~%7^(o+wP;jab!XI43(~^0RbA*NY@F7^HNg|A$;$;z^C6r*- zU+NMcZa8s#CFx~D6tMQCG(pJXov5)cMM#!f&#d3Fo|Io`Y6<2cSy8sYCG={rei|+6 zf`D=W@zlo%##5Y@sZlN8qs*A~9=Tnuv6ym(MY$}5z*3<|1)fPh9ehomb&o)bHg2@> zD6iXsKz;me4i9#HU(`@RvsqwpYTL~~8VtH{g+M$wF<8poDC-+&D#KSuW5gbFbl|(d} zcC>#SBiT}oa!`y~EpO{ZTxUMPS7v2%f{P&;5=R?Dq3-QCYSvvvZp3buCBn;%1N_^q z1f`>uIHjLvfWrjUBDY%jm%~48h|W>?7pSC&>xhl{8W?-j3_;|l-|7+IVXeOt%Tj16 z3n6eiq>&AI+aKV}61;rgE9sWa{W|CG*exyratr)O%O@XhKGjOcWd1lV9aV~S+GDr$ z6aVe7_fA}CeJt?oPNipqjBdvNd%(SL-b&F!AkD&Tf+Lmo{fAIZTmH?0>K?gcdfrW~ zK5a`?7Qw*)J%fY>oeD|1Js6sC4~$m|dDz`|aiw_-{$i8yt09&K&-$ zLZC9F=y-U>S@)AYpNq|#_+HsU`)&$x^_`(@`tvx&#lk!B8ecugxOm1MLPdO~Ac(9)5plJl9 z1A*;6G4vDPGJjMRu1$UZ4&)bHJBe!(;jE5BSBL#w(vhbP4*13pyw6V(#f|if-BjVM z4=->J7T@ZF_9ecE$j6O%I^p0Me_Pg`Gq%XWW;8y~aW99_Rd zj}4{%KMUAw^J2pYlFK`*C2c5(4_&G{-sG}6$7p|^qiiD}QpuI&EJC&8*V~|~Dopqw z^$r@2G(_Pim09r$>h#RWbYOg%J%IEIw;QwWV#%)l_#GTum3U`Qog*Bq(3TL8J7GwAw-Ywi1M1pQk(K<*6Y-M+JMPV z2B9@L$OualI26@J_Z5!8_Y9q$7btSmsaMRJxB|NE?|0&=K9Z z89a+3GJSbvxD1U?=}k2%kz=m5z5x*kI7s5Qh4uLT9gK?mI^C?w;&uZ(60r5(vj9TH zwvV;dxcucXymBvQ=G_!!@^7>vufr;|e8{0A2O`hsF*@S8?^1a&C1S$w&TaRf35ceN zGB!Npsz25c^uobKJmOX|DZB*Z7QMyujMs;Xl5W8wqHc&>b6ngh*v_n=xF6FyS`pY& z#CNpG;n&&I(`1>ngmhk+~mCob+jpT5r|}Yq_mdGYBCne zF^CL953^)ZA0_1SWdigvt-0x?VUuU!UxPCo22!#n&v2}j$H5l7iWU}OA0?7zkqYQ6 ki1RXP^<%NQQ=I?31Wnu5`nQWm1JNQtWL0H;Ntp)y4`S?yasU7T literal 0 HcmV?d00001 diff --git a/www/img/page-background.png b/www/img/page-background.png new file mode 100644 index 0000000000000000000000000000000000000000..210866686ede2aea24b96e7089c17924839eeb39 GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^%Yj&$g&9b`HfXvC;sp4FxGFF(9K8AQ#*1$szW#at z_4mPBAK!obbL06p!WyDviM)bx|v|sVcR~kM>7fsU)q^6c~rVdd-`J%gGnRxlRoJz?|F63`@QE=0fM``j19G6hhTHNA*Gb>UYwF_+qO-l zGmex}N&te*?Tr8&yD%xGl=6>n_Dkj9ITrvYZurT<_I!LTG?kWPVN>21OvqI`Pyb#C zHn%sfuJbQ_`(l!!e4RxB7e?8JUkQMfJKx{_%*I6r5rVO>$-oCMt>m)^?(SF?+;y?y zv$+QFyTei0^q7G}@PpzTvzUtU$k z(|aSVtPt`{Mex|jxRf_BrF2D874K-Ug zuT&VH7-MyP38{33zH!LWRU8RFZyCZh_1;1)*xX)UQd+jP)Dve#O$oQ$rMz)E3<7L3 z!Ill>j6@7f_hM#dBBvFk6B&!?9KKQnK>2)~H#$pLzsz9I=4wg`47&Rh=o%oc@vP)c zr)vX&lA8@xJ`kWO0?WzP87VO>$$Rag@u0OYIQ!_PrY12Y8!JYY<-b-`<8gPc;*Q2M z{a!iz<^$=skLtSKw}1bBXO2pr3J^d#MIbZ6iuMM@>*@(i&ty;b*s2oy|&hwie@h};+sH=3* zup|ILO~pKhr%Z;YO#E&eX%uc6vX(B;5X$C!mqfLrt)>w zV0d%YOu9IzpcvlXkfgY%5Pcl4%A??4aPMpDL9%s5!?0UjQ+t0K)2Z}sNoXD+-fatuY1)crx zbPVqrTCs9L;CQ>j@k`*+1<8!WaX?eSj70IJI(MQI5&#>U{^6U{9_o2~RdHFd-?&RH zB_}UWG8O9m%`$Q9MIbU;=^Z_La?E#=eNc)3aIen%g^6E@$YpcAUN8Cqh0N+4}7mZwB zWkp#b8yhShturVo$U#-^!e`4C1^X=2gXjOxT+Ds-;C?4CM4+Sb-4?=yF2 zIYK$-_U2c9cWpjTtk7`fr~sIzMQCCM+p_R@+~ntZF*Jer^tA0rF7zb$=c#GNCL$3% zJ-EJ39_fxmBAINDX}(SC+wv>)EkkxJaw+Y6WGX2ADWzY$WEw9>_{@ zeaPg&sw_AmeH{7Nk1YkyuAbui8|(k4>qe(dgfLJ9IN0E%lZv!#O<2)hsd@hu2~RH8 zbE`EWVBc9cUQd#*EYIc1H9AkOfk-UL_>}cUuBP)=0=JZXSc zJIumMmLqCZC;nhnkwTF>$@QTO=X+9&O{WMH>iB&*6y$rcY{`wGG)FJQNu(?)iw< z7Vosjaj9v>MhCIup_A3}#DNVp>Yipb3`Y(;12cO!%$;to#002ovPDHLk FV1lrOZe9QY literal 0 HcmV?d00001 diff --git a/www/img/run.png b/www/img/run.png new file mode 100644 index 0000000000000000000000000000000000000000..720dcc4429beb4c4db8964015878e505fd694e3e GIT binary patch literal 1595 zcmV-B2E_S^P)K~zY`rBi8eQ&ku}_r8~xv{~9DEnQN&1WQXxOWBuEoEAg| zDC&p<2%>|afGD!eIG`+|qo`~mgShWT^k9suH+PYNwAm(oqC2Ko^I@GKgs218~A z@~5T#$j*7JyFpJhJX$6t=V^H!0IH^?%l3f@oF||I?VrKo*X$)Y59k!v%k0X%gWqV| z@ub>omY%2v!0ClNuIJ-PAZgJ4jUis+U%~^xK8rDb+_KqM5_1x{a3FyC1C?fMi{nxw z%kx?1sxnr$U?@8XBme+i8d3bea3yd!oyeRx1v3CY03ftGPgLaH>{X*~(zKCB7e9_>!V=r094WVK<37_LtDQfm`i%TbKUGQy>~@qgtNbmV8;qZ)%-0O6l761ak~9 zSMvWvKA(|%z`o|e8N_4;SN{{Fh)N;nV)suS%Dejko%~r%4GRKGxI> z|CtI%j7QVrW&6hXx>k3)v?oP-{Gr*|69^$tG*(2~18DO4P*64wCwBdObxKV`;h&A^ zMnLei$F}U+alN#$Q9`7}3x~@KTTvmXtpMT9z}B8)({(^>#bnF$T+3PoR6FEu+N{Gr)!t~kM_t+LaUTPjajHnzBsjCB|{v6_)FQT(xI!xyN zaD8#s+wnu)^GuXK|62yT0O(C|_N46eisD)K%jsQs%aGrW<1*q6!qyQJ2bSA&4LU?afFc1PP<0k4 zycwdW2~iOE+dE**Oa&>K1b4fZwQt>eT51o@SHt4XsQ~LGun{n5IP!YGBw@jT90NxQ zflfzB&HxjMH<=KV1jykoh#+uz+F-C)k$OiK3>jHysBDq1?mxNuK6m@(TUpHmz&fA{ z3R@ykx)xf~y(Gsz|4fy8xYN;@n4ZcIr5dz)ec&u+WDhTaF(n0@(F|B@2uIxL3P*4B zm1TFx(M(}6-mz^bHUzOAQwEO9Qc#0el{y@@ReY8{dWX@0VX;^3*8{CauaJov-n= zcCvF{p6zg)uU#UA#m`p!^}F}n;Kv-(C|aJeK~p@`LNp~{Ar&!yK=obO-rDru3Mt~3z0siJ td924ZtQELnlv1-8mA>2bFB<=e-vJBWVaBR@{hj~-002ovPDHLkV1n#H;G_Tm literal 0 HcmV?d00001 diff --git a/www/img/running.png b/www/img/running.png new file mode 100644 index 0000000000000000000000000000000000000000..838c38bf132796fbf9ca73fc12083ac5f9989487 GIT binary patch literal 828 zcmV-C1H=4@P)ly+{r?!l-wo#(-WlaHd_Q)K;X(6~ z3#>mG9K#qGJ^%y|GfeX|pv^*3T+7{4bvYyr6&b{I6d3ql9b{nr^^xJz@+%CSvfmlb zzn5lsUY2v=_xGQUF+j~AeESsyn+#Vr z{bUf*|M2Mt!?6Po9~|8OOo5Z-FM}xG zKZZSPJ}?NYGchRXura(*i)1*v^+;zK1H%DiZvzAnI1FkS7z&}ZgMbjHgPw%~!;%^2 z7}WIy7&P=)8JKiE7#KdXG5lm;xPTt$009IK#PdlE1zhqv^%t+mGfbVdpTW>tia|q( zo#7WZ7X!zyuM7t( z{y&gCADdo)0Ae~A&S1c&sUX1c`w0WXpQj9xYD^3-ws$e;T7bjl7XxKi;u0+}?1J;mxhLiB4-69@K!s=F}6Mnn3^{fLMP2 zVaUI~=jw%zj~PDv`o?epm@p=~t!H=ul?Q2lfG?i_1Q-A!p8pI-KF#$20000tb9F!bv##4;Nj09{G0A@1>o&fdm_5h6!h`)|1svsMw2!7L90DLL` z|NmOWEJwT{C#?(V^V~0}BoTTTB&`ubwIR6QxQ4riF{mgWksWi&Rsd`|o85aLkIRn;jt))0Cku@TDWxehuO1?*3IF&1K)D;1+jszRHi_6_0EQbGtq4A}E3Mi` zQUCw|0d!JMQvg8b*k%9#00Cl4M??UK1szBL000SaNLh0L01FcU01FcV0GgZ_00007 zbV*G`2i6Az5eo{o)33OwAEm1VTxTpk}MMq>^+Lk&A9-$6=A z!qr@Wh0_}%;v*#{A>pbZz$s`WA`H^687v`T=B41L=FjYD4-}A*HdAnAQm{}nH4W6~ z1_~$}s~Xq@fcP%DA=W?vaXBGAQC~2h%>*PMBWEbD=kE{X>#_xbv}jowh3WBv`Re?v zAZs0sB;_oD>e*DBWkJ?5*m>*fO0u!BsXJ@4L!4?S!lkdTuE;OT4)ct#J-4+iH>)sK aj{^XWMHHq*2@&Et`KLh{;A^!jb*8KqT=m7w4+W!Co06_r0{{%-23|}?~2m=ZT2LNjg3nSeU z9Iym9Klcms;P?XZ)u0 z1Rx$B0t5#J0P_(N0QA_`00aCm0uM`o3kv}F3jhG+6A=LC9RT*>0R8ph0Q&Id0Q>Li z{sQpv{tnpV`wEKWl>&(6$m_Sy!#UVxeq6iG@Z|Sz1|~x-2KIkH7#Ns71AWK_#F7jQ zT!IYDT$&7=qTd-f8NM300G4EUg_t~7m7N`&u$1XFxZfd(;r1LE&c{0)jfF?@aYmf_<^hSvZA#FAnw%Ei+(g+ZK2mVuk~I|CEL zN3a40hF@qJf%Jc%p?^OxFtEI1`26xC!>4ZyZvg^`UyKf^HY|9=JA3e*gYKZZX*Oa24t-ya#?KmGLw zsNy+50I~dMW8wkIplOB$+*gPukmlb&oBsmYj6nL!XNEVge*Xq~^d&$5u`sX$V+QQ! z|415v^#89A4KU3hzkdg^Io^Vmzxd1ua`HQX0AgVhU}OhII*|RB0pgP15SRP~#>Q`u z0YK;f|G@C$-FpU>%g-5Dem`b-aha9j?CsyrL7@&1KrH+s-+(FZE+|_-!vSOfFcGl; z4PXIACmWFd`<8)?`c78 zY|H}O%*?!8Y>eETtPGso%nWRtj0_w+{}}#1`^&Iw+Oxk+``&DR!oZLL)cg{Z8vz1{ z(Ug;c@7#9=Ic5f6I$~hp2VzN9W(HACW(E;X76yKH7G{1P7G~bxe;BwfeEPKw=)PX$ c>GnG1Q=vxB^fSVy2hZSBq#m#>vtmo0bVCjQDIXF2~kA} z32_0Sde*$WyjeGHT+3l&V+R`m5I`)9jEoGwfB$Cq`04*xA_`w6%4-&YU^L#K7?7AIJcJ0Al&|>zBNyrrJ^m2TLOr z6$MV9jSN6BhOb}0Fns#-k>T67?_dKM8JQR~G&LBUoE)SVE}U-$)O&)7iHQLqfS6cV zSaQtFbgkXo960~|`wjHMC5CtJ-ho`i@aNAT1`!cqp!b9rxVX6(-hKGMU}kQ{rmUVe{!<#p681CG@&G7Ky zLxx9B9y5f6g((UN2`7TW03d*v85!B+EiKJ#SXr4Fe*E|ewiV<8kpDoo|NZ-yfrp!$ zfsdb`;nCyA48MVV2YWll@87=bojP@D2|xfbb8_>|Ni}hy9DHl z@87>OdkKmaj+|NiaYmoMK0t*k7aczL-QfBpIm zb~eZmR#sLp4RQr2HrUuW7`ATR`oFHO_T;f+$0C4on*jodSw=<)7}wvfii?XUtE;PU zfougi`R7kacz_I%l$2t4^5hvqYirA=88fE$0|PYy=-ekDF9HM*vxtZ|DD=Mr<6TKd zN6Um87~dcR{`~pPz|YSIwsq~=b^j_WD~_B#eJT#Je_>$+5J1eVtn6ULFJHbm z$;ru;q^GCNB_<{gboL*Hg9i`)Z)TIEegv5MKPEMA!YuCIvapKr)U}~EHRQC#3ZUhJ*Ms{`%2m=_}ptxsYVNLq=>!;3- kAK#|~g>Mte&Hw=h0DnAS#>U8DlmGw#07*qoM6N<$f;vjH&;S4c literal 0 HcmV?d00001 diff --git a/www/img/transparent.png b/www/img/transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..2a71f0782d126388fd3f2f02ef5007333f86cc88 GIT binary patch literal 2548 zcmVG`3`0&5B@7@rCkc{81!l-F!jKd& zA&V=pf`~{`1Q7*XaCHf?ii#)(L_q-qx`QkN%DT9UsHohGe(OS3{F zU-E7YK*Hlay?=lHKZeLj=5hdlZ~{)?M5nO@oG#!vPBKSWpAd3ZdWxV1I|-Q16I`Hx zLxddljgy2N`;B*g?FsOA6mU5JI8y9aCL9%V)K{jS5;8lEmkfYxx1e9`+uW}a*Am_Y zGoG6s&ErNUX@mcE{%Mw2n(%=~WyB|?>&0{bN9PFl%Qt#s{dFHejLPq|&4PEpdIbPd z`n{%h7y!y{06KfW*P@OC&{Yb6^iy^QFY{XsC0x*e04RVCWPl=21zJE47z1-)1?+$` z@Bls_0EB{#fDPh6GT?zMkPCK!0#F1>!9h?B>OdoC25sOB=mO`#WpEAL0(ZeEcntVp z8oUGx;2l_oAP5VQAsQqDDM9LxE@TX`AREXT@`C)KP$&Y5g}6`#lnd>Kil8#68mfny zpk2CZRd#Z|Eb8z$BOsE5I7C0nCE!VNW;!-T=qKsc<%&5ATC3;Rg5= z+zDTXZ^5H5AASihA^;&G3`7~xLs*C-;)8@CF$fRYjuavlNCVP_^dJMsJ%o?UBOg#0 z6b;2h>7lGpZm2*M8I<5TmPhNNEz$1i5Ogd$3tfP& zKsTW~&{xr;=xOvj3DU5n74{VNB6b8jjeU~uBU~j+5Z(}pL=~b1(T^BU+)1n?o+e%=P7*(m zs3aYdBPpDeLE1+;LApeGNP0silQqb8?s>5*^~;(S;`&Cyf|K5L)=k3Qhd93jrck7aq&e7nuL*rk3_OWu|$i+ z4T)JQma0K@rgEtH)ML~u)F~Q5Q>8i5*tFfWM%q={G#x|Nq`T7-=tcCO=|l7dNvfoY zWRT<*$r{NEl6(fj&|tVTk{Bh7GmJ6DM=1pTo&d5EIhvjwT{pEAykI4_p zFDfW1xGJP5R4H6hm{(*d+9@U|mMiuu&MDE9Y?R`a%9SoEyze7t>mJq}UWHy|v5LE@Vb!=ENzYy{Q?FHTQlFvkrJtwYrT@x6%^=KRzrldP7eiCS zB*R9-$3|2m52HMz9;3gFb&T1@HOBW>lUKW}-m$uS^=lJdlW3D8CJ#($rrxG|O#4hf zo0*&O%-YQ6%+<^z%xlfZS#*{!tC)4&0&U@7vBToL#Rp3>%XG^#mVa64StVMvSk11{ zTob*fam|#qigl!Qy*1y4X%k^{)P`@XY#V9YVEfEY)sAD=WH)24ZJ%I&%Knvup##sM z!(qwM(s7&PB`3tm)v3^F$eHRK=v?jm)J4T5)}_^D!PV3?$MupM+Rf8#zuUOGf;-#2 z*?qyo++&+ZzbDCaooBV@GcO%4o>z}I?Cs%wz!-s_!wbU4HfV0xvf;)?*^NmXFKnW0irjQI0v!jz~VorE(Lw{hJjxZ`nMYqMK5X!cVnKJ(#+{ z^W-(9L1`P(y3^@`5A$G#R>lt*lbJS|HJR_Tg0jwTk=VlBGPqS|>)x$1*)G|~b5J?# zoW5M;++Deo+w8a1Z-=%=ZSUKmx+8zb^iJ2ECwCEcCGNVNXP8%(_jY&i?w)*w{GItz zKe+zTS|C=yD;VEnwWsb!)Q|B$4((mNw`%W~LQdh$BEzDJqEE%_;+sDi{Z#qW%D$L= zLnUSJiZzQmR!6dG-1=mupuB z><2Dhx4wSdJeYl$^zikg%ty{$^PiKSSIj8QG|w8(o}Y7>yZd7Oi|LmsFPG;F{*?H$ z_LbJFU;ncEYj7cCVfr=i^~&GHZ)Dz_cx&>uZ_#)0>AU22%S(mtW!|6s!1^%oG5F)m za@Hs8r^?UTpL@P|ewkQFURe>jfXD?zE+BFNkqd}iK;!}<7ZACC$OS|$AaVhb3y54m zpF6?#-ybYXRL zXm4@=0C?KVDNW8V0ssbX0w%@INVfn001Zh*K~xCWWBC97KLY>=`~v=5pU>I=0000< KMNUMnLSTZ!^xO>q literal 0 HcmV?d00001 diff --git a/www/img/undo.png b/www/img/undo.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ed14ff6dda8227a30819fb0b4fbc9a66f774f5 GIT binary patch literal 585 zcmV-P0=E5$P)&^u0oF-G zK~#9!&5}K96k!yFpLgb++00I6zlTFeSOmKmL`|~Ub$2q~v#*7StHG~IPj&CP+^0Ak_}3DHOYxS{fjkhm z=S1&M0NU5Vm{xkU&dGgQ|Ai9=kBn)x?XLi7Ume=(g!e9w$JMh3qvIvZyUE3V@%MnK zK;uGmcxNG;KT{8@GUKqnV%tX#XgBPPnqw+(eho;LCtWkJM!}oCp#}K%Nj2@rdG~Dr36U|D=pY?VYThMq`__AJ`1JjM}R~{S9~wR z_mty%R>P3PV}=GB-6&pbbsL}>AXZo`e|tXt)SyW56UroCod6AVAQMPZ-(K{O%q3im3~t6k4Ccz;%1?Mcj3j&_!Q& z9Mw-t#GM6%ocXRuOe{&@nzYNa#hks}G)<)bpe*`5FZ1p7%uK~zY`m6dC3lT{eUe{b8_(Ty>=7?wfE2r?Kb%FSe%Aq4#3 zjDAoQKM=$S7>pr&7=}O`$%r9~vBJa|rs7;!U<8pn1i6H$$R-#DV{T!?mI7nFt?k;q z_xJdrYd2U4`cK~EInVo?=YO8tIRLobO?ChWKxb#Sas2pcBmi-(L=cDrKyB@zwE!$z zRxv55B1aPKO9k3}zIDr_kw_#&Wo6Cza5y3WNdoBiZWg(PM%w7F+6zg_T+ao#=7E?3 z{VFZLjT>^cW5gtB#)Y=ZPfBzZPFtj&|iY8Q;W?ol&d&>;~>go;&AQxcWx~f|M z(l4LRoUwH4>wl+Q2q9t1svhMy^@pCbwC#ABOS;hmFv_7Dz=IgXROnYBsxSgoReQ#s zJ^N==RW+e$ng|9XqN?iqp8?wlONp+3fF3o;+byLBaTvygXNq5Q0b~p78s_ z9o^mc8UulzpK5Bh+$GtzBao3`)23Q`etvF!S=pQw3l_{o*LA|-2+?RihGCGM{S*@> zjKk$}(cIj|*|V3AHZ|@3psTAb{3wwl6M>>AUzL}?vSQk_LOdQH_4Oxix3v8Fjn~_G z&FReUpE`9`QE~Be8y7F0Gk5;{*^C+EdZV{DRNK|n_Aw9~PBMaE<;u#U{QR8KsZ$FG zhr=8=aGtul?W;qfo*O_Iux{RLX+Cz0gYbpN<;p57E}n+V<$PhzoJF%+TQ6P$l*bY@ zG*o%Y%HCRj3=iK(B;;@`)?XNnMv-Mjl4Zq_y2dls;JUly z6T3}XDoJDsG3=iN5{O3+(<_f#FgkxsPIk7F-X6c4EyC?W=ts-8bZ!R>K%|}QUtc_T za&f`c(pA&J>;z2y7c2|z%Un9D^4+P>yFXm)Jq^UtDeAmqNtSDX(tr>2$bWZi3W&&fRq*tDmvqBKD;B6ucZLTCWg#1l>{K+%)Wm|}oofng?xENYREhtm6SkqrwX z3Rqh5^){{KXCx`e}zLr|I>>q^c&N z>0pYXZX4c3(%W+IWd0008SP)t-s3^#-a zK!^xMjSWSL5=Dy_Qj$SIeHc`f9#WMfP?JhZN+wg3AzGMFP*5XUm@rqCCtR6TRaGuw zozx>KE@GU}B`nV-E;3}E%PKTpU0gS1pfhNr%r7|8Ei=(BG(2XYU|?W8XQ0(CG&yOa zI%=ajYoWh6N3uauKy9REW@bWdr9p0|XJ=>EIzLKrrbl63)$jIHw z%HF)u;?dC1&(YG)&*9b8)yLWB%G>D7+UVHX+1S|U&ED(L-s{@h=+fTn(%F@UI@%QlX@bmNY@%8!e_WSws^Yixk^Y;7l z`2P3z`uF+!`1<_$`uzI(`uh6(`uqL+`~Ld;{rmj<{QUg<{Qdj={rmm?{Qdp>{r>&^ z{r&y^{r&&?|Ns5|{{H^{{{H{{|NsC0{r~^}O)qM000001VoOIv0Eh)0NB{r;32;bR za{vGf5C8xR5CN?ty>$Qp00(qQO+^RP1Q!!335)U|@SqRe;YxGco|gz$ept zUmt4P{QBYKh~(6qv-{I}wjCtTK+AJr10Oew-`i(b@p_krN*0UuMSm^@&1L8Y2G7~E zWpAlX|DG*7S|B7A^Q`l9Azt3fH}9&w{Oc(KQzt0TnlCwVM))Z-18vsNbu)7cOu8Fu zX66MUG0pRfRO)~jc-bZ7q!8!EGM^RvT2EVRUcWw#9)_`Z6TsB<<)v;=5(79I%9cPQ zYla)KYn^AG;>odjd zYo23?WvB~*Ab#N`Hy8;Arq*U=wi2OnW-tTKn=mY1$*i~J!0TyDZLeOxUbg`w3>N~! zFxU$ia`l&j!6cG_1(|d7yuPsd*o)WC*KT-3Vor&X5mvWAF_2QQ$^8gCFH;!+0M?!F3(2%7zyJUM07*qo IM6N<$f|4A}KmY&$ literal 0 HcmV?d00001 diff --git a/www/img/valid-xhtml10.png b/www/img/valid-xhtml10.png new file mode 100644 index 0000000000000000000000000000000000000000..a35f525edf2d4f4ac4830fd824c0942b73bd88d4 GIT binary patch literal 1363 zcmV-Z1+4msP)IWd0008tP)t-s3^#-a zK!^xMjSWSL5=Dy_Qj$SIeHc`f9#WMfP?JhZN+wg3AzGMFP*5XUm@rqCCtR6TRaGuw zozx>KE@GU}B`nV-E;3}E%PKTpU0gS1pfhNr%r7|8Ei=(BG(2XYU|?W8XQ0(CG&yOa zI%=ajYoWh6N3uauKy9REW@bWdr9p0|XJ=>EIzLKrrbl-6G z#HOaDr>3Nkt<0pP#-^snkFn5|u+6Bb$eFXynY7TXtjn{ouA{WYuCC0pv$M&otf9En zp}EwbyVkb0wxYb$qrB9&x6-+})4RLXtHavAzrVe`*1*8Puf*E2#o52V*RsXjw8q`D z$K1ie*~G-ewaDGL%i_ky+{DY!$jIHi(c;n2(9hA*(b416)8y6F)yLWB%G>D7+UVBS z=GfWU&ED(L-s{@h=+fTn(%(*x1+E-P8>g??1?ey#G^Y85J=kN9C@AU2M^y%;R>+$#S z@bK{P_VV)g^YioZ_4)Aj`}y`~Cj>{r&v?{{8*^{r&#^{r~#^|NZ{{{{H^{{{Q{||NsB} z|NsA-kc^-J0004EOGiWihy@);00009a7bBm000XR000XR0j(pwbpQYW2XskIMF-Rb z7ZVUP2qVU_0000TbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAXI2&AV*0}Q14_VZU6uQ z(Md!>RCwBBV52f%VEaNUa%j;kR z-?WH7KWbP0<)DU27K`?+04@d1^kk1Y07*SYzD-;k38GGJM-Bk8?zP9f6r_K+*2sY4Z|H_QrPEZ4(_*tyeWh4V9 zO@^_|%={yjx*!JLaS6E~#JQu?X9K_1ySC~tU#>vIFz4C1R5Mfqch@EEMl#S0!E!W| zErv$Q;|V+s(#Aoajb{=#3YYJDiiniMr<_2B0KE${aN44dY1j=k63$MB#qt4G?(|+p z#kF6q7O`*nfQaSHBM<7)Tv&2yMG1z1rq*U=wi2OnW-tS9m@ur~$gH>K_?J0M?VrDV z*|r@ThKaMzd7&B@c6(DMnt^Tw&c0?2Vg^xWa04H9Yri-jSlJ_$FQUJ=rmu{571+Rz zd1k?vC!!h{ylxWMz{{5}R{_lf#eJr$oUpg3nui&}z%PetzkFD*;BJMg`Q|6nbp$)_ zla>yng@uK!%#aQI^ytf%_bZ1fB<5V zG1M0SrEbdd_3dwl|3CqdA;14Z=)XYB0K|+y%mg&xKN~9pCx-+J^9~OCzrPs31^@&Q z%iCAq{s!{=U=b4i&+z|0$Os5v1VS*)_#cd!fZXpugW7L?VEFf!@efQLKmf5Yu`n_? zXmc@$@G>!A2OvZLK`{%%^o@)R|Nk<=WdQ<+<@bMPhHt~KNkHjuKZ@WbM_y@FV^1-zgfNjz44EM`->oh zD~B}04Gwkw=Rcl+T?7z7Pyq7&v8Q7-Zzc7z6}(7}$9P8Mt_a4FLj(=dCL+{QiPH`j6q~#TQj+j*eMUub6Hy2=VhXumd$S z0;PWb`pNMA%NK?h_xTvk9NPKw%kO7v00IaYmEss_K!(BDzRdr~m&02>{J-?}_wq(yNUVfr4hDb#0{|G3WrJ$T7kdBz002ov JPDHLkV1l#));ItF literal 0 HcmV?d00001 diff --git a/www/img/wait.png b/www/img/wait.png new file mode 100644 index 0000000000000000000000000000000000000000..1de43d56b057abd5bab76b97724d0db42b2aaf83 GIT binary patch literal 1049 zcmV+!1m^pRP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ0tk-OlK0J5%RKl$ZR3;ww?F;)|LyPp{~b%O z|F4;N;{T)X|No!=@b7=_n*0AntmpmbQ|+4%(+3bhFwFt#S%>~lz4GP%%b)-Mzy0<9 z|2rVQaR1}~lQ-Y}zyIz3{~Moy{Ez?tcb@(9U(jgUe=e!E0FYjQ0Af~6+AF~D@Be-$ zKXs0HBO!+WK*4`N40JgICl5OV7au3XZ=gVVMk2$p1N#`f0|FR+i3u`X*?!4`iPd%{ zKmalQ|NAe1ONvh*(n6f!7f|8PzYzQbgh6~DE=x~j*u7~TgR!$0!yBN0tez|bpQ?nw zzdwHi00M~V|DV713MxVj94t&=4Ium-N`nk32Ws90)LbxaIm2H~JBIyFzB1hZ_>)1- zQ4u)mHn@KXrNb@l;1LLNzvXFu8`v-;%OBXP>XH_!1_{qp1 z1N0W#uRjbo58h@Fmf!~&pa2j+OhAHx5h(HI^=F1RU;hG~$iVOxi0?mmz+i804-Vv= z)7ly4rg$-M{QAnk%k-at_3Kv#P8Ogo|Nk=p1P}`-k$ipkmBBK|h=B!Y^@pGT8912# zGZggCWw>_y0K>c!w-|UuC4k=f&+y|v3j;SVGlN5{1;g>RXF+B^00=p1Y;hc1zbQ2o}7Ka@ZijS zP?FvN5I{`N_eFz~=gKLE8UFqF4K{?EnSlZ5QigAzelmOpdXERl28o0G{rBq+hD8-? zK(;3WgZcwN05OAD-=1!|@sHD4;rO1L2I^`e49c?nK(8<`tlDs$;p&-(4Cdx?KxZ>B zoH~4$p(=6?!|NySCjd211nC6`Ae79+tK1s^%zg8X4W$GkLUb8a{{6>r^WHm# zWs6RO4EO-G8J?K{0*DbkQ*ny7fKwRIAbTKI07divfBzqV0u1D5kh7810|XcV^d_H1 Tk^AtW00000NkvXXu0mjfSz_lE literal 0 HcmV?d00001 diff --git a/www/img/warning.png b/www/img/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..612491d4d2ec7cc8c53827b9e05f48a815a6d53f GIT binary patch literal 578 zcmV-I0=@l-P)N4%al@Z!TYHb2_N0`%Xi^XV7k)VlHF zY~j9M;?Swdt$pz0l=06+wvH&>&7dYHIRF0uj))rF+(yf#LqInk_xCE=&LH;WSoP>Z z@ZO2%)OQdPA@b!b?Ams~nJBc382|en)2>(d?%4C^rTO&$?c7?}rWq`Qp-}j671Z2*sVhP@fq>ql*ge!&#fox*@rkhMGzD# z>*g}-+hOC!Z}RB4-nB^o{|Wc&rYGOUvj6}90d!JMQvg8b*k%9#00Cl4M??UK1szBL z000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i6Az5eqbTg2Gh*005pzL_t&-(_>)3 z4s^NX%uobkqTS?>`TS9OL8@#>0>&QRA$EqGa6Yq*xNEqVj}DA)Z!E^4CZ(v%!~+!& z4)wQ|=haqs;D+$s%}s@rWY|3gEchhB0s%o9k*pE20=D|n&LF;%k&1?aGK-&uzO*!> zC{Q3+&p*<@L_RE58VFcG0&%87KE8npAilH~P(Z}WMN`w!*%AaK1Q`ee04r!0U)IQe QJOBUy07*qoM6N<$f*gh!k^lez literal 0 HcmV?d00001 diff --git a/www/index.php b/www/index.php new file mode 100644 index 0000000..2936d85 --- /dev/null +++ b/www/index.php @@ -0,0 +1,280 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +session_start(); +header('Cache-Control: private, + must-revalidate, + max-age=3600, + post-check=3600, + pre-check=3600'); +require_once 'init.inc.php'; +require_once 'Pear/HTML/Table.php'; +require_once 'Pear/HTML/QuickForm.php'; +require_once 'htmlUtil.php'; +require_once 'dbUtil.php'; +require_once 'langUtil.php'; +require_once 'authUtil.php'; + + +if (!file_exists(ORTRO_CONF . 'configure.php')) { + //show the setup page + include ORTRO_TEMPLATE . 'install/index.php'; + exit; +} + +$auth = new AuthUtil(); + +$language = $auth->getSessionData('language'); +if (!$language) { + //setting the default language for the session + $language = ORTRO_DEFAULT_LANGUAGE; + if (isset($conf['env']['lang'])) { + $language = $conf['env']['lang']; + } + $auth->setSessionData('language', $language); +} + +if (!$auth->isAuthorized()) { + //show the login page + i18n('template', 'common.php'); + include ORTRO_TEMPLATE . 'login.php'; + exit; +} elseif (isset($_REQUEST['logout'])) { + //logout + $auth->logout(); + i18n('template', 'action_msg.php'); + header('location:?'); + exit; +} else { + //Get the system id from request for apply policy + $policy_id_system = false; + $user_is_system_admin = false; + $user_is_system_guest = false; + $user_is_admin = false; + $user_is_guest = false; + $error_code = ''; + + //Check fo valid categories + $allowed_cat = array('autodiscovery', + 'cas_settings', + 'db', + 'filemanager', + 'group', + 'host', + 'identity_management', + 'import_export', + 'jobs', + 'ldap_settings', + 'notify', + 'plugin', + 'plugin_notify', + 'settings', + 'system', + 'user', + 'workflows'); + + if (!in_array($_REQUEST['cat'], $allowed_cat)) { + $error_code = 404; + } + + //Check fo valid categories + $allowed_mode = array('action', 'add', 'details', 'edit', 'install', 'view'); + + if (!in_array($_REQUEST['mode'], $allowed_mode)) { + $error_code = 404; + } + + $_policy = $auth->getSessionData('policy'); + + if (isset($_REQUEST['systemHost'][0])) { + //used when you add/modify a system/host + $policy_id_system = $_REQUEST['systemHost'][0]; + } + if (isset($_REQUEST['systemHostDb'][0])) { + //used when you add/modify a db + $policy_id_system = $_REQUEST['systemHostDb'][0]; + } + if (isset($_REQUEST['id_system'])) { + //used when you add/modify a db + $policy_id_system = $_REQUEST['id_system']; + } + + if (isset($_REQUEST['id_chk'])) { + //used when you request action from view + $policy_id_system = $_REQUEST['id_chk'][key($_REQUEST['id_chk'])]; + } + + if (isset($_policy['SYSTEM_GUEST'])) { + if (in_array($policy_id_system, + explode(',', $_policy['SYSTEM_GUEST']))) { + $user_is_system_guest = true; + } + } + if (array_key_exists('GUEST', $_policy)) { + $user_is_guest = true; + } + if (isset($_policy['SYSTEM_ADMIN'])) { + if (in_array($policy_id_system, + explode(',', $_policy['SYSTEM_ADMIN']))) { + $user_is_admin_for_system = true; + } + if (count($_policy['SYSTEM_ADMIN']) > 0) { + if (count(explode(',', + $_policy['SYSTEM_ADMIN']))>0) { + $user_is_system_admin = true; + } + } + } + if (array_key_exists('ADMIN', $_policy)) { + $user_is_admin = true; + } + + if (isset($_REQUEST['download']) && $_REQUEST['download'] != '') { + $id_system = $_REQUEST['id_system']; + if ($_REQUEST['cat'] == 'filemanager') { + $file_path = ORTRO_INCOMING . $id_system . DS; + } else { + $file_path = ORTRO_REPORTS . $id_system . DS . $_REQUEST['id_job']; + } + $file_to_download = $file_path . DS . $_REQUEST['download']; + if (is_file($file_to_download) && (strpos($file_to_download, '..') === false)) { + httpDownload($_REQUEST['download'], $file_to_download); + exit; + } + } + + if (($user_is_admin || $user_is_system_admin) && + isset($_REQUEST['cat']) && + $_REQUEST['cat'] == 'ssh_public_key') { + //allows to download the ssh public key and exit + $ssh_public_key = $GLOBALS['conf']['env']['ssh_keyname'] . '.pub'; + httpDownload($ssh_public_key, ORTRO_SSH_PATH . $ssh_public_key); + exit; + } + + /* Define the policy for the categories */ + + if (isset($_REQUEST['action']) && $_REQUEST['action'] != '') { + // An action was requested... + i18n('template', 'action_msg.php'); + if ($user_is_system_admin || $user_is_admin || + ($_REQUEST['profile'] == 'edit' && + $auth->getSessionData('userid') == $_REQUEST['id_user'])) { + // Administrator for this system or modify the owner profile + $template = ORTRO_TEMPLATE . 'action' . DS . + $_REQUEST['cat'] . '.php'; + if (is_file($template) && (strpos($template, '..') === false)) { + include $template; + if ($_REQUEST['ajax'] == 1) { + exit; + } + } else { + $error_code = 404; + } + } else { + $error_code = 403; + } + } else { + if (!$user_is_admin) { + switch ($_REQUEST['cat']) { + case 'identity_management': + if (!$user_is_system_admin) { + $error_code = 403; + } + break; + case 'system': + case 'identity_management': + case 'userGroup': + case 'group': + //mode not allowed + $error_code = 403; + break; + + case 'user': + // allows to edit the own profile + if ($_REQUEST['profile'] != 'edit') { + $error_code = 403; + } + break; + + default: + //access to the category is allowed + break; + } + if (!isset($error_code) && !$user_is_system_admin) { + // other profile check for policy on mode + switch ($_REQUEST['mode']) { + case 'add': + if (!$user_is_system_admin) { + $error_code = 403; + } + break; + + case 'view': + case 'refresh_page': + case 'details': + case 'detail': + break; + + default: + $error_code = 403; + break; + + } + } + } + } + + switch ($error_code) { + case 403: + i18n('template', 'action_msg.php'); + $error_msg = MSG_PERMISSION_DENIED; + break; + case 404: + $error_msg = MSG_PAGE_NOT_FOUND; + break; + default: + break; + } + i18n('template', 'common.php'); + i18n('template', 'header.php'); + include ORTRO_TEMPLATE . 'header.php'; + ?> + + + + + +
+ + + +
+ \ No newline at end of file diff --git a/www/init.inc.php b/www/init.inc.php new file mode 100644 index 0000000..d972034 --- /dev/null +++ b/www/init.inc.php @@ -0,0 +1,22 @@ + + * @license GNU/GPL v2 + * @link http://www.ortro.net + */ + +require_once realpath(dirname(__FILE__) . '/../conf/init.php'); +?> \ No newline at end of file diff --git a/www/js/FCKeditor/editor/css/behaviors/disablehandles.htc b/www/js/FCKeditor/editor/css/behaviors/disablehandles.htc new file mode 100644 index 0000000..8dfb661 --- /dev/null +++ b/www/js/FCKeditor/editor/css/behaviors/disablehandles.htc @@ -0,0 +1,15 @@ + + + + + diff --git a/www/js/FCKeditor/editor/css/behaviors/showtableborders.htc b/www/js/FCKeditor/editor/css/behaviors/showtableborders.htc new file mode 100644 index 0000000..77418b9 --- /dev/null +++ b/www/js/FCKeditor/editor/css/behaviors/showtableborders.htc @@ -0,0 +1,36 @@ + + + + + + + + diff --git a/www/js/FCKeditor/editor/css/fck_editorarea.css b/www/js/FCKeditor/editor/css/fck_editorarea.css new file mode 100644 index 0000000..8a328bb --- /dev/null +++ b/www/js/FCKeditor/editor/css/fck_editorarea.css @@ -0,0 +1,110 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the default CSS file used by the editor area. It defines the + * initial font of the editor and background color. + * + * A user can configure the editor to use another CSS file. Just change + * the value of the FCKConfig.EditorAreaCSS key in the configuration + * file. + */ + +/** + * The "body" styles should match your editor web site, mainly regarding + * background color and font family and size. + */ + +body +{ + background-color: #ffffff; + padding: 5px 5px 5px 5px; + margin: 0px; +} + +body, td +{ + font-family: Arial, Verdana, sans-serif; + font-size: 12px; +} + +a[href] +{ + color: -moz-hyperlinktext !important; /* For Firefox... mark as important, otherwise it becomes black */ + text-decoration: -moz-anchor-decoration; /* For Firefox 3, otherwise no underline will be used */ +} + +/** + * Just uncomment the following block if you want to avoid spaces between + * paragraphs. Remember to apply the same style in your output front end page. + */ + +/* +p, ul, li +{ + margin-top: 0px; + margin-bottom: 0px; +} +*/ + +/** + * Uncomment the following block, or only selected lines if appropriate, + * if you have some style items that would break the styles combo box. + * You can also write other CSS overrides inside the style block below + * as needed and they will be applied to inside the style combo only. + */ + +/* +.SC_Item *, .SC_ItemSelected * +{ + margin: 0px !important; + padding: 0px !important; + text-indent: 0px !important; + clip: auto !important; + position: static !important; +} +*/ + +/** + * The following are some sample styles used in the "Styles" toolbar command. + * You should instead remove them, and include the styles used by the site + * you are using the editor in. + */ + +.Bold +{ + font-weight: bold; +} + +.Title +{ + font-weight: bold; + font-size: 18px; + color: #cc3300; +} + +.Code +{ + border: #8b4513 1px solid; + padding-right: 5px; + padding-left: 5px; + color: #000066; + font-family: 'Courier New' , Monospace; + background-color: #ff9933; +} diff --git a/www/js/FCKeditor/editor/css/fck_internal.css b/www/js/FCKeditor/editor/css/fck_internal.css new file mode 100644 index 0000000..725272f --- /dev/null +++ b/www/js/FCKeditor/editor/css/fck_internal.css @@ -0,0 +1,199 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This CSS Style Sheet defines rules used by the editor for its internal use. + */ + +/* ######### + * WARNING + * ######### + * When changing this file, the minified version of it must be updated in the + * fckeditor.html file (see FCK_InternalCSS). + */ + +/* Fix to allow putting the caret at the end of the content in Firefox if + clicking below the content. */ +html +{ + min-height: 100%; +} + +table.FCK__ShowTableBorders, table.FCK__ShowTableBorders td, table.FCK__ShowTableBorders th +{ + border: #d3d3d3 1px solid; +} + +form +{ + border: 1px dotted #FF0000; + padding: 2px; +} + +.FCK__Flash +{ + border: #a9a9a9 1px solid; + background-position: center center; + background-image: url(images/fck_flashlogo.gif); + background-repeat: no-repeat; + width: 80px; + height: 80px; +} + +.FCK__UnknownObject +{ + border: #a9a9a9 1px solid; + background-position: center center; + background-image: url(images/fck_plugin.gif); + background-repeat: no-repeat; + width: 80px; + height: 80px; +} + +/* Empty anchors images */ +.FCK__Anchor +{ + border: 1px dotted #00F; + background-position: center center; + background-image: url(images/fck_anchor.gif); + background-repeat: no-repeat; + width: 16px; + height: 15px; + vertical-align: middle; +} + +/* Anchors with content */ +.FCK__AnchorC +{ + border: 1px dotted #00F; + background-position: 1px center; + background-image: url(images/fck_anchor.gif); + background-repeat: no-repeat; + padding-left: 18px; +} + +/* Any anchor for non-IE, if we combine it with the previous rule IE ignores all. */ +a[name] +{ + border: 1px dotted #00F; + background-position: 0 center; + background-image: url(images/fck_anchor.gif); + background-repeat: no-repeat; + padding-left: 18px; +} + +.FCK__PageBreak +{ + background-position: center center; + background-image: url(images/fck_pagebreak.gif); + background-repeat: no-repeat; + clear: both; + display: block; + float: none; + width: 100%; + border-top: #999999 1px dotted; + border-bottom: #999999 1px dotted; + border-right: 0px; + border-left: 0px; + height: 5px; +} + +/* Hidden fields */ +.FCK__InputHidden +{ + width: 19px; + height: 18px; + background-image: url(images/fck_hiddenfield.gif); + background-repeat: no-repeat; + vertical-align: text-bottom; + background-position: center center; +} + +.FCK__ShowBlocks p, +.FCK__ShowBlocks div, +.FCK__ShowBlocks pre, +.FCK__ShowBlocks address, +.FCK__ShowBlocks blockquote, +.FCK__ShowBlocks h1, +.FCK__ShowBlocks h2, +.FCK__ShowBlocks h3, +.FCK__ShowBlocks h4, +.FCK__ShowBlocks h5, +.FCK__ShowBlocks h6 +{ + background-repeat: no-repeat; + border: 1px dotted gray; + padding-top: 8px; + padding-left: 8px; +} + +.FCK__ShowBlocks p +{ + background-image: url(images/block_p.png); +} + +.FCK__ShowBlocks div +{ + background-image: url(images/block_div.png); +} + +.FCK__ShowBlocks pre +{ + background-image: url(images/block_pre.png); +} + +.FCK__ShowBlocks address +{ + background-image: url(images/block_address.png); +} + +.FCK__ShowBlocks blockquote +{ + background-image: url(images/block_blockquote.png); +} + +.FCK__ShowBlocks h1 +{ + background-image: url(images/block_h1.png); +} + +.FCK__ShowBlocks h2 +{ + background-image: url(images/block_h2.png); +} + +.FCK__ShowBlocks h3 +{ + background-image: url(images/block_h3.png); +} + +.FCK__ShowBlocks h4 +{ + background-image: url(images/block_h4.png); +} + +.FCK__ShowBlocks h5 +{ + background-image: url(images/block_h5.png); +} + +.FCK__ShowBlocks h6 +{ + background-image: url(images/block_h6.png); +} diff --git a/www/js/FCKeditor/editor/css/fck_showtableborders_gecko.css b/www/js/FCKeditor/editor/css/fck_showtableborders_gecko.css new file mode 100644 index 0000000..87ab979 --- /dev/null +++ b/www/js/FCKeditor/editor/css/fck_showtableborders_gecko.css @@ -0,0 +1,49 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This CSS Style Sheet defines the rules to show table borders on Gecko. + */ + +/* ######### + * WARNING + * ######### + * When changing this file, the minified version of it must be updated in the + * fckeditor.html file (see FCK_ShowTableBordersCSS). + */ + +/* For tables with the "border" attribute set to "0" */ +table[border="0"], +table[border="0"] > tr > td, table[border="0"] > tr > th, +table[border="0"] > tbody > tr > td, table[border="0"] > tbody > tr > th, +table[border="0"] > thead > tr > td, table[border="0"] > thead > tr > th, +table[border="0"] > tfoot > tr > td, table[border="0"] > tfoot > tr > th +{ + border: #d3d3d3 1px dotted ; +} + +/* For tables with no "border" attribute set */ +table:not([border]), +table:not([border]) > tr > td, table:not([border]) > tr > th, +table:not([border]) > tbody > tr > td, table:not([border]) > tbody > tr > th, +table:not([border]) > thead > tr > td, table:not([border]) > thead > tr > th, +table:not([border]) > tfoot > tr > td, table:not([border]) > tfoot > tr > th +{ + border: #d3d3d3 1px dotted ; +} diff --git a/www/js/FCKeditor/editor/css/images/block_address.png b/www/js/FCKeditor/editor/css/images/block_address.png new file mode 100644 index 0000000000000000000000000000000000000000..8bbae6e5ad708d9023696ab3a227b227d38c52ea GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^xfDwCDYhhUcNd2LAh=-f^2tCE&H|6f zVg?3oVGw3ym^DWND9B#o>FdgVokNUIi-}jvbvIB*w!}4}#5q4VH#M(>!MP|ku_QG` zp**uBLm?z1Rl(iUH{gAWY93Hwi>HfYNX4zUQx5VSP~dRx{&@K3=eH?N92=}Qr?6Kk z`FBP+EV$~Wdb4R&+$t??vzRw>)1t*bYTP&SdiUV*jrdtN#h)@9SP|pLck7X~8s}k# zgu1KcJ~!VwYr9#-PJMR8^1S%x;(*XRk+p(qw-{3`tj(>{&Q30}_x)8>@{N0MZhzS7 bugrH3X)o?w_h=nA&^-*Eu6{1-oD!MFdgVos*TFNyzr0pfylPw!}4}#5q4VH#M(>!MP|ku_QG` zp**uBLm?z1Rl(iUH{gAWY93Hwr>Bc!NX4zUAs6`$7_cn4+5Wq@I!mpot?w?t)rv0ck=8q5%o&#@Y@$HwKqC9;r#L3y=m ziRsztKF1z%ByZo+y0Dc0{nfR0_f|d%uGXE?oWDi2{@M1Jhh_EN`6`PdviA!qhc4Xp hQvA|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;VIeuy8>v7c*%H@?66gHf+|;}h2Ir#G#FEq$ zh4Rdj426)4R0VfW-+=cis(C<#o}Mm_Ar-fh6C_xfS*4_;{v9^hWnt8-=cko$DA7_` z@zuj%uAbQJW)`z=fuH#7cLy|5bu5|dL`v|$E%gIE?u$Va$`Kp$iREekWp&q RKOdl>44$rjF6*2UngAfwM|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;ZT-MY8vQ^a*%H@?66gHf+|;}h2Ir#G#FEq$ zh4Rdj426)4R0VfW-+=cis(C<#cAhSdAr-fh6C_xfS*4_;{v{_TKMrP^aiUOQuWs6s zWk+?se2~3pmzR-|uw)zmNxoN%n|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;eQ6OcNjspBY>8_`iF1B#Zfaf$gL6@8Vo7R> zLV0FMhC)b2s)DC!}47L6$^@kkgTe~ HDWM4fvNb)= literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/css/images/block_h3.png b/www/js/FCKeditor/editor/css/images/block_h3.png new file mode 100644 index 0000000000000000000000000000000000000000..3c3034faf54dfb53b179f58317baae85250b233c GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^azM<_!3HEh@2Z~zq}Y|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;9eugU`#gX`vL&t&CC>S|xv6<249-QVi6yBi z3gww4844j8sS56%z5(x3RP%re?LA!_Ln>}1CrGd|vr0)x{d=6G{P|^)q2BQTrWqY2 zJjz>bPdJ^p9#M1NbP0 Hl+XkKqp?E8 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/css/images/block_h4.png b/www/js/FCKeditor/editor/css/images/block_h4.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3f64de6b97f8b53891b931b353eb2e66a959cd GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^azM<_!3HEh@2Z~zq}Y|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;U2f~{>>EHK*%H@?66gHf+|;}h2Ir#G#FEq$ zh4Rdj426)4R0VfW-+=cis(C<#o}Mm_Ar-fh6C_xfS*4_;{v{_L{_!H|36olo%#{ll z4tVJD8}Wvm*d)M}7xhDIdB3!jl*C0{r@r{CqsA9IyJt-^>V5V&(BKUNgX(m(maolf RN|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;eX*?Fsm(wk*%H@?66gHf+|;}h2Ir#G#FEq$ zh4Rdj426)4R0VfW-+=cis(C<#0iG_7Ar-fh6C_xfS*4_;{w>}t4J4J5vu+%AYHF5P z`O;A>$f+r6-_e)JIbsKDcuE|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;UCYlgRuMoU*%H@?66gHf+|;}h2Ir#G#FEq$ zh4Rdj426)4R0VfW-+=cis(C<#Hl8kyAr-fh6C_xfS*4_;{yk1o{`@k@Q15sE(~J`Z z63V7JX^Ky>b@rvpL^}HF9&pOpbIE3f`$3HbVhju`%(R>8GXp^GX7F_Nb6Mw<&;$T| CZaz%_ literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/css/images/block_p.png b/www/js/FCKeditor/editor/css/images/block_p.png new file mode 100644 index 0000000000000000000000000000000000000000..d055c514a6c77c69bea7ef2994e060e2d908a722 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^azM<_!3HEh@2Z~zq}Y|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;E#A2+BeZ}*vL&t&CC>S|xv6<249-QVi6yBi z3gww4844j8sS56%z5(x3RP%re4Lw~PLn>}1CrGfCF!j7(;^pQ2fAL38Ng=0L_y5a> sd~`QfF^0PPoCyaGIUJ?R>F8HBd8yr>mdKI;Vst07*(dMF0Q* literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/css/images/block_pre.png b/www/js/FCKeditor/editor/css/images/block_pre.png new file mode 100644 index 0000000000000000000000000000000000000000..be8ad26a75ad27b456dd0835d4667ed92fc17cf2 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^azM<_!3HEh@2Z~zq}Y|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfbq+B;E%`hF%_N|ZY>8_`iF1B#Zfaf$gL6@8Vo7R> zLV0FMhC)b2s)DgJ|Uu&?oD;%Ae!z@09(NL_hv#6Slx0y!YR{?r|LJZgAju=f-$sQVWNL{+Tsz18#+~Ke%+zTWns()WcPwy8dQcr!JH# U&i)o#hQ}|Gy#O|EKr=edPZ~8vO4q_`j_G|MH3d zH_!iH9Pr;);s3MyKRjgr`6&F~H2-;B+P@j~|2ED08=?O(&g$W$rvFR(|KB|SuRh_y z{7L`!um2Zm@S;BL-=_J0>*N3R6x?1h|K7ZbUxT&p&ztz9qvT(j!@s3{|Lg_+cISVJ zv-*=__cg)hKTu^+z;8RgcNrf4dkX%iIs7+f_zwmQxPjtN7DfgJGX@=y5|E!5*#0}r zF7VKiY8MG;J!WGy|8S>+g9nR{$%<_pnL1eyq7-)D4dPDxuw%{AWrwr3ZFa6WeDYJ$ zibg+iA!FW(N@o+sd>JNwA?X%ZedBy?6Y)OxwoE>zsncAgCT1Fo&2=-8$xK#V;-bNu zZ|t*iwSZAs`DzosZCTAN^LOuAq8Wdnuup_3Uy||6nTWXp3^O-g*_$KJRGYxSzuJZA zQYMq~Jty@AiQEQH&1BhcnX)peEfLo8X8B-xX9o}Gu2UHu2TD)$*>K)7*sEF4;9}WY zz|vC{5x}F<@+L!o;eZ1}uf&_S4H+8`IWL}|5j<_>F$M-+1~;2SB8L>N@hJKh?6Pq< z^7KrJqTmb(fk%@Xcp2Cdo^AO!sjZPQpnsoEkplyp5!W2P0|6auAxyrkXC$=0s{4ui z^l~{G9DeMpmdtOm*Yb$EAd6q(L`ee|yPs^ir><{U!f-(AfHuRcDf?R)&Nw)z b9J+CuD@{Yf=%(AVjaetTW(q2DFjxZs`Jnz5 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/css/images/fck_hiddenfield.gif b/www/js/FCKeditor/editor/css/images/fck_hiddenfield.gif new file mode 100644 index 0000000000000000000000000000000000000000..953f643b60032c36ac92590950577c336f133512 GIT binary patch literal 105 zcmZ?wbhEHb6lM@&n8?8JABg_{Z)j*>U|`SzVg`^n1Cx_W&+?fM`5zlEy44+e;LbT+ zkH8h7N-kQ@I;_|Q}>&=&Wsxvt_U!{00zr0#2QD@sN HCI)K&$9F25 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/css/images/fck_pagebreak.gif b/www/js/FCKeditor/editor/css/images/fck_pagebreak.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d1cffd64af72709b1180b3b0a51bbfe30bcb8c6 GIT binary patch literal 54 zcmZ?wbhEHbR zh=C=r6qdmXSP83OHN-(Ytbw)g9;}1)kN_JY5t872NQTXj3R@u!(&0nc1{%nKOvnN) zWJ3<Tuow2hekg_mPy(fJ5Dvj%(1QWWpd2dT2pok^pb|cX z<8T5_!YTL+s-PN-@Hy1L7jPQBgfnm!zJhab9xlMw@C}%t7V6+4)WaocfJSJ7W@v#{ z_!ho{@8Jh%gUfIQ+Tki(gCF51xDG$VFK`1o;8*w!euqxzf}8LMbi*z96K=yDxC{5- zFZdho!$0r<9>OE&fydAbPv9v$gXi!9{)Ikx3H>m@!2boee%bV-Rk6vdRw`1~B*!a4 z!)Ha}_CjbTd1dLtD_)0!xSxSR&S6#h+AOjC=$NJ|!^K>w`;5}C>at7u@`-CZnySki z3(TcDhg5wx0*k@QFukfaQ)DgIRftWZe8^*LrjOHEOfd85t92z|ueNR8)y zzZhe*VdN@_;}~y|ph<7pW(e6cId6vJ7;E#7qt7fqAh;C1+tbHWieIEkJW=Zq+#w^vl71ZsRdrfq@(<^e1^&`W@hC(N~6h)*;C9q3;E?qn+ zygk~t!N1=>b(b=C$MEs1yYGyz56K@I_>`@IUTy|&2Q_HB8s)?tw*F=zOu-s&YO?;cCksDuw6We99WkRh~a zTY%-XK0meH>_|hfJpO!au4}gDQnUB*O1nTaae>Kdtc^mJ{ig^etV>B$>)@~Y9QL~EBpu#Lhi z+i`K)We?|+;xjsBnxUsy6;d=EEo3%JRkSmup*nZ39kAiBebJAVN1jWLR8f zS58&B^{yuO!b8?3v*EK86quJwN!LF9G=ap|ta~?KK6)V#3WHgT0 zd_6JOQ4!Ip5<2%un>A}Z@=yI@(a&SrS!CH>+XBp7CP=_@709~ MFP~hub&xXkKL?Jd#{d8T literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/dialog/common/fck_dialog_common.css b/www/js/FCKeditor/editor/dialog/common/fck_dialog_common.css new file mode 100644 index 0000000..4e06834 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/common/fck_dialog_common.css @@ -0,0 +1,85 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This is the CSS file used for interface details in some dialog + * windows. + */ + +/* ######### + * WARNING + * ######### + * When changing this file, the minified version of it must be updated in the + * fck_dialog_common.js file (see GetCommonDialogCss). + */ + +.ImagePreviewArea +{ + border: #000000 1px solid; + overflow: auto; + width: 100%; + height: 170px; + background-color: #ffffff; +} + +.FlashPreviewArea +{ + border: #000000 1px solid; + padding: 5px; + overflow: auto; + width: 100%; + height: 170px; + background-color: #ffffff; +} + +.BtnReset +{ + float: left; + background-position: center center; + background-image: url(images/reset.gif); + width: 16px; + height: 16px; + background-repeat: no-repeat; + border: 1px none; + font-size: 1px ; +} + +.BtnLocked, .BtnUnlocked +{ + float: left; + background-position: center center; + background-image: url(images/locked.gif); + width: 16px; + height: 16px; + background-repeat: no-repeat; + border: none 1px; + font-size: 1px ; +} + +.BtnUnlocked +{ + background-image: url(images/unlocked.gif); +} + +.BtnOver +{ + border: outset 1px; + cursor: pointer; + cursor: hand; +} diff --git a/www/js/FCKeditor/editor/dialog/common/fck_dialog_common.js b/www/js/FCKeditor/editor/dialog/common/fck_dialog_common.js new file mode 100644 index 0000000..5536a83 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/common/fck_dialog_common.js @@ -0,0 +1,347 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Useful functions used by almost all dialog window pages. + * Dialogs should link to this file as the very first script on the page. + */ + +// Automatically detect the correct document.domain (#123). +(function() +{ + var d = document.domain ; + + while ( true ) + { + // Test if we can access a parent property. + try + { + var test = window.parent.document.domain ; + break ; + } + catch( e ) {} + + // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ... + d = d.replace( /.*?(?:\.|$)/, '' ) ; + + if ( d.length == 0 ) + break ; // It was not able to detect the domain. + + try + { + document.domain = d ; + } + catch (e) + { + break ; + } + } +})() ; + +// Attention: FCKConfig must be available in the page. +function GetCommonDialogCss( prefix ) +{ + // CSS minified by http://iceyboard.no-ip.org/projects/css_compressor (see _dev/css_compression.txt). + return FCKConfig.BasePath + 'dialog/common/' + '|.ImagePreviewArea{border:#000 1px solid;overflow:auto;width:100%;height:170px;background-color:#fff}.FlashPreviewArea{border:#000 1px solid;padding:5px;overflow:auto;width:100%;height:170px;background-color:#fff}.BtnReset{float:left;background-position:center center;background-image:url(images/reset.gif);width:16px;height:16px;background-repeat:no-repeat;border:1px none;font-size:1px}.BtnLocked,.BtnUnlocked{float:left;background-position:center center;background-image:url(images/locked.gif);width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.BtnUnlocked{background-image:url(images/unlocked.gif)}.BtnOver{border:outset 1px;cursor:pointer;cursor:hand}' ; +} + +// Gets a element by its Id. Used for shorter coding. +function GetE( elementId ) +{ + return document.getElementById( elementId ) ; +} + +function ShowE( element, isVisible ) +{ + if ( typeof( element ) == 'string' ) + element = GetE( element ) ; + element.style.display = isVisible ? '' : 'none' ; +} + +function SetAttribute( element, attName, attValue ) +{ + if ( attValue == null || attValue.length == 0 ) + element.removeAttribute( attName, 0 ) ; // 0 : Case Insensitive + else + element.setAttribute( attName, attValue, 0 ) ; // 0 : Case Insensitive +} + +function GetAttribute( element, attName, valueIfNull ) +{ + var oAtt = element.attributes[attName] ; + + if ( oAtt == null || !oAtt.specified ) + return valueIfNull ? valueIfNull : '' ; + + var oValue = element.getAttribute( attName, 2 ) ; + + if ( oValue == null ) + oValue = oAtt.nodeValue ; + + return ( oValue == null ? valueIfNull : oValue ) ; +} + +function SelectField( elementId ) +{ + var element = GetE( elementId ) ; + element.focus() ; + + // element.select may not be available for some fields (like + + + + + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_button.html b/www/js/FCKeditor/editor/dialog/fck_button.html new file mode 100644 index 0000000..6dc21b4 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_button.html @@ -0,0 +1,104 @@ + + + + + Button Properties + + + + + + + + + + +
+ + + + + + + + + + +
+ Name
+ +
+ Text (Value)
+ +
+ Type
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_checkbox.html b/www/js/FCKeditor/editor/dialog/fck_checkbox.html new file mode 100644 index 0000000..9a5d43c --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_checkbox.html @@ -0,0 +1,104 @@ + + + + + Checkbox Properties + + + + + + + + + + +
+ + + + + + + + + + +
+ Name
+ +
+ Value
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_colorselector.html b/www/js/FCKeditor/editor/dialog/fck_colorselector.html new file mode 100644 index 0000000..a6eac5c --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_colorselector.html @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + +
+ + + + + +
+ +
+
+ Highlight +
+
 
+ Selected +
+ +
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_div.html b/www/js/FCKeditor/editor/dialog/fck_div.html new file mode 100644 index 0000000..c5496e1 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_div.html @@ -0,0 +1,396 @@ + + + + + + + + + + + +
+ + + + + + + + + + + +
+ Style
+ +
  + Stylesheet Classes
+ +
+
+ + + diff --git a/www/js/FCKeditor/editor/dialog/fck_docprops.html b/www/js/FCKeditor/editor/dialog/fck_docprops.html new file mode 100644 index 0000000..364a23d --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_docprops.html @@ -0,0 +1,600 @@ + + + + + + + + + + + + + + + + + + +
+
+ Page Title
+ +
+ + + + + + +
+ Language Direction
+ +
+     + Language Code
+ +
+
+ + + + + + + + + + + + + + +
+ Character Set Encoding
+ +
+     + Other Character Set Encoding
+ +
+  
+ Document Type Heading
+ +
+ + Other Document Type Heading
+ +
+
+ + +
+ + + +
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_docprops/fck_document_preview.html b/www/js/FCKeditor/editor/dialog/fck_docprops/fck_document_preview.html new file mode 100644 index 0000000..5ea9efb --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_docprops/fck_document_preview.html @@ -0,0 +1,113 @@ + + + + + Document Properties - Preview + + + + + + + + + + + + + + +
+ Normal Text +
+ Visited Link + + Active Link +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_flash.html b/www/js/FCKeditor/editor/dialog/fck_flash.html new file mode 100644 index 0000000..2db4846 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_flash.html @@ -0,0 +1,152 @@ + + + + + Flash Properties + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + +
URL +
+
+
+ + + + + + +
+ Width
+ +
  + Height
+ +
+
+ + + + +
+ + + + + + + +
Preview
+
+
+
+ + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_flash/fck_flash.js b/www/js/FCKeditor/editor/dialog/fck_flash/fck_flash.js new file mode 100644 index 0000000..ca62ad0 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_flash/fck_flash.js @@ -0,0 +1,300 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts related to the Flash dialog window (see fck_flash.html). + */ + +var dialog = window.parent ; +var oEditor = dialog.InnerDialogLoaded() ; +var FCK = oEditor.FCK ; +var FCKLang = oEditor.FCKLang ; +var FCKConfig = oEditor.FCKConfig ; +var FCKTools = oEditor.FCKTools ; + +//#### Dialog Tabs + +// Set the dialog tabs. +dialog.AddTab( 'Info', oEditor.FCKLang.DlgInfoTab ) ; + +if ( FCKConfig.FlashUpload ) + dialog.AddTab( 'Upload', FCKLang.DlgLnkUpload ) ; + +if ( !FCKConfig.FlashDlgHideAdvanced ) + dialog.AddTab( 'Advanced', oEditor.FCKLang.DlgAdvancedTag ) ; + +// Function called when a dialog tag is selected. +function OnDialogTabChange( tabCode ) +{ + ShowE('divInfo' , ( tabCode == 'Info' ) ) ; + ShowE('divUpload' , ( tabCode == 'Upload' ) ) ; + ShowE('divAdvanced' , ( tabCode == 'Advanced' ) ) ; +} + +// Get the selected flash embed (if available). +var oFakeImage = dialog.Selection.GetSelectedElement() ; +var oEmbed ; + +if ( oFakeImage ) +{ + if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckflash') ) + oEmbed = FCK.GetRealElement( oFakeImage ) ; + else + oFakeImage = null ; +} + +window.onload = function() +{ + // Translate the dialog box texts. + oEditor.FCKLanguageManager.TranslatePage(document) ; + + // Load the selected element information (if any). + LoadSelection() ; + + // Show/Hide the "Browse Server" button. + GetE('tdBrowse').style.display = FCKConfig.FlashBrowser ? '' : 'none' ; + + // Set the actual uploader URL. + if ( FCKConfig.FlashUpload ) + GetE('frmUpload').action = FCKConfig.FlashUploadURL ; + + dialog.SetAutoSize( true ) ; + + // Activate the "OK" button. + dialog.SetOkButton( true ) ; + + SelectField( 'txtUrl' ) ; +} + +function LoadSelection() +{ + if ( ! oEmbed ) return ; + + GetE('txtUrl').value = GetAttribute( oEmbed, 'src', '' ) ; + GetE('txtWidth').value = GetAttribute( oEmbed, 'width', '' ) ; + GetE('txtHeight').value = GetAttribute( oEmbed, 'height', '' ) ; + + // Get Advances Attributes + GetE('txtAttId').value = oEmbed.id ; + GetE('chkAutoPlay').checked = GetAttribute( oEmbed, 'play', 'true' ) == 'true' ; + GetE('chkLoop').checked = GetAttribute( oEmbed, 'loop', 'true' ) == 'true' ; + GetE('chkMenu').checked = GetAttribute( oEmbed, 'menu', 'true' ) == 'true' ; + GetE('cmbScale').value = GetAttribute( oEmbed, 'scale', '' ).toLowerCase() ; + + GetE('txtAttTitle').value = oEmbed.title ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + GetE('txtAttClasses').value = oEmbed.getAttribute('className') || '' ; + GetE('txtAttStyle').value = oEmbed.style.cssText ; + } + else + { + GetE('txtAttClasses').value = oEmbed.getAttribute('class',2) || '' ; + GetE('txtAttStyle').value = oEmbed.getAttribute('style',2) || '' ; + } + + UpdatePreview() ; +} + +//#### The OK button was hit. +function Ok() +{ + if ( GetE('txtUrl').value.length == 0 ) + { + dialog.SetSelectedTab( 'Info' ) ; + GetE('txtUrl').focus() ; + + alert( oEditor.FCKLang.DlgAlertUrl ) ; + + return false ; + } + + oEditor.FCKUndo.SaveUndoStep() ; + if ( !oEmbed ) + { + oEmbed = FCK.EditorDocument.createElement( 'EMBED' ) ; + oFakeImage = null ; + } + UpdateEmbed( oEmbed ) ; + + if ( !oFakeImage ) + { + oFakeImage = oEditor.FCKDocumentProcessor_CreateFakeImage( 'FCK__Flash', oEmbed ) ; + oFakeImage.setAttribute( '_fckflash', 'true', 0 ) ; + oFakeImage = FCK.InsertElement( oFakeImage ) ; + } + + oEditor.FCKEmbedAndObjectProcessor.RefreshView( oFakeImage, oEmbed ) ; + + return true ; +} + +function UpdateEmbed( e ) +{ + SetAttribute( e, 'type' , 'application/x-shockwave-flash' ) ; + SetAttribute( e, 'pluginspage' , 'http://www.macromedia.com/go/getflashplayer' ) ; + + SetAttribute( e, 'src', GetE('txtUrl').value ) ; + SetAttribute( e, "width" , GetE('txtWidth').value ) ; + SetAttribute( e, "height", GetE('txtHeight').value ) ; + + // Advances Attributes + + SetAttribute( e, 'id' , GetE('txtAttId').value ) ; + SetAttribute( e, 'scale', GetE('cmbScale').value ) ; + + SetAttribute( e, 'play', GetE('chkAutoPlay').checked ? 'true' : 'false' ) ; + SetAttribute( e, 'loop', GetE('chkLoop').checked ? 'true' : 'false' ) ; + SetAttribute( e, 'menu', GetE('chkMenu').checked ? 'true' : 'false' ) ; + + SetAttribute( e, 'title' , GetE('txtAttTitle').value ) ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + SetAttribute( e, 'className', GetE('txtAttClasses').value ) ; + e.style.cssText = GetE('txtAttStyle').value ; + } + else + { + SetAttribute( e, 'class', GetE('txtAttClasses').value ) ; + SetAttribute( e, 'style', GetE('txtAttStyle').value ) ; + } +} + +var ePreview ; + +function SetPreviewElement( previewEl ) +{ + ePreview = previewEl ; + + if ( GetE('txtUrl').value.length > 0 ) + UpdatePreview() ; +} + +function UpdatePreview() +{ + if ( !ePreview ) + return ; + + while ( ePreview.firstChild ) + ePreview.removeChild( ePreview.firstChild ) ; + + if ( GetE('txtUrl').value.length == 0 ) + ePreview.innerHTML = ' ' ; + else + { + var oDoc = ePreview.ownerDocument || ePreview.document ; + var e = oDoc.createElement( 'EMBED' ) ; + + SetAttribute( e, 'src', GetE('txtUrl').value ) ; + SetAttribute( e, 'type', 'application/x-shockwave-flash' ) ; + SetAttribute( e, 'width', '100%' ) ; + SetAttribute( e, 'height', '100%' ) ; + + ePreview.appendChild( e ) ; + } +} + +// + +function BrowseServer() +{ + OpenFileBrowser( FCKConfig.FlashBrowserURL, FCKConfig.FlashBrowserWindowWidth, FCKConfig.FlashBrowserWindowHeight ) ; +} + +function SetUrl( url, width, height ) +{ + GetE('txtUrl').value = url ; + + if ( width ) + GetE('txtWidth').value = width ; + + if ( height ) + GetE('txtHeight').value = height ; + + UpdatePreview() ; + + dialog.SetSelectedTab( 'Info' ) ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + // Remove animation + window.parent.Throbber.Hide() ; + GetE( 'divUpload' ).style.display = '' ; + + switch ( errorNumber ) + { + case 0 : // No errors + alert( 'Your file has been successfully uploaded' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + return ; + case 101 : // Custom warning + alert( customMsg ) ; + break ; + case 201 : + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file type' ) ; + return ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + return ; + case 500 : + alert( 'The connector is disabled' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + return ; + } + + SetUrl( fileUrl ) ; + GetE('frmUpload').reset() ; +} + +var oUploadAllowedExtRegex = new RegExp( FCKConfig.FlashUploadAllowedExtensions, 'i' ) ; +var oUploadDeniedExtRegex = new RegExp( FCKConfig.FlashUploadDeniedExtensions, 'i' ) ; + +function CheckUpload() +{ + var sFile = GetE('txtUploadFile').value ; + + if ( sFile.length == 0 ) + { + alert( 'Please select a file to upload' ) ; + return false ; + } + + if ( ( FCKConfig.FlashUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) || + ( FCKConfig.FlashUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) ) + { + OnUploadCompleted( 202 ) ; + return false ; + } + + // Show animation + window.parent.Throbber.Show( 100 ) ; + GetE( 'divUpload' ).style.display = 'none' ; + + return true ; +} diff --git a/www/js/FCKeditor/editor/dialog/fck_flash/fck_flash_preview.html b/www/js/FCKeditor/editor/dialog/fck_flash/fck_flash_preview.html new file mode 100644 index 0000000..a590521 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_flash/fck_flash_preview.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_form.html b/www/js/FCKeditor/editor/dialog/fck_form.html new file mode 100644 index 0000000..c724282 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_form.html @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ Name
+ +
+ Action
+ +
+ Method
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_hiddenfield.html b/www/js/FCKeditor/editor/dialog/fck_hiddenfield.html new file mode 100644 index 0000000..2d0e0b5 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_hiddenfield.html @@ -0,0 +1,115 @@ + + + + + Hidden Field Properties + + + + + + + + + + +
+ + + + + + + +
+ Name
+ +
+ Value
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_image.html b/www/js/FCKeditor/editor/dialog/fck_image.html new file mode 100644 index 0000000..75681bf --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_image.html @@ -0,0 +1,258 @@ + + + + + Image Properties + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + +
+ URL +
+ +
+
+ Short Description
+
+
+ + + + + + +
+
+ + + + + + + + + + + +
+ Width  + +
+
+
+
+
+
+ Height  +
+
+ + + + + + + + + + + + + + + + + +
+ Border  +
+ HSpace  +
+ VSpace  +
+ Align  + +
+
+     + + + + + + + +
+ Preview
+ +
+
+
+
+ + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_image/fck_image.js b/www/js/FCKeditor/editor/dialog/fck_image/fck_image.js new file mode 100644 index 0000000..a5cf73b --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_image/fck_image.js @@ -0,0 +1,512 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts related to the Image dialog window (see fck_image.html). + */ + +var dialog = window.parent ; +var oEditor = dialog.InnerDialogLoaded() ; +var FCK = oEditor.FCK ; +var FCKLang = oEditor.FCKLang ; +var FCKConfig = oEditor.FCKConfig ; +var FCKDebug = oEditor.FCKDebug ; +var FCKTools = oEditor.FCKTools ; + +var bImageButton = ( document.location.search.length > 0 && document.location.search.substr(1) == 'ImageButton' ) ; + +//#### Dialog Tabs + +// Set the dialog tabs. +dialog.AddTab( 'Info', FCKLang.DlgImgInfoTab ) ; + +if ( !bImageButton && !FCKConfig.ImageDlgHideLink ) + dialog.AddTab( 'Link', FCKLang.DlgImgLinkTab ) ; + +if ( FCKConfig.ImageUpload ) + dialog.AddTab( 'Upload', FCKLang.DlgLnkUpload ) ; + +if ( !FCKConfig.ImageDlgHideAdvanced ) + dialog.AddTab( 'Advanced', FCKLang.DlgAdvancedTag ) ; + +// Function called when a dialog tag is selected. +function OnDialogTabChange( tabCode ) +{ + ShowE('divInfo' , ( tabCode == 'Info' ) ) ; + ShowE('divLink' , ( tabCode == 'Link' ) ) ; + ShowE('divUpload' , ( tabCode == 'Upload' ) ) ; + ShowE('divAdvanced' , ( tabCode == 'Advanced' ) ) ; +} + +// Get the selected image (if available). +var oImage = dialog.Selection.GetSelectedElement() ; + +if ( oImage && oImage.tagName != 'IMG' && !( oImage.tagName == 'INPUT' && oImage.type == 'image' ) ) + oImage = null ; + +// Get the active link. +var oLink = dialog.Selection.GetSelection().MoveToAncestorNode( 'A' ) ; + +var oImageOriginal ; + +function UpdateOriginal( resetSize ) +{ + if ( !eImgPreview ) + return ; + + if ( GetE('txtUrl').value.length == 0 ) + { + oImageOriginal = null ; + return ; + } + + oImageOriginal = document.createElement( 'IMG' ) ; // new Image() ; + + if ( resetSize ) + { + oImageOriginal.onload = function() + { + this.onload = null ; + ResetSizes() ; + } + } + + oImageOriginal.src = eImgPreview.src ; +} + +var bPreviewInitialized ; + +window.onload = function() +{ + // Translate the dialog box texts. + oEditor.FCKLanguageManager.TranslatePage(document) ; + + GetE('btnLockSizes').title = FCKLang.DlgImgLockRatio ; + GetE('btnResetSize').title = FCKLang.DlgBtnResetSize ; + + // Load the selected element information (if any). + LoadSelection() ; + + // Show/Hide the "Browse Server" button. + GetE('tdBrowse').style.display = FCKConfig.ImageBrowser ? '' : 'none' ; + GetE('divLnkBrowseServer').style.display = FCKConfig.LinkBrowser ? '' : 'none' ; + + UpdateOriginal() ; + + // Set the actual uploader URL. + if ( FCKConfig.ImageUpload ) + GetE('frmUpload').action = FCKConfig.ImageUploadURL ; + + dialog.SetAutoSize( true ) ; + + // Activate the "OK" button. + dialog.SetOkButton( true ) ; + + SelectField( 'txtUrl' ) ; +} + +function LoadSelection() +{ + if ( ! oImage ) return ; + + var sUrl = oImage.getAttribute( '_fcksavedurl' ) ; + if ( sUrl == null ) + sUrl = GetAttribute( oImage, 'src', '' ) ; + + GetE('txtUrl').value = sUrl ; + GetE('txtAlt').value = GetAttribute( oImage, 'alt', '' ) ; + GetE('txtVSpace').value = GetAttribute( oImage, 'vspace', '' ) ; + GetE('txtHSpace').value = GetAttribute( oImage, 'hspace', '' ) ; + GetE('txtBorder').value = GetAttribute( oImage, 'border', '' ) ; + GetE('cmbAlign').value = GetAttribute( oImage, 'align', '' ) ; + + var iWidth, iHeight ; + + var regexSize = /^\s*(\d+)px\s*$/i ; + + if ( oImage.style.width ) + { + var aMatchW = oImage.style.width.match( regexSize ) ; + if ( aMatchW ) + { + iWidth = aMatchW[1] ; + oImage.style.width = '' ; + SetAttribute( oImage, 'width' , iWidth ) ; + } + } + + if ( oImage.style.height ) + { + var aMatchH = oImage.style.height.match( regexSize ) ; + if ( aMatchH ) + { + iHeight = aMatchH[1] ; + oImage.style.height = '' ; + SetAttribute( oImage, 'height', iHeight ) ; + } + } + + GetE('txtWidth').value = iWidth ? iWidth : GetAttribute( oImage, "width", '' ) ; + GetE('txtHeight').value = iHeight ? iHeight : GetAttribute( oImage, "height", '' ) ; + + // Get Advances Attributes + GetE('txtAttId').value = oImage.id ; + GetE('cmbAttLangDir').value = oImage.dir ; + GetE('txtAttLangCode').value = oImage.lang ; + GetE('txtAttTitle').value = oImage.title ; + GetE('txtLongDesc').value = oImage.longDesc ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + GetE('txtAttClasses').value = oImage.className || '' ; + GetE('txtAttStyle').value = oImage.style.cssText ; + } + else + { + GetE('txtAttClasses').value = oImage.getAttribute('class',2) || '' ; + GetE('txtAttStyle').value = oImage.getAttribute('style',2) ; + } + + if ( oLink ) + { + var sLinkUrl = oLink.getAttribute( '_fcksavedurl' ) ; + if ( sLinkUrl == null ) + sLinkUrl = oLink.getAttribute('href',2) ; + + GetE('txtLnkUrl').value = sLinkUrl ; + GetE('cmbLnkTarget').value = oLink.target ; + } + + UpdatePreview() ; +} + +//#### The OK button was hit. +function Ok() +{ + if ( GetE('txtUrl').value.length == 0 ) + { + dialog.SetSelectedTab( 'Info' ) ; + GetE('txtUrl').focus() ; + + alert( FCKLang.DlgImgAlertUrl ) ; + + return false ; + } + + var bHasImage = ( oImage != null ) ; + + if ( bHasImage && bImageButton && oImage.tagName == 'IMG' ) + { + if ( confirm( 'Do you want to transform the selected image on a image button?' ) ) + oImage = null ; + } + else if ( bHasImage && !bImageButton && oImage.tagName == 'INPUT' ) + { + if ( confirm( 'Do you want to transform the selected image button on a simple image?' ) ) + oImage = null ; + } + + oEditor.FCKUndo.SaveUndoStep() ; + if ( !bHasImage ) + { + if ( bImageButton ) + { + oImage = FCK.EditorDocument.createElement( 'input' ) ; + oImage.type = 'image' ; + oImage = FCK.InsertElement( oImage ) ; + } + else + oImage = FCK.InsertElement( 'img' ) ; + } + + UpdateImage( oImage ) ; + + var sLnkUrl = GetE('txtLnkUrl').value.Trim() ; + + if ( sLnkUrl.length == 0 ) + { + if ( oLink ) + FCK.ExecuteNamedCommand( 'Unlink' ) ; + } + else + { + if ( oLink ) // Modifying an existent link. + oLink.href = sLnkUrl ; + else // Creating a new link. + { + if ( !bHasImage ) + oEditor.FCKSelection.SelectNode( oImage ) ; + + oLink = oEditor.FCK.CreateLink( sLnkUrl )[0] ; + + if ( !bHasImage ) + { + oEditor.FCKSelection.SelectNode( oLink ) ; + oEditor.FCKSelection.Collapse( false ) ; + } + } + + SetAttribute( oLink, '_fcksavedurl', sLnkUrl ) ; + SetAttribute( oLink, 'target', GetE('cmbLnkTarget').value ) ; + } + + return true ; +} + +function UpdateImage( e, skipId ) +{ + e.src = GetE('txtUrl').value ; + SetAttribute( e, "_fcksavedurl", GetE('txtUrl').value ) ; + SetAttribute( e, "alt" , GetE('txtAlt').value ) ; + SetAttribute( e, "width" , GetE('txtWidth').value ) ; + SetAttribute( e, "height", GetE('txtHeight').value ) ; + SetAttribute( e, "vspace", GetE('txtVSpace').value ) ; + SetAttribute( e, "hspace", GetE('txtHSpace').value ) ; + SetAttribute( e, "border", GetE('txtBorder').value ) ; + SetAttribute( e, "align" , GetE('cmbAlign').value ) ; + + // Advances Attributes + + if ( ! skipId ) + SetAttribute( e, 'id', GetE('txtAttId').value ) ; + + SetAttribute( e, 'dir' , GetE('cmbAttLangDir').value ) ; + SetAttribute( e, 'lang' , GetE('txtAttLangCode').value ) ; + SetAttribute( e, 'title' , GetE('txtAttTitle').value ) ; + SetAttribute( e, 'longDesc' , GetE('txtLongDesc').value ) ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + e.className = GetE('txtAttClasses').value ; + e.style.cssText = GetE('txtAttStyle').value ; + } + else + { + SetAttribute( e, 'class' , GetE('txtAttClasses').value ) ; + SetAttribute( e, 'style', GetE('txtAttStyle').value ) ; + } +} + +var eImgPreview ; +var eImgPreviewLink ; + +function SetPreviewElements( imageElement, linkElement ) +{ + eImgPreview = imageElement ; + eImgPreviewLink = linkElement ; + + UpdatePreview() ; + UpdateOriginal() ; + + bPreviewInitialized = true ; +} + +function UpdatePreview() +{ + if ( !eImgPreview || !eImgPreviewLink ) + return ; + + if ( GetE('txtUrl').value.length == 0 ) + eImgPreviewLink.style.display = 'none' ; + else + { + UpdateImage( eImgPreview, true ) ; + + if ( GetE('txtLnkUrl').value.Trim().length > 0 ) + eImgPreviewLink.href = 'javascript:void(null);' ; + else + SetAttribute( eImgPreviewLink, 'href', '' ) ; + + eImgPreviewLink.style.display = '' ; + } +} + +var bLockRatio = true ; + +function SwitchLock( lockButton ) +{ + bLockRatio = !bLockRatio ; + lockButton.className = bLockRatio ? 'BtnLocked' : 'BtnUnlocked' ; + lockButton.title = bLockRatio ? 'Lock sizes' : 'Unlock sizes' ; + + if ( bLockRatio ) + { + if ( GetE('txtWidth').value.length > 0 ) + OnSizeChanged( 'Width', GetE('txtWidth').value ) ; + else + OnSizeChanged( 'Height', GetE('txtHeight').value ) ; + } +} + +// Fired when the width or height input texts change +function OnSizeChanged( dimension, value ) +{ + // Verifies if the aspect ration has to be maintained + if ( oImageOriginal && bLockRatio ) + { + var e = dimension == 'Width' ? GetE('txtHeight') : GetE('txtWidth') ; + + if ( value.length == 0 || isNaN( value ) ) + { + e.value = '' ; + return ; + } + + if ( dimension == 'Width' ) + value = value == 0 ? 0 : Math.round( oImageOriginal.height * ( value / oImageOriginal.width ) ) ; + else + value = value == 0 ? 0 : Math.round( oImageOriginal.width * ( value / oImageOriginal.height ) ) ; + + if ( !isNaN( value ) ) + e.value = value ; + } + + UpdatePreview() ; +} + +// Fired when the Reset Size button is clicked +function ResetSizes() +{ + if ( ! oImageOriginal ) return ; + if ( oEditor.FCKBrowserInfo.IsGecko && !oImageOriginal.complete ) + { + setTimeout( ResetSizes, 50 ) ; + return ; + } + + GetE('txtWidth').value = oImageOriginal.width ; + GetE('txtHeight').value = oImageOriginal.height ; + + UpdatePreview() ; +} + +function BrowseServer() +{ + OpenServerBrowser( + 'Image', + FCKConfig.ImageBrowserURL, + FCKConfig.ImageBrowserWindowWidth, + FCKConfig.ImageBrowserWindowHeight ) ; +} + +function LnkBrowseServer() +{ + OpenServerBrowser( + 'Link', + FCKConfig.LinkBrowserURL, + FCKConfig.LinkBrowserWindowWidth, + FCKConfig.LinkBrowserWindowHeight ) ; +} + +function OpenServerBrowser( type, url, width, height ) +{ + sActualBrowser = type ; + OpenFileBrowser( url, width, height ) ; +} + +var sActualBrowser ; + +function SetUrl( url, width, height, alt ) +{ + if ( sActualBrowser == 'Link' ) + { + GetE('txtLnkUrl').value = url ; + UpdatePreview() ; + } + else + { + GetE('txtUrl').value = url ; + GetE('txtWidth').value = width ? width : '' ; + GetE('txtHeight').value = height ? height : '' ; + + if ( alt ) + GetE('txtAlt').value = alt; + + UpdatePreview() ; + UpdateOriginal( true ) ; + } + + dialog.SetSelectedTab( 'Info' ) ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + // Remove animation + window.parent.Throbber.Hide() ; + GetE( 'divUpload' ).style.display = '' ; + + switch ( errorNumber ) + { + case 0 : // No errors + alert( 'Your file has been successfully uploaded' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + return ; + case 101 : // Custom warning + alert( customMsg ) ; + break ; + case 201 : + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file type' ) ; + return ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + return ; + case 500 : + alert( 'The connector is disabled' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + return ; + } + + sActualBrowser = '' ; + SetUrl( fileUrl ) ; + GetE('frmUpload').reset() ; +} + +var oUploadAllowedExtRegex = new RegExp( FCKConfig.ImageUploadAllowedExtensions, 'i' ) ; +var oUploadDeniedExtRegex = new RegExp( FCKConfig.ImageUploadDeniedExtensions, 'i' ) ; + +function CheckUpload() +{ + var sFile = GetE('txtUploadFile').value ; + + if ( sFile.length == 0 ) + { + alert( 'Please select a file to upload' ) ; + return false ; + } + + if ( ( FCKConfig.ImageUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) || + ( FCKConfig.ImageUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) ) + { + OnUploadCompleted( 202 ) ; + return false ; + } + + // Show animation + window.parent.Throbber.Show( 100 ) ; + GetE( 'divUpload' ).style.display = 'none' ; + + return true ; +} diff --git a/www/js/FCKeditor/editor/dialog/fck_image/fck_image_preview.html b/www/js/FCKeditor/editor/dialog/fck_image/fck_image_preview.html new file mode 100644 index 0000000..1c6fe52 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_image/fck_image_preview.html @@ -0,0 +1,72 @@ + + + + + + + + + + + +
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_link.html b/www/js/FCKeditor/editor/dialog/fck_link.html new file mode 100644 index 0000000..061c84e --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_link.html @@ -0,0 +1,295 @@ + + + + + Link Properties + + + + + + + + + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_link/fck_link.js b/www/js/FCKeditor/editor/dialog/fck_link/fck_link.js new file mode 100644 index 0000000..1c661eb --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_link/fck_link.js @@ -0,0 +1,893 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts related to the Link dialog window (see fck_link.html). + */ + +var dialog = window.parent ; +var oEditor = dialog.InnerDialogLoaded() ; + +var FCK = oEditor.FCK ; +var FCKLang = oEditor.FCKLang ; +var FCKConfig = oEditor.FCKConfig ; +var FCKRegexLib = oEditor.FCKRegexLib ; +var FCKTools = oEditor.FCKTools ; + +//#### Dialog Tabs + +// Set the dialog tabs. +dialog.AddTab( 'Info', FCKLang.DlgLnkInfoTab ) ; + +if ( !FCKConfig.LinkDlgHideTarget ) + dialog.AddTab( 'Target', FCKLang.DlgLnkTargetTab, true ) ; + +if ( FCKConfig.LinkUpload ) + dialog.AddTab( 'Upload', FCKLang.DlgLnkUpload, true ) ; + +if ( !FCKConfig.LinkDlgHideAdvanced ) + dialog.AddTab( 'Advanced', FCKLang.DlgAdvancedTag ) ; + +// Function called when a dialog tag is selected. +function OnDialogTabChange( tabCode ) +{ + ShowE('divInfo' , ( tabCode == 'Info' ) ) ; + ShowE('divTarget' , ( tabCode == 'Target' ) ) ; + ShowE('divUpload' , ( tabCode == 'Upload' ) ) ; + ShowE('divAttribs' , ( tabCode == 'Advanced' ) ) ; + + dialog.SetAutoSize( true ) ; +} + +//#### Regular Expressions library. +var oRegex = new Object() ; + +oRegex.UriProtocol = /^(((http|https|ftp|news):\/\/)|mailto:)/gi ; + +oRegex.UrlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/gi ; + +oRegex.UrlOnChangeTestOther = /^((javascript:)|[#\/\.])/gi ; + +oRegex.ReserveTarget = /^_(blank|self|top|parent)$/i ; + +oRegex.PopupUri = /^javascript:void\(\s*window.open\(\s*'([^']+)'\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*\)\s*$/ ; + +// Accessible popups +oRegex.OnClickPopup = /^\s*on[cC]lick="\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*"$/ ; + +oRegex.PopupFeatures = /(?:^|,)([^=]+)=(\d+|yes|no)/gi ; + +//#### Parser Functions + +var oParser = new Object() ; + +// This method simply returns the two inputs in numerical order. You can even +// provide strings, as the method would parseInt() the values. +oParser.SortNumerical = function(a, b) +{ + return parseInt( a, 10 ) - parseInt( b, 10 ) ; +} + +oParser.ParseEMailParams = function(sParams) +{ + // Initialize the oEMailParams object. + var oEMailParams = new Object() ; + oEMailParams.Subject = '' ; + oEMailParams.Body = '' ; + + var aMatch = sParams.match( /(^|^\?|&)subject=([^&]+)/i ) ; + if ( aMatch ) oEMailParams.Subject = decodeURIComponent( aMatch[2] ) ; + + aMatch = sParams.match( /(^|^\?|&)body=([^&]+)/i ) ; + if ( aMatch ) oEMailParams.Body = decodeURIComponent( aMatch[2] ) ; + + return oEMailParams ; +} + +// This method returns either an object containing the email info, or FALSE +// if the parameter is not an email link. +oParser.ParseEMailUri = function( sUrl ) +{ + // Initializes the EMailInfo object. + var oEMailInfo = new Object() ; + oEMailInfo.Address = '' ; + oEMailInfo.Subject = '' ; + oEMailInfo.Body = '' ; + + var aLinkInfo = sUrl.match( /^(\w+):(.*)$/ ) ; + if ( aLinkInfo && aLinkInfo[1] == 'mailto' ) + { + // This seems to be an unprotected email link. + var aParts = aLinkInfo[2].match( /^([^\?]+)\??(.+)?/ ) ; + if ( aParts ) + { + // Set the e-mail address. + oEMailInfo.Address = aParts[1] ; + + // Look for the optional e-mail parameters. + if ( aParts[2] ) + { + var oEMailParams = oParser.ParseEMailParams( aParts[2] ) ; + oEMailInfo.Subject = oEMailParams.Subject ; + oEMailInfo.Body = oEMailParams.Body ; + } + } + return oEMailInfo ; + } + else if ( aLinkInfo && aLinkInfo[1] == 'javascript' ) + { + // This may be a protected email. + + // Try to match the url against the EMailProtectionFunction. + var func = FCKConfig.EMailProtectionFunction ; + if ( func != null ) + { + try + { + // Escape special chars. + func = func.replace( /([\/^$*+.?()\[\]])/g, '\\$1' ) ; + + // Define the possible keys. + var keys = new Array('NAME', 'DOMAIN', 'SUBJECT', 'BODY') ; + + // Get the order of the keys (hold them in the array ) and + // the function replaced by regular expression patterns. + var sFunc = func ; + var pos = new Array() ; + for ( var i = 0 ; i < keys.length ; i ++ ) + { + var rexp = new RegExp( keys[i] ) ; + var p = func.search( rexp ) ; + if ( p >= 0 ) + { + sFunc = sFunc.replace( rexp, '\'([^\']*)\'' ) ; + pos[pos.length] = p + ':' + keys[i] ; + } + } + + // Sort the available keys. + pos.sort( oParser.SortNumerical ) ; + + // Replace the excaped single quotes in the url, such they do + // not affect the regexp afterwards. + aLinkInfo[2] = aLinkInfo[2].replace( /\\'/g, '###SINGLE_QUOTE###' ) ; + + // Create the regexp and execute it. + var rFunc = new RegExp( '^' + sFunc + '$' ) ; + var aMatch = rFunc.exec( aLinkInfo[2] ) ; + if ( aMatch ) + { + var aInfo = new Array(); + for ( var i = 1 ; i < aMatch.length ; i ++ ) + { + var k = pos[i-1].match(/^\d+:(.+)$/) ; + aInfo[k[1]] = aMatch[i].replace(/###SINGLE_QUOTE###/g, '\'') ; + } + + // Fill the EMailInfo object that will be returned + oEMailInfo.Address = aInfo['NAME'] + '@' + aInfo['DOMAIN'] ; + oEMailInfo.Subject = decodeURIComponent( aInfo['SUBJECT'] ) ; + oEMailInfo.Body = decodeURIComponent( aInfo['BODY'] ) ; + + return oEMailInfo ; + } + } + catch (e) + { + } + } + + // Try to match the email against the encode protection. + var aMatch = aLinkInfo[2].match( /^(?:void\()?location\.href='mailto:'\+(String\.fromCharCode\([\d,]+\))\+'(.*)'\)?$/ ) ; + if ( aMatch ) + { + // The link is encoded + oEMailInfo.Address = eval( aMatch[1] ) ; + if ( aMatch[2] ) + { + var oEMailParams = oParser.ParseEMailParams( aMatch[2] ) ; + oEMailInfo.Subject = oEMailParams.Subject ; + oEMailInfo.Body = oEMailParams.Body ; + } + return oEMailInfo ; + } + } + return false; +} + +oParser.CreateEMailUri = function( address, subject, body ) +{ + // Switch for the EMailProtection setting. + switch ( FCKConfig.EMailProtection ) + { + case 'function' : + var func = FCKConfig.EMailProtectionFunction ; + if ( func == null ) + { + if ( FCKConfig.Debug ) + { + alert('EMailProtection alert!\nNo function defined. Please set "FCKConfig.EMailProtectionFunction"') ; + } + return ''; + } + + // Split the email address into name and domain parts. + var aAddressParts = address.split( '@', 2 ) ; + if ( aAddressParts[1] == undefined ) + { + aAddressParts[1] = '' ; + } + + // Replace the keys by their values (embedded in single quotes). + func = func.replace(/NAME/g, "'" + aAddressParts[0].replace(/'/g, '\\\'') + "'") ; + func = func.replace(/DOMAIN/g, "'" + aAddressParts[1].replace(/'/g, '\\\'') + "'") ; + func = func.replace(/SUBJECT/g, "'" + encodeURIComponent( subject ).replace(/'/g, '\\\'') + "'") ; + func = func.replace(/BODY/g, "'" + encodeURIComponent( body ).replace(/'/g, '\\\'') + "'") ; + + return 'javascript:' + func ; + + case 'encode' : + var aParams = [] ; + var aAddressCode = [] ; + + if ( subject.length > 0 ) + aParams.push( 'subject='+ encodeURIComponent( subject ) ) ; + if ( body.length > 0 ) + aParams.push( 'body=' + encodeURIComponent( body ) ) ; + for ( var i = 0 ; i < address.length ; i++ ) + aAddressCode.push( address.charCodeAt( i ) ) ; + + return 'javascript:void(location.href=\'mailto:\'+String.fromCharCode(' + aAddressCode.join( ',' ) + ')+\'?' + aParams.join( '&' ) + '\')' ; + } + + // EMailProtection 'none' + + var sBaseUri = 'mailto:' + address ; + + var sParams = '' ; + + if ( subject.length > 0 ) + sParams = '?subject=' + encodeURIComponent( subject ) ; + + if ( body.length > 0 ) + { + sParams += ( sParams.length == 0 ? '?' : '&' ) ; + sParams += 'body=' + encodeURIComponent( body ) ; + } + + return sBaseUri + sParams ; +} + +//#### Initialization Code + +// oLink: The actual selected link in the editor. +var oLink = dialog.Selection.GetSelection().MoveToAncestorNode( 'A' ) ; +if ( oLink ) + FCK.Selection.SelectNode( oLink ) ; + +window.onload = function() +{ + // Translate the dialog box texts. + oEditor.FCKLanguageManager.TranslatePage(document) ; + + // Fill the Anchor Names and Ids combos. + LoadAnchorNamesAndIds() ; + + // Load the selected link information (if any). + LoadSelection() ; + + // Update the dialog box. + SetLinkType( GetE('cmbLinkType').value ) ; + + // Show/Hide the "Browse Server" button. + GetE('divBrowseServer').style.display = FCKConfig.LinkBrowser ? '' : 'none' ; + + // Show the initial dialog content. + GetE('divInfo').style.display = '' ; + + // Set the actual uploader URL. + if ( FCKConfig.LinkUpload ) + GetE('frmUpload').action = FCKConfig.LinkUploadURL ; + + // Set the default target (from configuration). + SetDefaultTarget() ; + + // Activate the "OK" button. + dialog.SetOkButton( true ) ; + + // Select the first field. + switch( GetE('cmbLinkType').value ) + { + case 'url' : + SelectField( 'txtUrl' ) ; + break ; + case 'email' : + SelectField( 'txtEMailAddress' ) ; + break ; + case 'anchor' : + if ( GetE('divSelAnchor').style.display != 'none' ) + SelectField( 'cmbAnchorName' ) ; + else + SelectField( 'cmbLinkType' ) ; + } +} + +var bHasAnchors ; + +function LoadAnchorNamesAndIds() +{ + // Since version 2.0, the anchors are replaced in the DOM by IMGs so the user see the icon + // to edit them. So, we must look for that images now. + var aAnchors = new Array() ; + var i ; + var oImages = oEditor.FCK.EditorDocument.getElementsByTagName( 'IMG' ) ; + for( i = 0 ; i < oImages.length ; i++ ) + { + if ( oImages[i].getAttribute('_fckanchor') ) + aAnchors[ aAnchors.length ] = oEditor.FCK.GetRealElement( oImages[i] ) ; + } + + // Add also real anchors + var oLinks = oEditor.FCK.EditorDocument.getElementsByTagName( 'A' ) ; + for( i = 0 ; i < oLinks.length ; i++ ) + { + if ( oLinks[i].name && ( oLinks[i].name.length > 0 ) ) + aAnchors[ aAnchors.length ] = oLinks[i] ; + } + + var aIds = FCKTools.GetAllChildrenIds( oEditor.FCK.EditorDocument.body ) ; + + bHasAnchors = ( aAnchors.length > 0 || aIds.length > 0 ) ; + + for ( i = 0 ; i < aAnchors.length ; i++ ) + { + var sName = aAnchors[i].name ; + if ( sName && sName.length > 0 ) + FCKTools.AddSelectOption( GetE('cmbAnchorName'), sName, sName ) ; + } + + for ( i = 0 ; i < aIds.length ; i++ ) + { + FCKTools.AddSelectOption( GetE('cmbAnchorId'), aIds[i], aIds[i] ) ; + } + + ShowE( 'divSelAnchor' , bHasAnchors ) ; + ShowE( 'divNoAnchor' , !bHasAnchors ) ; +} + +function LoadSelection() +{ + if ( !oLink ) return ; + + var sType = 'url' ; + + // Get the actual Link href. + var sHRef = oLink.getAttribute( '_fcksavedurl' ) ; + if ( sHRef == null ) + sHRef = oLink.getAttribute( 'href' , 2 ) || '' ; + + // Look for a popup javascript link. + var oPopupMatch = oRegex.PopupUri.exec( sHRef ) ; + if( oPopupMatch ) + { + GetE('cmbTarget').value = 'popup' ; + sHRef = oPopupMatch[1] ; + FillPopupFields( oPopupMatch[2], oPopupMatch[3] ) ; + SetTarget( 'popup' ) ; + } + + // Accessible popups, the popup data is in the onclick attribute + if ( !oPopupMatch ) + { + var onclick = oLink.getAttribute( 'onclick_fckprotectedatt' ) ; + if ( onclick ) + { + // Decode the protected string + onclick = decodeURIComponent( onclick ) ; + + oPopupMatch = oRegex.OnClickPopup.exec( onclick ) ; + if( oPopupMatch ) + { + GetE( 'cmbTarget' ).value = 'popup' ; + FillPopupFields( oPopupMatch[1], oPopupMatch[2] ) ; + SetTarget( 'popup' ) ; + } + } + } + + // Search for the protocol. + var sProtocol = oRegex.UriProtocol.exec( sHRef ) ; + + // Search for a protected email link. + var oEMailInfo = oParser.ParseEMailUri( sHRef ); + + if ( oEMailInfo ) + { + sType = 'email' ; + + GetE('txtEMailAddress').value = oEMailInfo.Address ; + GetE('txtEMailSubject').value = oEMailInfo.Subject ; + GetE('txtEMailBody').value = oEMailInfo.Body ; + } + else if ( sProtocol ) + { + sProtocol = sProtocol[0].toLowerCase() ; + GetE('cmbLinkProtocol').value = sProtocol ; + + // Remove the protocol and get the remaining URL. + var sUrl = sHRef.replace( oRegex.UriProtocol, '' ) ; + sType = 'url' ; + GetE('txtUrl').value = sUrl ; + } + else if ( sHRef.substr(0,1) == '#' && sHRef.length > 1 ) // It is an anchor link. + { + sType = 'anchor' ; + GetE('cmbAnchorName').value = GetE('cmbAnchorId').value = sHRef.substr(1) ; + } + else // It is another type of link. + { + sType = 'url' ; + + GetE('cmbLinkProtocol').value = '' ; + GetE('txtUrl').value = sHRef ; + } + + if ( !oPopupMatch ) + { + // Get the target. + var sTarget = oLink.target ; + + if ( sTarget && sTarget.length > 0 ) + { + if ( oRegex.ReserveTarget.test( sTarget ) ) + { + sTarget = sTarget.toLowerCase() ; + GetE('cmbTarget').value = sTarget ; + } + else + GetE('cmbTarget').value = 'frame' ; + GetE('txtTargetFrame').value = sTarget ; + } + } + + // Get Advances Attributes + GetE('txtAttId').value = oLink.id ; + GetE('txtAttName').value = oLink.name ; + GetE('cmbAttLangDir').value = oLink.dir ; + GetE('txtAttLangCode').value = oLink.lang ; + GetE('txtAttAccessKey').value = oLink.accessKey ; + GetE('txtAttTabIndex').value = oLink.tabIndex <= 0 ? '' : oLink.tabIndex ; + GetE('txtAttTitle').value = oLink.title ; + GetE('txtAttContentType').value = oLink.type ; + GetE('txtAttCharSet').value = oLink.charset ; + + var sClass ; + if ( oEditor.FCKBrowserInfo.IsIE ) + { + sClass = oLink.getAttribute('className',2) || '' ; + // Clean up temporary classes for internal use: + sClass = sClass.replace( FCKRegexLib.FCK_Class, '' ) ; + + GetE('txtAttStyle').value = oLink.style.cssText ; + } + else + { + sClass = oLink.getAttribute('class',2) || '' ; + GetE('txtAttStyle').value = oLink.getAttribute('style',2) || '' ; + } + GetE('txtAttClasses').value = sClass ; + + // Update the Link type combo. + GetE('cmbLinkType').value = sType ; +} + +//#### Link type selection. +function SetLinkType( linkType ) +{ + ShowE('divLinkTypeUrl' , (linkType == 'url') ) ; + ShowE('divLinkTypeAnchor' , (linkType == 'anchor') ) ; + ShowE('divLinkTypeEMail' , (linkType == 'email') ) ; + + if ( !FCKConfig.LinkDlgHideTarget ) + dialog.SetTabVisibility( 'Target' , (linkType == 'url') ) ; + + if ( FCKConfig.LinkUpload ) + dialog.SetTabVisibility( 'Upload' , (linkType == 'url') ) ; + + if ( !FCKConfig.LinkDlgHideAdvanced ) + dialog.SetTabVisibility( 'Advanced' , (linkType != 'anchor' || bHasAnchors) ) ; + + if ( linkType == 'email' ) + dialog.SetAutoSize( true ) ; +} + +//#### Target type selection. +function SetTarget( targetType ) +{ + GetE('tdTargetFrame').style.display = ( targetType == 'popup' ? 'none' : '' ) ; + GetE('tdPopupName').style.display = + GetE('tablePopupFeatures').style.display = ( targetType == 'popup' ? '' : 'none' ) ; + + switch ( targetType ) + { + case "_blank" : + case "_self" : + case "_parent" : + case "_top" : + GetE('txtTargetFrame').value = targetType ; + break ; + case "" : + GetE('txtTargetFrame').value = '' ; + break ; + } + + if ( targetType == 'popup' ) + dialog.SetAutoSize( true ) ; +} + +//#### Called while the user types the URL. +function OnUrlChange() +{ + var sUrl = GetE('txtUrl').value ; + var sProtocol = oRegex.UrlOnChangeProtocol.exec( sUrl ) ; + + if ( sProtocol ) + { + sUrl = sUrl.substr( sProtocol[0].length ) ; + GetE('txtUrl').value = sUrl ; + GetE('cmbLinkProtocol').value = sProtocol[0].toLowerCase() ; + } + else if ( oRegex.UrlOnChangeTestOther.test( sUrl ) ) + { + GetE('cmbLinkProtocol').value = '' ; + } +} + +//#### Called while the user types the target name. +function OnTargetNameChange() +{ + var sFrame = GetE('txtTargetFrame').value ; + + if ( sFrame.length == 0 ) + GetE('cmbTarget').value = '' ; + else if ( oRegex.ReserveTarget.test( sFrame ) ) + GetE('cmbTarget').value = sFrame.toLowerCase() ; + else + GetE('cmbTarget').value = 'frame' ; +} + +// Accessible popups +function BuildOnClickPopup() +{ + var sWindowName = "'" + GetE('txtPopupName').value.replace(/\W/gi, "") + "'" ; + + var sFeatures = '' ; + var aChkFeatures = document.getElementsByName( 'chkFeature' ) ; + for ( var i = 0 ; i < aChkFeatures.length ; i++ ) + { + if ( i > 0 ) sFeatures += ',' ; + sFeatures += aChkFeatures[i].value + '=' + ( aChkFeatures[i].checked ? 'yes' : 'no' ) ; + } + + if ( GetE('txtPopupWidth').value.length > 0 ) sFeatures += ',width=' + GetE('txtPopupWidth').value ; + if ( GetE('txtPopupHeight').value.length > 0 ) sFeatures += ',height=' + GetE('txtPopupHeight').value ; + if ( GetE('txtPopupLeft').value.length > 0 ) sFeatures += ',left=' + GetE('txtPopupLeft').value ; + if ( GetE('txtPopupTop').value.length > 0 ) sFeatures += ',top=' + GetE('txtPopupTop').value ; + + if ( sFeatures != '' ) + sFeatures = sFeatures + ",status" ; + + return ( "window.open(this.href," + sWindowName + ",'" + sFeatures + "'); return false" ) ; +} + +//#### Fills all Popup related fields. +function FillPopupFields( windowName, features ) +{ + if ( windowName ) + GetE('txtPopupName').value = windowName ; + + var oFeatures = new Object() ; + var oFeaturesMatch ; + while( ( oFeaturesMatch = oRegex.PopupFeatures.exec( features ) ) != null ) + { + var sValue = oFeaturesMatch[2] ; + if ( sValue == ( 'yes' || '1' ) ) + oFeatures[ oFeaturesMatch[1] ] = true ; + else if ( ! isNaN( sValue ) && sValue != 0 ) + oFeatures[ oFeaturesMatch[1] ] = sValue ; + } + + // Update all features check boxes. + var aChkFeatures = document.getElementsByName('chkFeature') ; + for ( var i = 0 ; i < aChkFeatures.length ; i++ ) + { + if ( oFeatures[ aChkFeatures[i].value ] ) + aChkFeatures[i].checked = true ; + } + + // Update position and size text boxes. + if ( oFeatures['width'] ) GetE('txtPopupWidth').value = oFeatures['width'] ; + if ( oFeatures['height'] ) GetE('txtPopupHeight').value = oFeatures['height'] ; + if ( oFeatures['left'] ) GetE('txtPopupLeft').value = oFeatures['left'] ; + if ( oFeatures['top'] ) GetE('txtPopupTop').value = oFeatures['top'] ; +} + +//#### The OK button was hit. +function Ok() +{ + var sUri, sInnerHtml ; + oEditor.FCKUndo.SaveUndoStep() ; + + switch ( GetE('cmbLinkType').value ) + { + case 'url' : + sUri = GetE('txtUrl').value ; + + if ( sUri.length == 0 ) + { + alert( FCKLang.DlnLnkMsgNoUrl ) ; + return false ; + } + + sUri = GetE('cmbLinkProtocol').value + sUri ; + + break ; + + case 'email' : + sUri = GetE('txtEMailAddress').value ; + + if ( sUri.length == 0 ) + { + alert( FCKLang.DlnLnkMsgNoEMail ) ; + return false ; + } + + sUri = oParser.CreateEMailUri( + sUri, + GetE('txtEMailSubject').value, + GetE('txtEMailBody').value ) ; + break ; + + case 'anchor' : + var sAnchor = GetE('cmbAnchorName').value ; + if ( sAnchor.length == 0 ) sAnchor = GetE('cmbAnchorId').value ; + + if ( sAnchor.length == 0 ) + { + alert( FCKLang.DlnLnkMsgNoAnchor ) ; + return false ; + } + + sUri = '#' + sAnchor ; + break ; + } + + // If no link is selected, create a new one (it may result in more than one link creation - #220). + var aLinks = oLink ? [ oLink ] : oEditor.FCK.CreateLink( sUri, true ) ; + + // If no selection, no links are created, so use the uri as the link text (by dom, 2006-05-26) + var aHasSelection = ( aLinks.length > 0 ) ; + if ( !aHasSelection ) + { + sInnerHtml = sUri; + + // Built a better text for empty links. + switch ( GetE('cmbLinkType').value ) + { + // anchor: use old behavior --> return true + case 'anchor': + sInnerHtml = sInnerHtml.replace( /^#/, '' ) ; + break ; + + // url: try to get path + case 'url': + var oLinkPathRegEx = new RegExp("//?([^?\"']+)([?].*)?$") ; + var asLinkPath = oLinkPathRegEx.exec( sUri ) ; + if (asLinkPath != null) + sInnerHtml = asLinkPath[1]; // use matched path + break ; + + // mailto: try to get email address + case 'email': + sInnerHtml = GetE('txtEMailAddress').value ; + break ; + } + + // Create a new (empty) anchor. + aLinks = [ oEditor.FCK.InsertElement( 'a' ) ] ; + } + + for ( var i = 0 ; i < aLinks.length ; i++ ) + { + oLink = aLinks[i] ; + + if ( aHasSelection ) + sInnerHtml = oLink.innerHTML ; // Save the innerHTML (IE changes it if it is like an URL). + + oLink.href = sUri ; + SetAttribute( oLink, '_fcksavedurl', sUri ) ; + + var onclick; + // Accessible popups + if( GetE('cmbTarget').value == 'popup' ) + { + onclick = BuildOnClickPopup() ; + // Encode the attribute + onclick = encodeURIComponent( " onclick=\"" + onclick + "\"" ) ; + SetAttribute( oLink, 'onclick_fckprotectedatt', onclick ) ; + } + else + { + // Check if the previous onclick was for a popup: + // In that case remove the onclick handler. + onclick = oLink.getAttribute( 'onclick_fckprotectedatt' ) ; + if ( onclick ) + { + // Decode the protected string + onclick = decodeURIComponent( onclick ) ; + + if( oRegex.OnClickPopup.test( onclick ) ) + SetAttribute( oLink, 'onclick_fckprotectedatt', '' ) ; + } + } + + oLink.innerHTML = sInnerHtml ; // Set (or restore) the innerHTML + + // Target + if( GetE('cmbTarget').value != 'popup' ) + SetAttribute( oLink, 'target', GetE('txtTargetFrame').value ) ; + else + SetAttribute( oLink, 'target', null ) ; + + // Let's set the "id" only for the first link to avoid duplication. + if ( i == 0 ) + SetAttribute( oLink, 'id', GetE('txtAttId').value ) ; + + // Advances Attributes + SetAttribute( oLink, 'name' , GetE('txtAttName').value ) ; + SetAttribute( oLink, 'dir' , GetE('cmbAttLangDir').value ) ; + SetAttribute( oLink, 'lang' , GetE('txtAttLangCode').value ) ; + SetAttribute( oLink, 'accesskey', GetE('txtAttAccessKey').value ) ; + SetAttribute( oLink, 'tabindex' , ( GetE('txtAttTabIndex').value > 0 ? GetE('txtAttTabIndex').value : null ) ) ; + SetAttribute( oLink, 'title' , GetE('txtAttTitle').value ) ; + SetAttribute( oLink, 'type' , GetE('txtAttContentType').value ) ; + SetAttribute( oLink, 'charset' , GetE('txtAttCharSet').value ) ; + + if ( oEditor.FCKBrowserInfo.IsIE ) + { + var sClass = GetE('txtAttClasses').value ; + // If it's also an anchor add an internal class + if ( GetE('txtAttName').value.length != 0 ) + sClass += ' FCK__AnchorC' ; + SetAttribute( oLink, 'className', sClass ) ; + + oLink.style.cssText = GetE('txtAttStyle').value ; + } + else + { + SetAttribute( oLink, 'class', GetE('txtAttClasses').value ) ; + SetAttribute( oLink, 'style', GetE('txtAttStyle').value ) ; + } + } + + // Select the (first) link. + oEditor.FCKSelection.SelectNode( aLinks[0] ); + + return true ; +} + +function BrowseServer() +{ + OpenFileBrowser( FCKConfig.LinkBrowserURL, FCKConfig.LinkBrowserWindowWidth, FCKConfig.LinkBrowserWindowHeight ) ; +} + +function SetUrl( url ) +{ + GetE('txtUrl').value = url ; + OnUrlChange() ; + dialog.SetSelectedTab( 'Info' ) ; +} + +function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg ) +{ + // Remove animation + window.parent.Throbber.Hide() ; + GetE( 'divUpload' ).style.display = '' ; + + switch ( errorNumber ) + { + case 0 : // No errors + alert( 'Your file has been successfully uploaded' ) ; + break ; + case 1 : // Custom error + alert( customMsg ) ; + return ; + case 101 : // Custom warning + alert( customMsg ) ; + break ; + case 201 : + alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ; + break ; + case 202 : + alert( 'Invalid file type' ) ; + return ; + case 203 : + alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ; + return ; + case 500 : + alert( 'The connector is disabled' ) ; + break ; + default : + alert( 'Error on file upload. Error number: ' + errorNumber ) ; + return ; + } + + SetUrl( fileUrl ) ; + GetE('frmUpload').reset() ; +} + +var oUploadAllowedExtRegex = new RegExp( FCKConfig.LinkUploadAllowedExtensions, 'i' ) ; +var oUploadDeniedExtRegex = new RegExp( FCKConfig.LinkUploadDeniedExtensions, 'i' ) ; + +function CheckUpload() +{ + var sFile = GetE('txtUploadFile').value ; + + if ( sFile.length == 0 ) + { + alert( 'Please select a file to upload' ) ; + return false ; + } + + if ( ( FCKConfig.LinkUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) || + ( FCKConfig.LinkUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) ) + { + OnUploadCompleted( 202 ) ; + return false ; + } + + // Show animation + window.parent.Throbber.Show( 100 ) ; + GetE( 'divUpload' ).style.display = 'none' ; + + return true ; +} + +function SetDefaultTarget() +{ + var target = FCKConfig.DefaultLinkTarget || '' ; + + if ( oLink || target.length == 0 ) + return ; + + switch ( target ) + { + case '_blank' : + case '_self' : + case '_parent' : + case '_top' : + GetE('cmbTarget').value = target ; + break ; + default : + GetE('cmbTarget').value = 'frame' ; + break ; + } + + GetE('txtTargetFrame').value = target ; +} diff --git a/www/js/FCKeditor/editor/dialog/fck_listprop.html b/www/js/FCKeditor/editor/dialog/fck_listprop.html new file mode 100644 index 0000000..55b337a --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_listprop.html @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + +
+ + + + + +
+ List Type
+ + +   +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_paste.html b/www/js/FCKeditor/editor/dialog/fck_paste.html new file mode 100644 index 0000000..b5b9403 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_paste.html @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ Please paste inside the following box using the keyboard + (Ctrl+V) and hit OK.
+   +
+
+ +
+ + + +
+ + + +
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_radiobutton.html b/www/js/FCKeditor/editor/dialog/fck_radiobutton.html new file mode 100644 index 0000000..80516e0 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_radiobutton.html @@ -0,0 +1,104 @@ + + + + + Radio Button Properties + + + + + + + + + + +
+ + + + + + + + + + +
+ Name
+ +
+ Value
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_replace.html b/www/js/FCKeditor/editor/dialog/fck_replace.html new file mode 100644 index 0000000..bf98335 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_replace.html @@ -0,0 +1,650 @@ + + + + + + + + + + + + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_select.html b/www/js/FCKeditor/editor/dialog/fck_select.html new file mode 100644 index 0000000..633633a --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_select.html @@ -0,0 +1,180 @@ + + + + + Select Properties + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
Name 
Value 
Size  lines
+
+
+  Available + Options  + + + + + + + + + + + + + + + + + + +
Text
+ +
Value
+ +
+ + +
+
+ +
   +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_select/fck_select.js b/www/js/FCKeditor/editor/dialog/fck_select/fck_select.js new file mode 100644 index 0000000..3a03475 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_select/fck_select.js @@ -0,0 +1,194 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Scripts for the fck_select.html page. + */ + +function Select( combo ) +{ + var iIndex = combo.selectedIndex ; + + oListText.selectedIndex = iIndex ; + oListValue.selectedIndex = iIndex ; + + var oTxtText = document.getElementById( "txtText" ) ; + var oTxtValue = document.getElementById( "txtValue" ) ; + + oTxtText.value = oListText.value ; + oTxtValue.value = oListValue.value ; +} + +function Add() +{ + var oTxtText = document.getElementById( "txtText" ) ; + var oTxtValue = document.getElementById( "txtValue" ) ; + + AddComboOption( oListText, oTxtText.value, oTxtText.value ) ; + AddComboOption( oListValue, oTxtValue.value, oTxtValue.value ) ; + + oListText.selectedIndex = oListText.options.length - 1 ; + oListValue.selectedIndex = oListValue.options.length - 1 ; + + oTxtText.value = '' ; + oTxtValue.value = '' ; + + oTxtText.focus() ; +} + +function Modify() +{ + var iIndex = oListText.selectedIndex ; + + if ( iIndex < 0 ) return ; + + var oTxtText = document.getElementById( "txtText" ) ; + var oTxtValue = document.getElementById( "txtValue" ) ; + + oListText.options[ iIndex ].innerHTML = HTMLEncode( oTxtText.value ) ; + oListText.options[ iIndex ].value = oTxtText.value ; + + oListValue.options[ iIndex ].innerHTML = HTMLEncode( oTxtValue.value ) ; + oListValue.options[ iIndex ].value = oTxtValue.value ; + + oTxtText.value = '' ; + oTxtValue.value = '' ; + + oTxtText.focus() ; +} + +function Move( steps ) +{ + ChangeOptionPosition( oListText, steps ) ; + ChangeOptionPosition( oListValue, steps ) ; +} + +function Delete() +{ + RemoveSelectedOptions( oListText ) ; + RemoveSelectedOptions( oListValue ) ; +} + +function SetSelectedValue() +{ + var iIndex = oListValue.selectedIndex ; + if ( iIndex < 0 ) return ; + + var oTxtValue = document.getElementById( "txtSelValue" ) ; + + oTxtValue.value = oListValue.options[ iIndex ].value ; +} + +// Moves the selected option by a number of steps (also negative) +function ChangeOptionPosition( combo, steps ) +{ + var iActualIndex = combo.selectedIndex ; + + if ( iActualIndex < 0 ) + return ; + + var iFinalIndex = iActualIndex + steps ; + + if ( iFinalIndex < 0 ) + iFinalIndex = 0 ; + + if ( iFinalIndex > ( combo.options.length - 1 ) ) + iFinalIndex = combo.options.length - 1 ; + + if ( iActualIndex == iFinalIndex ) + return ; + + var oOption = combo.options[ iActualIndex ] ; + var sText = HTMLDecode( oOption.innerHTML ) ; + var sValue = oOption.value ; + + combo.remove( iActualIndex ) ; + + oOption = AddComboOption( combo, sText, sValue, null, iFinalIndex ) ; + + oOption.selected = true ; +} + +// Remove all selected options from a SELECT object +function RemoveSelectedOptions(combo) +{ + // Save the selected index + var iSelectedIndex = combo.selectedIndex ; + + var oOptions = combo.options ; + + // Remove all selected options + for ( var i = oOptions.length - 1 ; i >= 0 ; i-- ) + { + if (oOptions[i].selected) combo.remove(i) ; + } + + // Reset the selection based on the original selected index + if ( combo.options.length > 0 ) + { + if ( iSelectedIndex >= combo.options.length ) iSelectedIndex = combo.options.length - 1 ; + combo.selectedIndex = iSelectedIndex ; + } +} + +// Add a new option to a SELECT object (combo or list) +function AddComboOption( combo, optionText, optionValue, documentObject, index ) +{ + var oOption ; + + if ( documentObject ) + oOption = documentObject.createElement("OPTION") ; + else + oOption = document.createElement("OPTION") ; + + if ( index != null ) + combo.options.add( oOption, index ) ; + else + combo.options.add( oOption ) ; + + oOption.innerHTML = optionText.length > 0 ? HTMLEncode( optionText ) : ' ' ; + oOption.value = optionValue ; + + return oOption ; +} + +function HTMLEncode( text ) +{ + if ( !text ) + return '' ; + + text = text.replace( /&/g, '&' ) ; + text = text.replace( //g, '>' ) ; + + return text ; +} + + +function HTMLDecode( text ) +{ + if ( !text ) + return '' ; + + text = text.replace( />/g, '>' ) ; + text = text.replace( /</g, '<' ) ; + text = text.replace( /&/g, '&' ) ; + + return text ; +} diff --git a/www/js/FCKeditor/editor/dialog/fck_smiley.html b/www/js/FCKeditor/editor/dialog/fck_smiley.html new file mode 100644 index 0000000..bd2eaea --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_smiley.html @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + +
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_source.html b/www/js/FCKeditor/editor/dialog/fck_source.html new file mode 100644 index 0000000..d61e710 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_source.html @@ -0,0 +1,68 @@ + + + + + Source + + + + + + + + + + +
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_specialchar.html b/www/js/FCKeditor/editor/dialog/fck_specialchar.html new file mode 100644 index 0000000..eb0238c --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_specialchar.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + +
+ + +
+
     + + + + +
 
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages.html b/www/js/FCKeditor/editor/dialog/fck_spellerpages.html new file mode 100644 index 0000000..cd2355d --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages.html @@ -0,0 +1,70 @@ + + + + + Spell Check + + + + + + + + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html new file mode 100644 index 0000000..e69de29 diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js new file mode 100644 index 0000000..80af849 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js @@ -0,0 +1,87 @@ +//////////////////////////////////////////////////// +// controlWindow object +//////////////////////////////////////////////////// +function controlWindow( controlForm ) { + // private properties + this._form = controlForm; + + // public properties + this.windowType = "controlWindow"; +// this.noSuggestionSelection = "- No suggestions -"; // by FredCK + this.noSuggestionSelection = FCKLang.DlgSpellNoSuggestions ; + // set up the properties for elements of the given control form + this.suggestionList = this._form.sugg; + this.evaluatedText = this._form.misword; + this.replacementText = this._form.txtsugg; + this.undoButton = this._form.btnUndo; + + // public methods + this.addSuggestion = addSuggestion; + this.clearSuggestions = clearSuggestions; + this.selectDefaultSuggestion = selectDefaultSuggestion; + this.resetForm = resetForm; + this.setSuggestedText = setSuggestedText; + this.enableUndo = enableUndo; + this.disableUndo = disableUndo; +} + +function resetForm() { + if( this._form ) { + this._form.reset(); + } +} + +function setSuggestedText() { + var slct = this.suggestionList; + var txt = this.replacementText; + var str = ""; + if( (slct.options[0].text) && slct.options[0].text != this.noSuggestionSelection ) { + str = slct.options[slct.selectedIndex].text; + } + txt.value = str; +} + +function selectDefaultSuggestion() { + var slct = this.suggestionList; + var txt = this.replacementText; + if( slct.options.length == 0 ) { + this.addSuggestion( this.noSuggestionSelection ); + } else { + slct.options[0].selected = true; + } + this.setSuggestedText(); +} + +function addSuggestion( sugg_text ) { + var slct = this.suggestionList; + if( sugg_text ) { + var i = slct.options.length; + var newOption = new Option( sugg_text, 'sugg_text'+i ); + slct.options[i] = newOption; + } +} + +function clearSuggestions() { + var slct = this.suggestionList; + for( var j = slct.length - 1; j > -1; j-- ) { + if( slct.options[j] ) { + slct.options[j] = null; + } + } +} + +function enableUndo() { + if( this.undoButton ) { + if( this.undoButton.disabled == true ) { + this.undoButton.disabled = false; + } + } +} + +function disableUndo() { + if( this.undoButton ) { + if( this.undoButton.disabled == false ) { + this.undoButton.disabled = true; + } + } +} diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html new file mode 100644 index 0000000..d91bcce --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html @@ -0,0 +1,153 @@ + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
Not in dictionary:
Change to:
+ + + + + + + +
+ +
+ +
+
   + + + + + + + + + + + + + + + + + + + + + + +
+ +    + +
+ +    + +
+ +    + +
+
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js new file mode 100644 index 0000000..c85be9a --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js @@ -0,0 +1,461 @@ +//////////////////////////////////////////////////// +// spellChecker.js +// +// spellChecker object +// +// This file is sourced on web pages that have a textarea object to evaluate +// for spelling. It includes the implementation for the spellCheckObject. +// +//////////////////////////////////////////////////// + + +// constructor +function spellChecker( textObject ) { + + // public properties - configurable +// this.popUpUrl = '/speller/spellchecker.html'; // by FredCK + this.popUpUrl = 'fck_spellerpages/spellerpages/spellchecker.html'; // by FredCK + this.popUpName = 'spellchecker'; +// this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes"; // by FredCK + this.popUpProps = null ; // by FredCK +// this.spellCheckScript = '/speller/server-scripts/spellchecker.php'; // by FredCK + //this.spellCheckScript = '/cgi-bin/spellchecker.pl'; + + // values used to keep track of what happened to a word + this.replWordFlag = "R"; // single replace + this.ignrWordFlag = "I"; // single ignore + this.replAllFlag = "RA"; // replace all occurances + this.ignrAllFlag = "IA"; // ignore all occurances + this.fromReplAll = "~RA"; // an occurance of a "replace all" word + this.fromIgnrAll = "~IA"; // an occurance of a "ignore all" word + // properties set at run time + this.wordFlags = new Array(); + this.currentTextIndex = 0; + this.currentWordIndex = 0; + this.spellCheckerWin = null; + this.controlWin = null; + this.wordWin = null; + this.textArea = textObject; // deprecated + this.textInputs = arguments; + + // private methods + this._spellcheck = _spellcheck; + this._getSuggestions = _getSuggestions; + this._setAsIgnored = _setAsIgnored; + this._getTotalReplaced = _getTotalReplaced; + this._setWordText = _setWordText; + this._getFormInputs = _getFormInputs; + + // public methods + this.openChecker = openChecker; + this.startCheck = startCheck; + this.checkTextBoxes = checkTextBoxes; + this.checkTextAreas = checkTextAreas; + this.spellCheckAll = spellCheckAll; + this.ignoreWord = ignoreWord; + this.ignoreAll = ignoreAll; + this.replaceWord = replaceWord; + this.replaceAll = replaceAll; + this.terminateSpell = terminateSpell; + this.undo = undo; + + // set the current window's "speller" property to the instance of this class. + // this object can now be referenced by child windows/frames. + window.speller = this; +} + +// call this method to check all text boxes (and only text boxes) in the HTML document +function checkTextBoxes() { + this.textInputs = this._getFormInputs( "^text$" ); + this.openChecker(); +} + +// call this method to check all textareas (and only textareas ) in the HTML document +function checkTextAreas() { + this.textInputs = this._getFormInputs( "^textarea$" ); + this.openChecker(); +} + +// call this method to check all text boxes and textareas in the HTML document +function spellCheckAll() { + this.textInputs = this._getFormInputs( "^text(area)?$" ); + this.openChecker(); +} + +// call this method to check text boxe(s) and/or textarea(s) that were passed in to the +// object's constructor or to the textInputs property +function openChecker() { + this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps ); + if( !this.spellCheckerWin.opener ) { + this.spellCheckerWin.opener = window; + } +} + +function startCheck( wordWindowObj, controlWindowObj ) { + + // set properties from args + this.wordWin = wordWindowObj; + this.controlWin = controlWindowObj; + + // reset properties + this.wordWin.resetForm(); + this.controlWin.resetForm(); + this.currentTextIndex = 0; + this.currentWordIndex = 0; + // initialize the flags to an array - one element for each text input + this.wordFlags = new Array( this.wordWin.textInputs.length ); + // each element will be an array that keeps track of each word in the text + for( var i=0; i wi ) || i > ti ) { + // future word: set as "from ignore all" if + // 1) do not already have a flag and + // 2) have the same value as current word + if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl ) + && ( !this.wordFlags[i][j] )) { + this._setAsIgnored( i, j, this.fromIgnrAll ); + } + } + } + } + + // finally, move on + this.currentWordIndex++; + this._spellcheck(); + return true; +} + +function replaceWord() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + if( !this.wordWin.getTextVal( ti, wi )) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + if( !this.controlWin.replacementText ) { + return false ; + } + var txt = this.controlWin.replacementText; + if( txt.value ) { + var newspell = new String( txt.value ); + if( this._setWordText( ti, wi, newspell, this.replWordFlag )) { + this.currentWordIndex++; + this._spellcheck(); + } + } + return true; +} + +function replaceAll() { + var ti = this.currentTextIndex; + var wi = this.currentWordIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + var s_word_to_repl = this.wordWin.getTextVal( ti, wi ); + if( !s_word_to_repl ) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + var txt = this.controlWin.replacementText; + if( !txt.value ) return false; + var newspell = new String( txt.value ); + + // set this word as a "replace all" word. + this._setWordText( ti, wi, newspell, this.replAllFlag ); + + // loop through all the words after this word + for( var i = ti; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == ti && j > wi ) || i > ti ) { + // future word: set word text to s_word_to_repl if + // 1) do not already have a flag and + // 2) have the same value as s_word_to_repl + if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl ) + && ( !this.wordFlags[i][j] )) { + this._setWordText( i, j, newspell, this.fromReplAll ); + } + } + } + } + + // finally, move on + this.currentWordIndex++; + this._spellcheck(); + return true; +} + +function terminateSpell() { + // called when we have reached the end of the spell checking. + var msg = ""; // by FredCK + var numrepl = this._getTotalReplaced(); + if( numrepl == 0 ) { + // see if there were no misspellings to begin with + if( !this.wordWin ) { + msg = ""; + } else { + if( this.wordWin.totalMisspellings() ) { +// msg += "No words changed."; // by FredCK + msg += FCKLang.DlgSpellNoChanges ; // by FredCK + } else { +// msg += "No misspellings found."; // by FredCK + msg += FCKLang.DlgSpellNoMispell ; // by FredCK + } + } + } else if( numrepl == 1 ) { +// msg += "One word changed."; // by FredCK + msg += FCKLang.DlgSpellOneChange ; // by FredCK + } else { +// msg += numrepl + " words changed."; // by FredCK + msg += FCKLang.DlgSpellManyChanges.replace( /%1/g, numrepl ) ; + } + if( msg ) { +// msg += "\n"; // by FredCK + alert( msg ); + } + + if( numrepl > 0 ) { + // update the text field(s) on the opener window + for( var i = 0; i < this.textInputs.length; i++ ) { + // this.textArea.value = this.wordWin.text; + if( this.wordWin ) { + if( this.wordWin.textInputs[i] ) { + this.textInputs[i].value = this.wordWin.textInputs[i]; + } + } + } + } + + // return back to the calling window +// this.spellCheckerWin.close(); // by FredCK + if ( typeof( this.OnFinished ) == 'function' ) // by FredCK + this.OnFinished(numrepl) ; // by FredCK + + return true; +} + +function undo() { + // skip if this is the first word! + var ti = this.currentTextIndex; + var wi = this.currentWordIndex; + + if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) { + this.wordWin.removeFocus( ti, wi ); + + // go back to the last word index that was acted upon + do { + // if the current word index is zero then reset the seed + if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) { + this.currentTextIndex--; + this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1; + if( this.currentWordIndex < 0 ) this.currentWordIndex = 0; + } else { + if( this.currentWordIndex > 0 ) { + this.currentWordIndex--; + } + } + } while ( + this.wordWin.totalWords( this.currentTextIndex ) == 0 + || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll + || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll + ); + + var text_idx = this.currentTextIndex; + var idx = this.currentWordIndex; + var preReplSpell = this.wordWin.originalSpellings[text_idx][idx]; + + // if we got back to the first word then set the Undo button back to disabled + if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) { + this.controlWin.disableUndo(); + } + + var i, j, origSpell ; + // examine what happened to this current word. + switch( this.wordFlags[text_idx][idx] ) { + // replace all: go through this and all the future occurances of the word + // and revert them all to the original spelling and clear their flags + case this.replAllFlag : + for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) { + for( j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == text_idx && j >= idx ) || i > text_idx ) { + origSpell = this.wordWin.originalSpellings[i][j]; + if( origSpell == preReplSpell ) { + this._setWordText ( i, j, origSpell, undefined ); + } + } + } + } + break; + + // ignore all: go through all the future occurances of the word + // and clear their flags + case this.ignrAllFlag : + for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) { + for( j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == text_idx && j >= idx ) || i > text_idx ) { + origSpell = this.wordWin.originalSpellings[i][j]; + if( origSpell == preReplSpell ) { + this.wordFlags[i][j] = undefined; + } + } + } + } + break; + + // replace: revert the word to its original spelling + case this.replWordFlag : + this._setWordText ( text_idx, idx, preReplSpell, undefined ); + break; + } + + // For all four cases, clear the wordFlag of this word. re-start the process + this.wordFlags[text_idx][idx] = undefined; + this._spellcheck(); + } +} + +function _spellcheck() { + var ww = this.wordWin; + + // check if this is the last word in the current text element + if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) { + this.currentTextIndex++; + this.currentWordIndex = 0; + // keep going if we're not yet past the last text element + if( this.currentTextIndex < this.wordWin.textInputs.length ) { + this._spellcheck(); + return; + } else { + this.terminateSpell(); + return; + } + } + + // if this is after the first one make sure the Undo button is enabled + if( this.currentWordIndex > 0 ) { + this.controlWin.enableUndo(); + } + + // skip the current word if it has already been worked on + if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) { + // increment the global current word index and move on. + this.currentWordIndex++; + this._spellcheck(); + } else { + var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex ); + if( evalText ) { + this.controlWin.evaluatedText.value = evalText; + ww.setFocus( this.currentTextIndex, this.currentWordIndex ); + this._getSuggestions( this.currentTextIndex, this.currentWordIndex ); + } + } +} + +function _getSuggestions( text_num, word_num ) { + this.controlWin.clearSuggestions(); + // add suggestion in list for each suggested word. + // get the array of suggested words out of the + // three-dimensional array containing all suggestions. + var a_suggests = this.wordWin.suggestions[text_num][word_num]; + if( a_suggests ) { + // got an array of suggestions. + for( var ii = 0; ii < a_suggests.length; ii++ ) { + this.controlWin.addSuggestion( a_suggests[ii] ); + } + } + this.controlWin.selectDefaultSuggestion(); +} + +function _setAsIgnored( text_num, word_num, flag ) { + // set the UI + this.wordWin.removeFocus( text_num, word_num ); + // do the bookkeeping + this.wordFlags[text_num][word_num] = flag; + return true; +} + +function _getTotalReplaced() { + var i_replaced = 0; + for( var i = 0; i < this.wordFlags.length; i++ ) { + for( var j = 0; j < this.wordFlags[i].length; j++ ) { + if(( this.wordFlags[i][j] == this.replWordFlag ) + || ( this.wordFlags[i][j] == this.replAllFlag ) + || ( this.wordFlags[i][j] == this.fromReplAll )) { + i_replaced++; + } + } + } + return i_replaced; +} + +function _setWordText( text_num, word_num, newText, flag ) { + // set the UI and form inputs + this.wordWin.setText( text_num, word_num, newText ); + // keep track of what happened to this word: + this.wordFlags[text_num][word_num] = flag; + return true; +} + +function _getFormInputs( inputPattern ) { + var inputs = new Array(); + for( var i = 0; i < document.forms.length; i++ ) { + for( var j = 0; j < document.forms[i].elements.length; j++ ) { + if( document.forms[i].elements[j].type.match( inputPattern )) { + inputs[inputs.length] = document.forms[i].elements[j]; + } + } + } + return inputs; +} diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html new file mode 100644 index 0000000..cbcd7db --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html @@ -0,0 +1,71 @@ + + + + + + +Speller Pages + + + + + + diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css new file mode 100644 index 0000000..9928086 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css @@ -0,0 +1,49 @@ +.blend { + font-family: courier new; + font-size: 10pt; + border: 0; + margin-bottom:-1; +} +.normalLabel { + font-size:8pt; +} +.normalText { + font-family:arial, helvetica, sans-serif; + font-size:10pt; + color:000000; + background-color:FFFFFF; +} +.plainText { + font-family: courier new, courier, monospace; + font-size: 10pt; + color:000000; + background-color:FFFFFF; +} +.controlWindowBody { + font-family:arial, helvetica, sans-serif; + font-size:8pt; + padding: 7px ; /* by FredCK */ + margin: 0px ; /* by FredCK */ + /* color:000000; by FredCK */ + /* background-color:DADADA; by FredCK */ +} +.readonlyInput { + background-color:DADADA; + color:000000; + font-size:8pt; + width:392px; +} +.textDefault { + font-size:8pt; + width: 200px; +} +.buttonDefault { + width:90px; + height:22px; + font-size:8pt; +} +.suggSlct { + width:200px; + margin-top:2; + font-size:8pt; +} diff --git a/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js new file mode 100644 index 0000000..7990296 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js @@ -0,0 +1,272 @@ +//////////////////////////////////////////////////// +// wordWindow object +//////////////////////////////////////////////////// +function wordWindow() { + // private properties + this._forms = []; + + // private methods + this._getWordObject = _getWordObject; + //this._getSpellerObject = _getSpellerObject; + this._wordInputStr = _wordInputStr; + this._adjustIndexes = _adjustIndexes; + this._isWordChar = _isWordChar; + this._lastPos = _lastPos; + + // public properties + this.wordChar = /[a-zA-Z]/; + this.windowType = "wordWindow"; + this.originalSpellings = new Array(); + this.suggestions = new Array(); + this.checkWordBgColor = "pink"; + this.normWordBgColor = "white"; + this.text = ""; + this.textInputs = new Array(); + this.indexes = new Array(); + //this.speller = this._getSpellerObject(); + + // public methods + this.resetForm = resetForm; + this.totalMisspellings = totalMisspellings; + this.totalWords = totalWords; + this.totalPreviousWords = totalPreviousWords; + //this.getTextObjectArray = getTextObjectArray; + this.getTextVal = getTextVal; + this.setFocus = setFocus; + this.removeFocus = removeFocus; + this.setText = setText; + //this.getTotalWords = getTotalWords; + this.writeBody = writeBody; + this.printForHtml = printForHtml; +} + +function resetForm() { + if( this._forms ) { + for( var i = 0; i < this._forms.length; i++ ) { + this._forms[i].reset(); + } + } + return true; +} + +function totalMisspellings() { + var total_words = 0; + for( var i = 0; i < this.textInputs.length; i++ ) { + total_words += this.totalWords( i ); + } + return total_words; +} + +function totalWords( textIndex ) { + return this.originalSpellings[textIndex].length; +} + +function totalPreviousWords( textIndex, wordIndex ) { + var total_words = 0; + for( var i = 0; i <= textIndex; i++ ) { + for( var j = 0; j < this.totalWords( i ); j++ ) { + if( i == textIndex && j == wordIndex ) { + break; + } else { + total_words++; + } + } + } + return total_words; +} + +//function getTextObjectArray() { +// return this._form.elements; +//} + +function getTextVal( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + return word.value; + } +} + +function setFocus( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + if( word.type == "text" ) { + word.focus(); + word.style.backgroundColor = this.checkWordBgColor; + } + } +} + +function removeFocus( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + if( word.type == "text" ) { + word.blur(); + word.style.backgroundColor = this.normWordBgColor; + } + } +} + +function setText( textIndex, wordIndex, newText ) { + var word = this._getWordObject( textIndex, wordIndex ); + var beginStr; + var endStr; + if( word ) { + var pos = this.indexes[textIndex][wordIndex]; + var oldText = word.value; + // update the text given the index of the string + beginStr = this.textInputs[textIndex].substring( 0, pos ); + endStr = this.textInputs[textIndex].substring( + pos + oldText.length, + this.textInputs[textIndex].length + ); + this.textInputs[textIndex] = beginStr + newText + endStr; + + // adjust the indexes on the stack given the differences in + // length between the new word and old word. + var lengthDiff = newText.length - oldText.length; + this._adjustIndexes( textIndex, wordIndex, lengthDiff ); + + word.size = newText.length; + word.value = newText; + this.removeFocus( textIndex, wordIndex ); + } +} + + +function writeBody() { + var d = window.document; + var is_html = false; + + d.open(); + + // iterate through each text input. + for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) { + var end_idx = 0; + var begin_idx = 0; + d.writeln( '
' ); + var wordtxt = this.textInputs[txtid]; + this.indexes[txtid] = []; + + if( wordtxt ) { + var orig = this.originalSpellings[txtid]; + if( !orig ) break; + + //!!! plain text, or HTML mode? + d.writeln( '
' ); + // iterate through each occurrence of a misspelled word. + for( var i = 0; i < orig.length; i++ ) { + // find the position of the current misspelled word, + // starting at the last misspelled word. + // and keep looking if it's a substring of another word + do { + begin_idx = wordtxt.indexOf( orig[i], end_idx ); + end_idx = begin_idx + orig[i].length; + // word not found? messed up! + if( begin_idx == -1 ) break; + // look at the characters immediately before and after + // the word. If they are word characters we'll keep looking. + var before_char = wordtxt.charAt( begin_idx - 1 ); + var after_char = wordtxt.charAt( end_idx ); + } while ( + this._isWordChar( before_char ) + || this._isWordChar( after_char ) + ); + + // keep track of its position in the original text. + this.indexes[txtid][i] = begin_idx; + + // write out the characters before the current misspelled word + for( var j = this._lastPos( txtid, i ); j < begin_idx; j++ ) { + // !!! html mode? make it html compatible + d.write( this.printForHtml( wordtxt.charAt( j ))); + } + + // write out the misspelled word. + d.write( this._wordInputStr( orig[i] )); + + // if it's the last word, write out the rest of the text + if( i == orig.length-1 ){ + d.write( printForHtml( wordtxt.substr( end_idx ))); + } + } + + d.writeln( '
' ); + + } + d.writeln( '
' ); + } + //for ( var j = 0; j < d.forms.length; j++ ) { + // alert( d.forms[j].name ); + // for( var k = 0; k < d.forms[j].elements.length; k++ ) { + // alert( d.forms[j].elements[k].name + ": " + d.forms[j].elements[k].value ); + // } + //} + + // set the _forms property + this._forms = d.forms; + d.close(); +} + +// return the character index in the full text after the last word we evaluated +function _lastPos( txtid, idx ) { + if( idx > 0 ) + return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length; + else + return 0; +} + +function printForHtml( n ) { + return n ; // by FredCK +/* + var htmlstr = n; + if( htmlstr.length == 1 ) { + // do simple case statement if it's just one character + switch ( n ) { + case "\n": + htmlstr = '
'; + break; + case "<": + htmlstr = '<'; + break; + case ">": + htmlstr = '>'; + break; + } + return htmlstr; + } else { + htmlstr = htmlstr.replace( //g, '>' ); + htmlstr = htmlstr.replace( /\n/g, '
' ); + return htmlstr; + } +*/ +} + +function _isWordChar( letter ) { + if( letter.search( this.wordChar ) == -1 ) { + return false; + } else { + return true; + } +} + +function _getWordObject( textIndex, wordIndex ) { + if( this._forms[textIndex] ) { + if( this._forms[textIndex].elements[wordIndex] ) { + return this._forms[textIndex].elements[wordIndex]; + } + } + return null; +} + +function _wordInputStr( word ) { + var str = ''; + return str; +} + +function _adjustIndexes( textIndex, wordIndex, lengthDiff ) { + for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) { + this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff; + } +} diff --git a/www/js/FCKeditor/editor/dialog/fck_table.html b/www/js/FCKeditor/editor/dialog/fck_table.html new file mode 100644 index 0000000..74a899b --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_table.html @@ -0,0 +1,440 @@ + + + + + Table Properties + + + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ Rows: +  
+ Columns: +  
Headers: +   +
+ Border size: +  
+ Alignment: +  
+
+     + + + + + + + + + + + + + + + + + + + + + + + + +
+ Width: +   +  
+ Height: +   +  pixels
 
+ Cell spacing: +   +  
+ Cell padding: +   +  
+
+ + + + + + + + + + + +
+ Caption +   +
+ Summary +   +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_tablecell.html b/www/js/FCKeditor/editor/dialog/fck_tablecell.html new file mode 100644 index 0000000..a7bc921 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_tablecell.html @@ -0,0 +1,293 @@ + + + + + Table Cell Properties + + + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Width: +   
+ Height: +   pixels
+   +  
+ Word Wrap: +  
+   +  
+ Horizontal Alignment: +  
+ Vertical Alignment: +  
+
+     + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Cell Type: +   +
+   +   +  
+ Rows Span: +   + +
+ Columns Span: +   + +
+   +   +  
+ Background Color: +   +   +
+ Border Color: +   +   +
+
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_template.html b/www/js/FCKeditor/editor/dialog/fck_template.html new file mode 100644 index 0000000..084dc6d --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_template.html @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ Please select the template to open in the editor
+ (the actual contents will be lost):
+
+
+ + +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_template/images/template1.gif b/www/js/FCKeditor/editor/dialog/fck_template/images/template1.gif new file mode 100644 index 0000000000000000000000000000000000000000..efdabbebd4503ceb55c948fa73b9b83cbd373e57 GIT binary patch literal 375 zcmV--0f_!bNk%w1VPpVC0FeLyva+%O00960{{R30A^8LV00000EC2ui0Av7000092 zgpaAq?GK}zwAu@W-n{z{hT=$;9b%^H%BpA!$8!13_AS@=&Xal%3~GMDB95pDD3{Ep z^T{;k4xj+g%7JRP+$IPq!1Bb&uKB$DQa@x|8x8NO4b`hO25#TOnRw~9=3yE0xyeE4CQ8$(2)Mz>8udZCXX=BRr7DZbW_#-a zYZEHlJM(KAEc4dditDMnJ4(CC+&uK06fIp0D*Z|wX5EYpGb{?;a*WKVoEoWp!Y!`y zeo4*}FFC(bZf@duda#%D-q zaHzPUxA@lRm;@PFNk%w1VPpVC0FeLyva+%O00960{{R30A^8LV00000EC2ui0Av7000092 zgpaAq?GK}zwAu@W-n{z{hT=$;9b%^H%BpA!$8!13_AS@=&Xal%3~GMDB93TG#*l%g z^9hYgr_`$T`us4l+^+W<)gC_JviY3#AeC&_xD98m<8-m1jvsB&<_@0q~XXRsCap^IRqK$(K#c!N9pBf82AawVH$?WN){q&IjedXiz+EX zOS+od%WDgp+d909toAG5`lTy-9D18rOxWx+T}>D*o&1Qa9n5V^96nACtqfi*?*05t zZSMX~zfpQ^<%jRPUfiDEO8=eEuB)DKv}S_cJW8uTxqL`=(AMXYB~Aenu4SM=e_ zrj6M`kqsZ_xrlC}y^5evW>krApudqWP2zFM5Fo{b%sA$2wGU)SI5vkKVQCad(WEn$ zGF`IFr&KONpB8ayRSwduHn4I{;q@zxs8h=VDkqjl*t8(;n#c+zd*_U=jy QeEa(S3plV~2n7HDJNoX*`2YX_ literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/dialog/fck_textarea.html b/www/js/FCKeditor/editor/dialog/fck_textarea.html new file mode 100644 index 0000000..e4edae9 --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_textarea.html @@ -0,0 +1,94 @@ + + + + + Text Area Properties + + + + + + + + + + +
+ + + + +
+ Name
+ + Collumns
+ +
+ Rows
+ +
+
+ + diff --git a/www/js/FCKeditor/editor/dialog/fck_textfield.html b/www/js/FCKeditor/editor/dialog/fck_textfield.html new file mode 100644 index 0000000..efde66d --- /dev/null +++ b/www/js/FCKeditor/editor/dialog/fck_textfield.html @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ Name
+ +
+ + Value
+ +
+ Character Width
+ +
+ + Maximum Characters
+ +
+ Type
+ +
+   +
+
+ + diff --git a/www/js/FCKeditor/editor/dtd/fck_dtd_test.html b/www/js/FCKeditor/editor/dtd/fck_dtd_test.html new file mode 100644 index 0000000..c149d15 --- /dev/null +++ b/www/js/FCKeditor/editor/dtd/fck_dtd_test.html @@ -0,0 +1,41 @@ + + + + DTD Test Page + + + + + +

+ DTD Contents +

+ + +
+ + diff --git a/www/js/FCKeditor/editor/dtd/fck_xhtml10strict.js b/www/js/FCKeditor/editor/dtd/fck_xhtml10strict.js new file mode 100644 index 0000000..81c2670 --- /dev/null +++ b/www/js/FCKeditor/editor/dtd/fck_xhtml10strict.js @@ -0,0 +1,116 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Contains the DTD mapping for XHTML 1.0 Strict. + * This file was automatically generated from the file: xhtml10-strict.dtd + */ +FCK.DTD = (function() +{ + var X = FCKTools.Merge ; + + var H,I,J,K,C,L,M,A,B,D,E,G,N,F ; + A = {ins:1, del:1, script:1} ; + B = {hr:1, ul:1, div:1, blockquote:1, noscript:1, table:1, address:1, pre:1, p:1, h5:1, dl:1, h4:1, ol:1, h6:1, h1:1, h3:1, h2:1} ; + C = X({fieldset:1}, B) ; + D = X({sub:1, bdo:1, 'var':1, sup:1, br:1, kbd:1, map:1, samp:1, b:1, acronym:1, '#':1, abbr:1, code:1, i:1, cite:1, tt:1, strong:1, q:1, em:1, big:1, small:1, span:1, dfn:1}, A) ; + E = X({img:1, object:1}, D) ; + F = {input:1, button:1, textarea:1, select:1, label:1} ; + G = X({a:1}, F) ; + H = {img:1, noscript:1, br:1, kbd:1, button:1, h5:1, h4:1, samp:1, h6:1, ol:1, h1:1, h3:1, h2:1, form:1, select:1, '#':1, ins:1, abbr:1, label:1, code:1, table:1, script:1, cite:1, input:1, strong:1, textarea:1, big:1, small:1, span:1, hr:1, sub:1, bdo:1, 'var':1, div:1, object:1, sup:1, map:1, dl:1, del:1, fieldset:1, ul:1, b:1, acronym:1, a:1, blockquote:1, i:1, address:1, tt:1, q:1, pre:1, p:1, em:1, dfn:1} ; + + I = X({form:1, fieldset:1}, B, E, G) ; + J = {tr:1} ; + K = {'#':1} ; + L = X(E, G) ; + M = {li:1} ; + N = X({form:1}, A, C) ; + + return { + col: {}, + tr: {td:1, th:1}, + img: {}, + colgroup: {col:1}, + noscript: N, + td: I, + br: {}, + th: I, + kbd: L, + button: X(B, E), + h5: L, + h4: L, + samp: L, + h6: L, + ol: M, + h1: L, + h3: L, + option: K, + h2: L, + form: X(A, C), + select: {optgroup:1, option:1}, + ins: I, + abbr: L, + label: L, + code: L, + table: {thead:1, col:1, tbody:1, tr:1, colgroup:1, caption:1, tfoot:1}, + script: K, + tfoot: J, + cite: L, + li: I, + input: {}, + strong: L, + textarea: K, + big: L, + small: L, + span: L, + dt: L, + hr: {}, + sub: L, + optgroup: {option:1}, + bdo: L, + param: {}, + 'var': L, + div: I, + object: X({param:1}, H), + sup: L, + dd: I, + area: {}, + map: X({form:1, area:1}, A, C), + dl: {dt:1, dd:1}, + del: I, + fieldset: X({legend:1}, H), + thead: J, + ul: M, + acronym: L, + b: L, + a: X({img:1, object:1}, D, F), + blockquote: N, + caption: L, + i: L, + tbody: J, + address: L, + tt: L, + legend: L, + q: L, + pre: X({a:1}, D, F), + p: L, + em: L, + dfn: L + } ; +})() ; diff --git a/www/js/FCKeditor/editor/dtd/fck_xhtml10transitional.js b/www/js/FCKeditor/editor/dtd/fck_xhtml10transitional.js new file mode 100644 index 0000000..ce056a1 --- /dev/null +++ b/www/js/FCKeditor/editor/dtd/fck_xhtml10transitional.js @@ -0,0 +1,140 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Contains the DTD mapping for XHTML 1.0 Transitional. + * This file was automatically generated from the file: xhtml10-transitional.dtd + */ +FCK.DTD = (function() +{ + var X = FCKTools.Merge ; + + var A,L,J,M,N,O,D,H,P,K,Q,F,G,C,B,E,I ; + A = {isindex:1, fieldset:1} ; + B = {input:1, button:1, select:1, textarea:1, label:1} ; + C = X({a:1}, B) ; + D = X({iframe:1}, C) ; + E = {hr:1, ul:1, menu:1, div:1, blockquote:1, noscript:1, table:1, center:1, address:1, dir:1, pre:1, h5:1, dl:1, h4:1, noframes:1, h6:1, ol:1, h1:1, h3:1, h2:1} ; + F = {ins:1, del:1, script:1} ; + G = X({b:1, acronym:1, bdo:1, 'var':1, '#':1, abbr:1, code:1, br:1, i:1, cite:1, kbd:1, u:1, strike:1, s:1, tt:1, strong:1, q:1, samp:1, em:1, dfn:1, span:1}, F) ; + H = X({sub:1, img:1, object:1, sup:1, basefont:1, map:1, applet:1, font:1, big:1, small:1}, G) ; + I = X({p:1}, H) ; + J = X({iframe:1}, H, B) ; + K = {img:1, noscript:1, br:1, kbd:1, center:1, button:1, basefont:1, h5:1, h4:1, samp:1, h6:1, ol:1, h1:1, h3:1, h2:1, form:1, font:1, '#':1, select:1, menu:1, ins:1, abbr:1, label:1, code:1, table:1, script:1, cite:1, input:1, iframe:1, strong:1, textarea:1, noframes:1, big:1, small:1, span:1, hr:1, sub:1, bdo:1, 'var':1, div:1, object:1, sup:1, strike:1, dir:1, map:1, dl:1, applet:1, del:1, isindex:1, fieldset:1, ul:1, b:1, acronym:1, a:1, blockquote:1, i:1, u:1, s:1, tt:1, address:1, q:1, pre:1, p:1, em:1, dfn:1} ; + + L = X({a:1}, J) ; + M = {tr:1} ; + N = {'#':1} ; + O = X({param:1}, K) ; + P = X({form:1}, A, D, E, I) ; + Q = {li:1} ; + + return { + col: {}, + tr: {td:1, th:1}, + img: {}, + colgroup: {col:1}, + noscript: P, + td: P, + br: {}, + th: P, + center: P, + kbd: L, + button: X(I, E), + basefont: {}, + h5: L, + h4: L, + samp: L, + h6: L, + ol: Q, + h1: L, + h3: L, + option: N, + h2: L, + form: X(A, D, E, I), + select: {optgroup:1, option:1}, + font: J, // Changed from L to J (see (1)) + ins: P, + menu: Q, + abbr: L, + label: L, + table: {thead:1, col:1, tbody:1, tr:1, colgroup:1, caption:1, tfoot:1}, + code: L, + script: N, + tfoot: M, + cite: L, + li: P, + input: {}, + iframe: P, + strong: J, // Changed from L to J (see (1)) + textarea: N, + noframes: P, + big: J, // Changed from L to J (see (1)) + small: J, // Changed from L to J (see (1)) + span: J, // Changed from L to J (see (1)) + hr: {}, + dt: L, + sub: J, // Changed from L to J (see (1)) + optgroup: {option:1}, + param: {}, + bdo: L, + 'var': J, // Changed from L to J (see (1)) + div: P, + object: O, + sup: J, // Changed from L to J (see (1)) + dd: P, + strike: J, // Changed from L to J (see (1)) + area: {}, + dir: Q, + map: X({area:1, form:1, p:1}, A, F, E), + applet: O, + dl: {dt:1, dd:1}, + del: P, + isindex: {}, + fieldset: X({legend:1}, K), + thead: M, + ul: Q, + acronym: L, + b: J, // Changed from L to J (see (1)) + a: J, + blockquote: P, + caption: L, + i: J, // Changed from L to J (see (1)) + u: J, // Changed from L to J (see (1)) + tbody: M, + s: L, + address: X(D, I), + tt: J, // Changed from L to J (see (1)) + legend: L, + q: L, + pre: X(G, C), + p: L, + em: J, // Changed from L to J (see (1)) + dfn: L + } ; +})() ; + +/* + Notes: + (1) According to the DTD, many elements, like accept elements + inside of them. But, to produce better output results, we have manually + changed the map to avoid breaking the links on pieces, having + "this is a link test", instead of + "this is a link test". +*/ diff --git a/www/js/FCKeditor/editor/fckdebug.html b/www/js/FCKeditor/editor/fckdebug.html new file mode 100644 index 0000000..35dd663 --- /dev/null +++ b/www/js/FCKeditor/editor/fckdebug.html @@ -0,0 +1,153 @@ + + + + + FCKeditor Debug Window + + + + + + + + + + + +
+ + + + + +
+ FCKeditor Debug Window +
+
+ +
+ + diff --git a/www/js/FCKeditor/editor/fckdialog.html b/www/js/FCKeditor/editor/fckdialog.html new file mode 100644 index 0000000..706e4b1 --- /dev/null +++ b/www/js/FCKeditor/editor/fckdialog.html @@ -0,0 +1,819 @@ + + + + + + + + + + +
+ +
+
+ + + + + +
  + +   + +
+
+
+
+
+
+
+
+
+
+
+ + + + + diff --git a/www/js/FCKeditor/editor/fckeditor.html b/www/js/FCKeditor/editor/fckeditor.html new file mode 100644 index 0000000..5438b68 --- /dev/null +++ b/www/js/FCKeditor/editor/fckeditor.html @@ -0,0 +1,317 @@ + + + + + FCKeditor + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/www/js/FCKeditor/editor/fckeditor.original.html b/www/js/FCKeditor/editor/fckeditor.original.html new file mode 100644 index 0000000..3bb4b40 --- /dev/null +++ b/www/js/FCKeditor/editor/fckeditor.original.html @@ -0,0 +1,425 @@ + + + + + FCKeditor + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/www/js/FCKeditor/editor/images/anchor.gif b/www/js/FCKeditor/editor/images/anchor.gif new file mode 100644 index 0000000000000000000000000000000000000000..5aa797b2240a432d9f3f1d166ed5542eaf684937 GIT binary patch literal 184 zcmZ?wbhEHb6kygJ|Uu&?oD;%Ae!z@09(NL_hv#6Slx0y!YR{?r|LJZgAju=f-$sQVWNL{+Tsz18#+~Ke%+zTWns()WcPwy8dQcr!JH# U&i)o#0r5dH3``s@d}5hzR)=UXSOWn0FbS~$ literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/arrow_rtl.gif b/www/js/FCKeditor/editor/images/arrow_rtl.gif new file mode 100644 index 0000000000000000000000000000000000000000..22e864984dc8be2445bc66780300651610c029b3 GIT binary patch literal 49 ucmZ?wbhEHbWMN=uXkcW30L7myKqe!D4u}hqVPN9uDdaf4E0als!5RRbfd=jX literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/angel_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/angel_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..a95e053715347debd916ed191a9411a81b97c471 GIT binary patch literal 445 zcmZ?wbhEHb6lM@+xXQrr9|(Sb_<#TZmHYqCocVv?&VeiY|Nox>6kYZI{;DhYSN-3= z>dO9A|L3o|GJn;A1xx<_5B+~X^veCv|NBF)><|4vKlIA{&{gw+f(-xnGhErv@P9tT zmH7<+>qA!oQGDns`_TXO46A_1o}s=zG!%&9LqqLD>*X1!0u+C;aB?uPGw6U!1Nn)8 z?bdpKkHzGr_?|tkP*zrwQ_#3s<;%KVQtI0mlP5;%EsX7TQU#R>4h0^J Y+;U1?I|3RGOjWBEnPcc+z`_b-pkvvd@;YvKie|v^2_6+~!8Lr4P ztg>fVCC^YV9~vqjs%0OlB_CQZ&k!olKy{$_lZBImfrUW_WHQK43~Y}anhH85q*w@Z zCY?~pQtH=mahB4ZsXWO=sn)}7L5GWSrrWAXZBf#-E*hzc7rnDCt4=uXI$6MOYZkA7 zfHH%Mpn#yD91BN!TMQe&3S(QIgrF>Eh4NH+zCdLzW@Y|PK~Kr_#idOOiahP&f)e6l zGW^QiN=x~9g)-tcCyT}+GB%Uce!hTiF?^;x8yJG>gSwKrZG0 z6C=Cw454kTES%E(B9T)Veznhd;v^)Jw)f;D)r6LG-(v@w*>vZyl=!x&dU75dX)&5lr z7A#pce^o<6!~gnKSL#=-s$ccLKJ-d`=>Pc8EAgSL>O)t>hyJ$@y<#8wUp{n|edsEA zpcKQEc!vM>3|H(K{>w95k!M&X&p;!f_>+Z`gMo!X2V_3TPYi5F9GVI|bfo%EJZwBP zMW(}hV%sN?Af<`tSb}Y19K`$CjTLMJ*iN=MCkkjtUr;Yu*rM>hS&T$tHgPEt`JS%OQ5vpPyxUWh@crCCHyjLVyizh^ENYqG*rDc)3mp=#k? zVIIaL2{~y|9ww)496~a}qFjO!5(*N$^)5U@JtExRGIH{lQeC&zaPi6Pzvm$)bhCEZ mWzYI7SuyVWo-7RPPX)NXxr&Ls`^766;Qv5?!M%xr!5RS2k9cPQ literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/cake.gif b/www/js/FCKeditor/editor/images/smiley/msn/cake.gif new file mode 100644 index 0000000000000000000000000000000000000000..f6489d7d59dc8dba08fb248e9b0a6182695f5e01 GIT binary patch literal 453 zcmZ?wbhEHb6lM@+xXQrr9|(Sb_<#TZmHYqCocVv?&Vgm8KK!2n6kYZI{;DhYSN-3= z>dO9A|L3n-wSU!u1xr@VU)9jiu&REQR{Sb0`&C-p5cl;Lw$W{eSD~vJ&68_N$gbeS zDhzroJfdsAFGyRV`i=9}4E~kM(rnrlo;*^G!jf71T_V!b{BAlt96Wqt^`f_P;a`ABWE2>Fv+}!NAO*1LA<}WMJL@K%tNMpb3xTy2pofx;E|L)fVEFIb0LGhDBCiZMJEM zF6+Th3MWL`k0+aDo|R*0Nd3-{k*VZ%X3__r<8zOcJXByw?RQD%{;r^-cQVoJ+d5IP zNPYnxL4HdERv%vLu68{hzM9F_#?u5_eW&@)HWt(q| z%*7`&Nm6ozm-R1u?j2Sd7c&_b*U>lynMHL7Yg&A PG*b->VrSA(WUvMRUk7-C literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/cry_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/cry_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..0758f429e95b1fa75f3e54b731fab507ab9318bd GIT binary patch literal 473 zcmZ?wbhEHb6lM@+xXQrr9|(SbxN`shnKSnzaM(#e(3-Gp;v%te(0+Gp{wQt1sVSD zXSf1H^BGpvhpvhbU1cA-s-9t0Ji{t`hWh%@`uNaLdmzbBZ_hv>Q2fcl$-%(RpaU`o zp$RRi*^+&@(=1KgLMhldk9yB&+Cz$0#Ola^FV6X-N Dk$IbY literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/devil_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/devil_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..15518d7f05408c0c00be035fbbeb20001878807b GIT binary patch literal 444 zcmZ?wbhEHb6lM@+xXQrr9|(Sb_<#TZmHYn>+&S=n#{Vn(S6!LEYSsQ#tLCq2XlS@n zziL(eDy{nep&$|{75cwE^h$l`|M<`=@u92gLs!Lz{+Z`gMpPn2V^+NPYi4~4>Vm^Bq-G@-}NwJL4y#>vI`qF zx-6f?_xO}ajSc5wRpw1HOIW#=RsGGdoB5=r`DK8K+@91(gD1M;%F0SYLL$w|QeqrQ z@~r}bf=YtQf+7;~0dDNVLV~ReCJHJq|Pj?=;e9q-^_#2|zdIKUYk(Fhu#F*HOF1Rxj!p#lZephOfzAQ~c(1PMrn zL=-^*ilGn`5TJon5v^)56{-_;P-p6>jc5aHOdDzt4bWg3s4A*ZHC1X9jnHTssYx_J zlWC$B(E=@|g-WSIDNRWeF@cGh(43fqIWtFV#2Q#**3g1jfCaNqHFYeQS`}Lqi?C=G zX-O=>l3Ah^u>vb*g+?*LXhvp{EXZP6n4M&Y>?}LxMskDPSZTUD_vb*4gENHbg+BVsnt8;-p&V4KfLVx>nDcC z?z^Mww?A&{pZsFuucY> ztow=MFWxoP-u2J+zjwWK{LsnSJ?p0K{%pFpr}Mzb?SA9j+u!dzHUIdk-Q&01w6$++ x$nQS$<_Jd59(ixz-PXe952gkkx~}V(@%^?x&i-=4>46{K8TW_Vms}&8{s+7l5EK9a literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/envelope.gif b/www/js/FCKeditor/editor/images/smiley/msn/envelope.gif new file mode 100644 index 0000000000000000000000000000000000000000..66d3656147a0f70d36c65ea44a0ee1577fc5832b GIT binary patch literal 1030 zcmW+#U5FM$6g|dTZhx$PAq3H^i})~wp;2T#3{jc}!4lof${kBv77<#ghsuY$pT!ck zJ=GUm56uRPu-AvohoEQ~_a$@tN~B2$jCt@uiUOlBBIq=`2Znow;czeKo_TD~t_OC! z&_M@(V+B*IXKJ-fwcFGR&RjZkV)?2M<^z3%kK&{GNU!iJUd=0gf=}X;`9z=Lv-oU2 z(^vQ^zM8M}gr|6#Cj}6QzyuTraU#ydQ35201d~9CkSG#OB1Iu8q9#g7kR*~!5+y^j zNH)oo3aKL1q*4f>2u(-@w5eeVs)IUFXX>Z{8bpI>phjpEji!;RP!&~Er6y<+O{R&O zp;o$JN*Z7ggBfTJ=ER(tqXk$H3ub{9VNooa#inUviK#WQC0G(m zW{H+zSuC4nT7^}yYF254QH*9}0SctR3RoP9lj5v6mVgqZ1S^3hqC_dtN@P(Km7-RZ zC7~oK$x33$C|OFjl36NBl~S!#7NSrJt&l5rw$2W8Le~fxz#t69Kt?bMqcO7CO%c_#tEJV(8aDkiFt`rqaCdub zKcWMyyNve+@7R56Zt2bGn+G3!ZK!+K#1AJHzC1fQeBH!Q`r?i0nUO~Z`X4`Wbo!53 zd+E-bMn>0u_v2?zot<6SzVnq$OTBCV{W5d$$=>7 z=WoC7##_3N4t)C6@Y`D^XBPLBtxx}ae0b^PzJo`$bpHCax43uk)UKoN^cFtpj*Txa zUpxNMbBhN$n}_B<`2DBTFQ5N>|N95}`@3Tsx848k-qVMcp1tAl`Xd*&Um19D!^C<& zI&|gS?Aq5aj9lJ!=$?ZcF8w+3&DY(x9^TX0{M*j!kIkL*x6Y66?oD>rtieP717~&l A`~Uy| literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/heart.gif b/www/js/FCKeditor/editor/images/smiley/msn/heart.gif new file mode 100644 index 0000000000000000000000000000000000000000..305714f889555d11032bb7a07bff522f5f854acb GIT binary patch literal 1012 zcmW+#U5JoH6g`r{F8w^T{ScHNVN_0O%Wi}gG@@ZYSO{^55E%toF!CX?p3=LTML#cv z3N5kC(vQh~>d7D<#xTK_g%AdVPzE6qgTSDuE$B4sf#IHEINZy*XP$g|^Sbpr$1sM! zu!QMrXZl*1?zibBoVsx8*!-~%BV>l`AuAMw!caUEg@(`= znun$!1Tn~iM1UaSggAf$IXDL~f{~2QC?+tG$(ck0jWnl;8O&sMX0d>UEY2b}u#wH# zM1dmZlnk)0h8tu9Y@iKpgDk=#ExJWnf+bpVOEQBQ&D>0uVVRcQvaG-gt+*9ggEd-n zYcin^Wpa}oaM0ln`2Zj2gZm(l@JNsDQJ&z5p4?N{^s(sXUF;d2>DfKY3%t;adyzMI zqc`^^7hH6?OBJYKg;%H!r~~WZbx@6{ku`dastGl*Ca+1=P>t2RnrcSPtl4W;EvSXH zcrB_8wXrs@O;xC3l~-xW&fa-|25RU;icqAYD@qAURB|PCyJeJl_eB}XRCZ;lK!qx< zA~mQ{&DA9J75Tz~w4h08N}5@s-P67{!n~V{3}hlZvQU6R6h{#n(1_+}>N)C`2Oxj} zohS?l1H<59P>2YT`uFPG+~+;g>N)Rq>CcysZg_8D;=iBHj2&LH{iFSh2cMsK@xH0EZ;$@AeD9BIwtT&L>gIdKZ+YhE z?EV#dUV4A`%1w{lKC$Z9k;CV=Kfdq$`mGPo9N)UyMlYV({lb=Y`)=T>zi+$ac$yu5 z>%xl5({m^8-L(48TPMcuiU(g_`Nqeue75%VJ2(Ea`s4#YTsm~!?`OYw^`Xg)oEg73 Zx%`_QpFEehjXkm9*%NyXEL(=h{s()1^AZ36 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/kiss.gif b/www/js/FCKeditor/editor/images/smiley/msn/kiss.gif new file mode 100644 index 0000000000000000000000000000000000000000..f840ea602cc02693e97a5cc3b3453f7c39dc2abf GIT binary patch literal 978 zcmW+#O=uoO6dXz`iDG;BE~yBMAXFDcLM|~{mNZr)h#u1Mx&|Z%5xf{_6@011ix>ZT zP%vx?wdgDUL9en=+e6!U+k=R>7o`@8^j4&Yag%}N&9V&dF>m&{=bxQ_a&>|U?qC-i zduL;>Y>eB+F1G*JzHse!OdgYBM$C-aV^%aoV>FMZSP%iCNYDV%+4$tXrwt!EMOsvvxpU}WOY`tgPrWoE(#PW zr(}Q)HQXQzus{oLL6%^NmfVso!!j+qWtqW@W^N`cutFl?SCJ}Isp_gyhdR|= zUD8;Q@9aoBnv>R~&v)tYbgYdqALgO}g(!|9RG<>oQH2h4qC2`qj)vtCh+xDZiUBb& z29H58AtvhX?X9izBhnfR;n{TeaedVLWbGgp1|9t7<$|GlHmS*oBpPekfaQ{mOU!VHq z%O_r)pS$@xXFuG2`qaXy%fH;}>7C_s2Yy|;dH(u~_2su7SUa?MY4z;MwQKFj;eCsz z-+T9q*WQ@9`oZSGsW@}*g>N?>UO({Tk$+YfR~F_zzI^t^_R*#3<5#Ynxbf#v-pBX9 bnSAx{vD59u;bX7d`Qh*DpB=hqKc4y@%md%w literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/lightbulb.gif b/www/js/FCKeditor/editor/images/smiley/msn/lightbulb.gif new file mode 100644 index 0000000000000000000000000000000000000000..863be6e51ca72e7855147df62c8506d60eb0e9c8 GIT binary patch literal 303 zcmV+~0nq+ONk%w1VG{ro0K@TH# zs?@)#)Ss%Vzp9|1q^h5)fPjF1pQ``=RsY{r)W22KpH-@#Re*p1s()3gUsbAq0DoUq zRbN#qUsY8$YpNh5b^ri)7!6Y-7!y`)016uqFe(KY6j=cl8xE0E1rUA+7>@-~Q!IT#nJE_w zB{-u84;&B>91mOz7%&7W4h{wm9)?JpBn}Yz9GcS0a>OJd06W)^ BeUJbE literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/omg_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/omg_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..aabc7fd17e0f09bcb73ac9e200a626f3068d778e GIT binary patch literal 342 zcmZ?wbhEHb6lM@+IKsg29|(SbxN`shfjbA5o%-;9#{d8KS6u<3{i{~ZU)9ji@c)14 z|NEg=?uY*0A9@9d=7+AD4-{eezn|d>5Y1<3Xkb`XAG)fZVO2aseSK)XJPQK z;!hS%4hB{R9S|2}Cj;x{1jWAAhc=sud8brn*#y@mnaV6C}`I17`wg@}N%$RQqaCWbT-Ve$P+Y-U0{8zn9>2=E0PaO_?wEX7>7 eIK)7SUzA^1KvGIVfcc#rhu~ihrgu&Z4AuY%yn4<6 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/regular_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/regular_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..33f297e818c0fc7cc4841272301963c3344ad373 GIT binary patch literal 1036 zcmW+#O=uoO6da1sM2c1t@KW5Spwg{)Xhmv0Y*TEt@nHHjPejBuAxR+zp*Mxfi;9g( z1fil;k^O9&5TAlrr3XE14nZ^x7Qz<%DQxvp6vSLg4Iai#29`I=GQ7vU*~gC_+5gCB zANp_$8<^fa)0<_w-KICNcx`chdCdp&fj+`V@zH#wS9le#=9NCdC-KRAqR;SId^Vry zD|{7S%~yKDQ#{R+0tiH40*Zq;5oh8k0TM)lNuWeX6p1F0q7W5P6Qv|b5=kbBk|9|n zn`BCbRFP^@DTGjjCZqz|)G!6rL7k{Gb<_Y2qQNv!BQ%Oe(@0gQimItn6Euk?(?reC zESgO-wL+_CHLX;l4W%?C4KRqo3^WIGV$RIb0xXCHvp|cmC>G6P)3mX~)SB25EQuwv zM9Z)&md!G)!m3y`t2DwWMl-Si1yW!IEDpsq{5 z=mUEG#F^e5XSefY0{KOFmg zabmS|v-iEBaXa`*XZN0~+sC@fEr+*_UwOVevC!#V`g!Y#^v+@4JbCGh{)gVZ@^5$e z+hbEdOBt5b@1b<`QtNpj1BL- z_s;SA&Yavm{AIlH_xY($KkxM1|JRE{-;IrS=B{tKaeVpwKd;#f?|0sq9zBRh{|CYs B0q6h# literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/sad_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/sad_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..dfb78efea7fe651c7ba84aaf2fb3ee19aa8f8efc GIT binary patch literal 1039 zcmW+#O=uoO6nwQRZIK#H1fzu|Dwr(MOGWDMT7PQPprK?ygSd!RrQSS9!NNz@umN&~XyvMxRC!gB2 zrCa`%HH@#H@%1v^ZsTj1|8@Sv!m1DE1AP=9;iLITui_P6%`1HppWu`EM4!cH_-sDY zSMe3Tny>T}Pk5RqAp!x!AcPY*z!@A71OW(!Ktw?Vq9GD0P(TezBtZg_ArV=Sfo#Y` z6;z-aDnS7O8b}qK^VYb3}h5WFd8G9-BeJm`NAYj zU@|5$3p1FFnXJMJR%0dER%A;{rX!EqK4Wib}l_ZiN$s|#-NQPvSOsOIj zQcWsbj+*6O#0$JMLhr;ocxT?x2k`;CvfAlPw@9<)yeZa8tBp1E{d@K1O>$NS+hh9? z-6ES-Rlqd^@^-?C#r_yKZwm!~cAF_^;2d-_o;x>+a#-FTc>)*MHR$4^B*dzkSb4 zr}x77KWdoiy7Kef#NJ+yfxc^JFOIJK`0!%qLvLR^*ZJVajb~RT-o7yO)z-PGEw6T6 z8alYJd*Gv!zSj<&8kw9reRTAv`RV`qAAkPx&A&Y|GqimCNblaxf$42;Jv+DbX8-*s z9vZu2^65)EKV2C4dT{vMO#`35^vXMTT{Cg->Ct1)d^dRJlb&}cHXc8D_|_rZ^WKIH G^1%P79RflC literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/shades_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/shades_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..157df770acd36cbd49f1fd80da2cd9251ef52626 GIT binary patch literal 1059 zcmW+#U1$(g7(K4lexM&2lQyE;9zwhr%_Om+ZYHP`VOD+#v$`fMEqcj%TE@4cKpKIh z7DaSd*wSx7AQU|WSExp7+o5>2LwnxR=V zn`UZ-R?%u&sYDw}X-XPk5Q7!E=Subuy9^*i@( z+0Yaxc8=Y0pTD>?^y#jFbuV?{tI4j>TPN4t_Rv3_yFVGd16_wZHXr@-@u>-1S^wPJ z+V^JP$L^6Yd#88Kj(@lR)XS@;54xkna{0*2t^pf=@d3Fw*nMEy-@Etjk4Nl!dwp=k z@4LLI-yNFY@y7Fy93Niy@HJ`a!p8lFe>wBY>YIQ6d1>h6-m>Pw7w*I#`^G=qadPnV z#JO4Jl@k+Fmu~dq@AiD)UtK%(%#WWvJA2@_r#D>~pF8x{rHx-4IJ?J2w%mTTKeqkX Uj>pdQe*Mv?@9e*7RR`|*A1UAdR{#J2 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/teeth_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/teeth_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..26b5a555f834884bf75e8c64021893d85eb1fc7a GIT binary patch literal 1064 zcmW+#Uue)(7(LV&v!aqUL5VH~n{@kw)+$%vudp?o3ljYXMsO?8{plfm5TufCnhz04 zQ5gDAccIw!2_+fjOWeJLm4im!6^`Hv=F1*p{r|J_bhiVS?_4g2@8f*u_HB85W6!hg zXvd#e!r1Z|TP|buHnxPRAEr)zz2F=34Sj$Q;)D4>ukb2f%`1I`kK&{GNT1-7_+&oO z7x*H+m@o8%r+Att1rUh91QZ8xBF@B78b~A3m^73C2_nHHP!ysfYNC_~i6YS?QW7MI zB$GrbkRnn{3WX4g(1cV#s~V=DI;azMrjFV`8_~wJp$2FW4W@yrP!&~ErABBJji!;B zph+~DCTf8e(PCPtL>)?LN*Z7ggBfTJ=ER(tqcyNbtTAh70T#r9S*V&imY7-5s zsYA|&S?mV|wWop@O(-@uDjE-hFkZHZgf@btJiKQ2!SKCdczhr4dvoaU!F~Im9>+Lt zU;}fTXKu61_1oMA&R;$M@%QT?dWZ@MAu%KmNx=||!918kM#v1=LslpVg`s#T3Jsw# zG!IQd2x5>2i2y;u32^`ia&Qh}1S1)pQA}VWlQW418fi`wGnmQj%whoxS)4^|U?ZEe zi2_B+DH&j04L8UJ*gzZH23dqfT6BxD1WUB!mShGqnz@-Q!!j+qWm$n0T5&6~25YqD z)?`8-%H$?F;Gn}D@&P{32lqi9;gKHQqddVAJ-Mf@>0{B&yVx^4)3bY)7kHr;_ablb zMsMy-F1YA&mnu-f3a?NdPzTn*>!2D@BWv^;RTFArO)844$k-@Wu)9C@A2AM$evNm>cI^9! zOHYiZ+n;=I_1cA*)rHgH-0L6iI<_?Rf83t?z;TR{K(-W|7@Gz`NbnQ*MI-z&~1;Mym9TT>*Ig#xp>^C{<{CA zH{SZO-16PR_Oa*heP(`i>h0|>|M}aqpU+%;>dgM5r`CR0x%%JM4|d;mVGa-e5AP%G AhX4Qo literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/thumbs_up.gif b/www/js/FCKeditor/editor/images/smiley/msn/thumbs_up.gif new file mode 100644 index 0000000000000000000000000000000000000000..7e8c74627f641e404eee62083dfbb87e8664e119 GIT binary patch literal 989 zcmW+#KWN`Y9DPI4)Fpv9=pf%V&?48UgB1Kzdu)Nf0B*!gAW%bRyY^bi#iLSjfBl7b-^gLyE8jF1_!hpbQ#3PbTw6dFQf zXdaq^5X2x45&?pQ6XF04E18g7scuz@zX4YCM}wCEOP36^NdEy)aKG;=dqhGklI%d!G1wBlA|4c2JQ zt;vKwl*vtUz(I#Q)m{6<(n_pbo5q*FiO+M%L&xswULLn!F}eLp4_OYN{DEvu3YZwV)Q( z;n?! z(22r;Ffa@r28Dp1++frDeXf$9F(f5ap(_6_AUbuJF=PtkX z^ts2Myc#~6`uy~dvtQ3|&5w_^UbsK~`}K_z$Jb{LeYJZ1N65z>EI_TNaT&eTaf@e+=`Q!P1ARvuh6-4a=c@P)BfCWUJ^Q=%q0E{DPF) zOJ#%>)Lr2g`_#kOV-H=+QF9w)deaKwg49F4w1TK8JKgQT<#R5V!{@{KocqwjJA1bb zwa~(!SVVj2w3kY|-r9>eb?Maj?1J;=JY9eb;)1zAr*JAx%_&`ki{hfWNSEM}xMVKT z6}TdRP5Y&rv_*c4W@yrP!&~ErABBJji!;B zph+~DCTf8e(PCPtL>)?LN*Z7ggBfTItPyL>8k&cBF>mH+0T#r9S*V&imY7-SO&8EuiaPyxo24iR*uydTeg=rpJ31ewZ3QcXIm+Cq_Qp@$|%PJ9BT(JD(gm+uMKX z?%xi$BiHQxqr2mg%bR7xrbpL)H~Eb}boh?`l~4W}MqgjO;@*{OXVy&*A0GLyWAM7c znPs~=etvak-IYDVa|09aec!pFb^p2X?Q@sc+<5lj?DDZ=%iKK<66 zuUvU>+vcCXO?SmDhsK|~dA*z&_~rfmtJXw!;P|pVe?7k=9$a;N<1KG~-1^|liT<&^ z-uCW^zL&RdY+YFY#?(O9wNFeBj_iJR==9O6AD!>)d0^jI*Tu2DUtjDQ`uz9(yN*sy cPW8RG_3G^T;g{~)XUm`QH_Wd7qK$3;1Il~_)&Kwi literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif b/www/js/FCKeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0741223de8ddc366826bad1ef5db6e19e938896 GIT binary patch literal 1034 zcmW+#UuYLp82ui!bObFoBPF;7NpVpKjaWro6Q(GV{n>db;W}llm!9hV+dwkbL*z{S z1K!_C#eEdS`a?u<2aU2hE7pCng8NboLSjZ>Gur8H2QJ^aTn^vI`Oe+DZ%^OjgFVtC zw`2t)t7l}jjI`Ux3Z{RZzBIe&gZV%o#YgyPKGLgrg;(=RpTsBlWIoYn@fkjw&-7J% zg|Fr-J;f8A=1GV^05J&R1P*WpM+89tf*}x55P@ijgbEZ;gAz%QfMiHS7GxkBGEoH; zsD?^VK!65PMYO5KRH#nWL7l0i2GIZwrhytoBQ%;us){O9O_iEN6EvA7Y8K7VY?`T6 zv_h+CrBd2ZN>kEAOkiRrG$-a@&dkw*SbznyK#O7#7R_SQw6S1nO>9Xl!ID{`Ww8v) zW|>ySDy*7S8pQ~s8CgV%pokS=aZ((Lv*K8Slzk z)-A~R`uk7c_4Cxg)y_SK`WCNG4bNYA>b28j6T5KW+0MgTpL@~wZo>9s-#qy4-rnwu zul{{yX5-W2^PT>ak8S^bX87Xf{V&~n`QVoE?iZGBe0-xbJv4v&^V@fRcyMNT^wbw! zzioTy(KknzC;nOJJ(Bdm^4cdZ|1tRdMCB!-HH09+ zTH73C6PjvyHV4yM#LEW6LrrQCR>2}HCiLq1NYs2$CKUY z#-CWj==vF5FQe@?x`xH?7eDxN#Rv0&KEg-w(R`#=conbal|I2I@yUFm&+u7%HlOJ$ zd=+2KS9-!zJk65=2t;54ii0>2XW}RU5=4SYphQR%i6)Vv5EW4qr6foaNhXPsAz37w zWJ-lpk!n&YgiwSgqypO1Fa^~?ov1T))Bp{l!8A}KG>S&kNL8qcs;N>FG>InDM9t7F znoTpcLaS&styH27r8FfCFo?knGzW8H&dkvQEQkfOK#Q;_7R_SQw6Vn0n%EL7i6yf{ z%djk#%`&aRs#rCvG{PuGGqL~$QeXuv4#i1vRvb$}2~vWUz!FiSlxQWgD2hr^E6S2k zl9Xg6v1F7iC0ofX6{Sk4Rw@foD1}zYH9K2p2Rfl^gbZL124f&27=_Uo+3cnY)tWC% zU=k){A~TqU*_g=+R$(<(l5It{yi6|hW^xZXy+)g-ZEXUzW-bzt1j&$y3}itzWTFC9 zPz{wWN6m5%c!)-W2Pl)y5h&|J~8miIcdYJ+>dw z4RoHvzOE||UV3I>aB1ed?TgoJy!-Xn`e*K6J^Djm@7Ul~Bc1a@HrRdro!bshJazB0 zr{@k2^_<_8COZzyzPtDQ?l128bKD2bK=fI8I4<9|pSPp%%AN4WNzQYZ^s6QAD-R%?S{wt-q`!#*In1%_Iuycb1!YY=gq&S7Y0VoPWjd8 z=iQ?h&(3}}`RS&#b$I5XpAMa!wSkZJZ+_yH!O|edsbh*WoF>W*oTi?c3uA# L=^WkAfo=Z-Q#A*W literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/images/spacer.gif b/www/js/FCKeditor/editor/images/spacer.gif new file mode 100644 index 0000000000000000000000000000000000000000..5bfd67a2d6f72ac3a55cbfcea5866e841d22f5d9 GIT binary patch literal 43 mcmZ?wbhEHbWMp7uXkdT>#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 literal 0 HcmV?d00001 diff --git a/www/js/FCKeditor/editor/js/fckadobeair.js b/www/js/FCKeditor/editor/js/fckadobeair.js new file mode 100644 index 0000000..468164c --- /dev/null +++ b/www/js/FCKeditor/editor/js/fckadobeair.js @@ -0,0 +1,176 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Compatibility code for Adobe AIR. + */ + +if ( FCKBrowserInfo.IsAIR ) +{ + var FCKAdobeAIR = (function() + { + /* + * ### Private functions. + */ + + var getDocumentHead = function( doc ) + { + var head ; + var heads = doc.getElementsByTagName( 'head' ) ; + + if( heads && heads[0] ) + head = heads[0] ; + else + { + head = doc.createElement( 'head' ) ; + doc.documentElement.insertBefore( head, doc.documentElement.firstChild ) ; + } + + return head ; + } ; + + /* + * ### Public interface. + */ + return { + FCKeditorAPI_Evaluate : function( parentWindow, script ) + { + // TODO : This one doesn't work always. The parent window will + // point to an anonymous function in this window. If this + // window is destroyied the parent window will be pointing to + // an invalid reference. + + // Evaluate the script in this window. + eval( script ) ; + + // Point the FCKeditorAPI property of the parent window to the + // local reference. + parentWindow.FCKeditorAPI = window.FCKeditorAPI ; + }, + + EditingArea_Start : function( doc, html ) + { + // Get the HTML for the . + var headInnerHtml = html.match( /([\s\S]*)<\/head>/i )[1] ; + + if ( headInnerHtml && headInnerHtml.length > 0 ) + { + // Inject the HTML inside a
. + // Do that before getDocumentHead because WebKit moves + // elements to the at this point. + var div = doc.createElement( 'div' ) ; + div.innerHTML = headInnerHtml ; + + // Move the
nodes to . + FCKDomTools.MoveChildren( div, getDocumentHead( doc ) ) ; + } + + doc.body.innerHTML = html.match( /([\s\S]*)<\/body>/i )[1] ; + + //prevent clicking on hyperlinks and navigating away + doc.addEventListener('click', function( ev ) + { + ev.preventDefault() ; + ev.stopPropagation() ; + }, true ) ; + }, + + Panel_Contructor : function( doc, baseLocation ) + { + var head = getDocumentHead( doc ) ; + + // Set the href. + head.appendChild( doc.createElement('base') ).href = baseLocation ; + + doc.body.style.margin = '0px' ; + doc.body.style.padding = '0px' ; + }, + + ToolbarSet_GetOutElement : function( win, outMatch ) + { + var toolbarTarget = win.parent ; + + var targetWindowParts = outMatch[1].split( '.' ) ; + while ( targetWindowParts.length > 0 ) + { + var part = targetWindowParts.shift() ; + if ( part.length > 0 ) + toolbarTarget = toolbarTarget[ part ] ; + } + + toolbarTarget = toolbarTarget.document.getElementById( outMatch[2] ) ; + }, + + ToolbarSet_InitOutFrame : function( doc ) + { + var head = getDocumentHead( doc ) ; + + head.appendChild( doc.createElement('base') ).href = window.document.location ; + + var targetWindow = doc.defaultView; + + targetWindow.adjust = function() + { + targetWindow.frameElement.height = doc.body.scrollHeight; + } ; + + targetWindow.onresize = targetWindow.adjust ; + targetWindow.setTimeout( targetWindow.adjust, 0 ) ; + + doc.body.style.overflow = 'hidden'; + doc.body.innerHTML = document.getElementById( 'xToolbarSpace' ).innerHTML ; + } + } ; + })(); + + /* + * ### Overrides + */ + ( function() + { + // Save references for override reuse. + var _Original_FCKPanel_Window_OnFocus = FCKPanel_Window_OnFocus ; + var _Original_FCKPanel_Window_OnBlur = FCKPanel_Window_OnBlur ; + var _Original_FCK_StartEditor = FCK.StartEditor ; + + FCKPanel_Window_OnFocus = function( e, panel ) + { + // Call the original implementation. + _Original_FCKPanel_Window_OnFocus.call( this, e, panel ) ; + + if ( panel._focusTimer ) + clearTimeout( panel._focusTimer ) ; + } + + FCKPanel_Window_OnBlur = function( e, panel ) + { + // Delay the execution of the original function. + panel._focusTimer = FCKTools.SetTimeout( _Original_FCKPanel_Window_OnBlur, 100, this, [ e, panel ] ) ; + } + + FCK.StartEditor = function() + { + // Force pointing to the CSS files instead of using the inline CSS cached styles. + window.FCK_InternalCSS = FCKConfig.BasePath + 'css/fck_internal.css' ; + window.FCK_ShowTableBordersCSS = FCKConfig.BasePath + 'css/fck_showtableborders_gecko.css' ; + + _Original_FCK_StartEditor.apply( this, arguments ) ; + } + })(); +} diff --git a/www/js/FCKeditor/editor/js/fckeditorcode_gecko.js b/www/js/FCKeditor/editor/js/fckeditorcode_gecko.js new file mode 100644 index 0000000..ca5ac6b --- /dev/null +++ b/www/js/FCKeditor/editor/js/fckeditorcode_gecko.js @@ -0,0 +1,109 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * This file has been compressed for better performance. The original source + * can be found at "editor/_source". + */ + +var FCK_STATUS_NOTLOADED=window.parent.FCK_STATUS_NOTLOADED=0;var FCK_STATUS_ACTIVE=window.parent.FCK_STATUS_ACTIVE=1;var FCK_STATUS_COMPLETE=window.parent.FCK_STATUS_COMPLETE=2;var FCK_TRISTATE_OFF=window.parent.FCK_TRISTATE_OFF=0;var FCK_TRISTATE_ON=window.parent.FCK_TRISTATE_ON=1;var FCK_TRISTATE_DISABLED=window.parent.FCK_TRISTATE_DISABLED=-1;var FCK_UNKNOWN=window.parent.FCK_UNKNOWN=-9;var FCK_TOOLBARITEM_ONLYICON=window.parent.FCK_TOOLBARITEM_ONLYICON=0;var FCK_TOOLBARITEM_ONLYTEXT=window.parent.FCK_TOOLBARITEM_ONLYTEXT=1;var FCK_TOOLBARITEM_ICONTEXT=window.parent.FCK_TOOLBARITEM_ICONTEXT=2;var FCK_EDITMODE_WYSIWYG=window.parent.FCK_EDITMODE_WYSIWYG=0;var FCK_EDITMODE_SOURCE=window.parent.FCK_EDITMODE_SOURCE=1;var FCK_IMAGES_PATH='images/';var FCK_SPACER_PATH='images/spacer.gif';var CTRL=1000;var SHIFT=2000;var ALT=4000;var FCK_STYLE_BLOCK=0;var FCK_STYLE_INLINE=1;var FCK_STYLE_OBJECT=2; +String.prototype.Contains=function(A){return (this.indexOf(A)>-1);};String.prototype.Equals=function(){var A=arguments;if (A.length==1&&A[0].pop) A=A[0];for (var i=0;iC) return false;if (B){var E=new RegExp(A+'$','i');return E.test(this);}else return (D==0||this.substr(C-D,D)==A);};String.prototype.Remove=function(A,B){var s='';if (A>0) s=this.substring(0,A);if (A+B=7),IsIE6:/*@cc_on!@*/false&&(parseInt(s.match(/msie (\d+)/)[1],10)>=6),IsSafari:s.Contains(' applewebkit/'),IsOpera:!!window.opera,IsAIR:s.Contains(' adobeair/'),IsMac:s.Contains('macintosh')};(function(A){A.IsGecko=(navigator.product=='Gecko')&&!A.IsSafari&&!A.IsOpera;A.IsGeckoLike=(A.IsGecko||A.IsSafari||A.IsOpera);if (A.IsGecko){var B=s.match(/rv:(\d+\.\d+)/);var C=B&&parseFloat(B[1]);if (C){A.IsGecko10=(C<1.8);A.IsGecko19=(C>1.8);}}})(FCKBrowserInfo); +var FCKURLParams={};(function(){var A=document.location.search.substr(1).split('&');for (var i=0;i';if (!FCKRegexLib.HtmlOpener.test(A)) A=''+A+'';if (!FCKRegexLib.HeadOpener.test(A)) A=A.replace(FCKRegexLib.HtmlOpener,'$&');return A;}else{var B=FCKConfig.DocType+'0&&!FCKRegexLib.Html4DocType.test(FCKConfig.DocType)) B+=' style="overflow-y: scroll"';B+='>'+A+'';return B;}},ConvertToDataFormat:function(A,B,C,D){var E=FCKXHtml.GetXHTML(A,!B,D);if (C&&FCKRegexLib.EmptyOutParagraph.test(E)) return '';return E;},FixHtml:function(A){return A;}}; +var FCK={Name:FCKURLParams['InstanceName'],Status:0,EditMode:0,Toolbar:null,HasFocus:false,DataProcessor:new FCKDataProcessor(),GetInstanceObject:(function(){var w=window;return function(name){return w[name];}})(),AttachToOnSelectionChange:function(A){this.Events.AttachEvent('OnSelectionChange',A);},GetLinkedFieldValue:function(){return this.LinkedField.value;},GetParentForm:function(){return this.LinkedField.form;},StartupValue:'',IsDirty:function(){if (this.EditMode==1) return (this.StartupValue!=this.EditingArea.Textarea.value);else{if (!this.EditorDocument) return false;return (this.StartupValue!=this.EditorDocument.body.innerHTML);}},ResetIsDirty:function(){if (this.EditMode==1) this.StartupValue=this.EditingArea.Textarea.value;else if (this.EditorDocument.body) this.StartupValue=this.EditorDocument.body.innerHTML;},StartEditor:function(){this.TempBaseTag=FCKConfig.BaseHref.length>0?'':'';var A=FCK.KeystrokeHandler=new FCKKeystrokeHandler();A.OnKeystroke=_FCK_KeystrokeHandler_OnKeystroke;A.SetKeystrokes(FCKConfig.Keystrokes);if (FCKBrowserInfo.IsIE7){if ((CTRL+86) in A.Keystrokes) A.SetKeystrokes([CTRL+86,true]);if ((SHIFT+45) in A.Keystrokes) A.SetKeystrokes([SHIFT+45,true]);};A.SetKeystrokes([CTRL+8,true]);this.EditingArea=new FCKEditingArea(document.getElementById('xEditingArea'));this.EditingArea.FFSpellChecker=FCKConfig.FirefoxSpellChecker;this.SetData(this.GetLinkedFieldValue(),true);FCKTools.AddEventListener(document,"keydown",this._TabKeyHandler);this.AttachToOnSelectionChange(_FCK_PaddingNodeListener);if (FCKBrowserInfo.IsGecko) this.AttachToOnSelectionChange(this._ExecCheckEmptyBlock);},Focus:function(){FCK.EditingArea.Focus();},SetStatus:function(A){this.Status=A;if (A==1){FCKFocusManager.AddWindow(window,true);if (FCKBrowserInfo.IsIE) FCKFocusManager.AddWindow(window.frameElement,true);if (FCKConfig.StartupFocus) FCK.Focus();};this.Events.FireEvent('OnStatusChange',A);},FixBody:function(){var A=FCKConfig.EnterMode;if (A!='p'&&A!='div') return;var B=this.EditorDocument;if (!B) return;var C=B.body;if (!C) return;FCKDomTools.TrimNode(C);var D=C.firstChild;var E;while (D){var F=false;switch (D.nodeType){case 1:var G=D.nodeName.toLowerCase();if (!FCKListsLib.BlockElements[G]&&G!='li'&&!D.getAttribute('_fckfakelement')&&D.getAttribute('_moz_dirty')==null) F=true;break;case 3:if (E||D.nodeValue.Trim().length>0) F=true;break;case 8:if (E) F=true;break;};if (F){var H=D.parentNode;if (!E) E=H.insertBefore(B.createElement(A),D);E.appendChild(H.removeChild(D));D=E.nextSibling;}else{if (E){FCKDomTools.TrimNode(E);E=null;};D=D.nextSibling;}};if (E) FCKDomTools.TrimNode(E);},GetData:function(A){FCK.Events.FireEvent("OnBeforeGetData");if (FCK.EditMode==1) return FCK.EditingArea.Textarea.value;this.FixBody();var B=FCK.EditorDocument;if (!B) return null;var C=FCKConfig.FullPage;var D=FCK.DataProcessor.ConvertToDataFormat(C?B.documentElement:B.body,!C,FCKConfig.IgnoreEmptyParagraphValue,A);D=FCK.ProtectEventsRestore(D);if (FCKBrowserInfo.IsIE) D=D.replace(FCKRegexLib.ToReplace,'$1');if (C){if (FCK.DocTypeDeclaration&&FCK.DocTypeDeclaration.length>0) D=FCK.DocTypeDeclaration+'\n'+D;if (FCK.XmlDeclaration&&FCK.XmlDeclaration.length>0) D=FCK.XmlDeclaration+'\n'+D;};D=FCKConfig.ProtectedSource.Revert(D);setTimeout(function() { FCK.Events.FireEvent("OnAfterGetData");},0);return D;},UpdateLinkedField:function(){var A=FCK.GetXHTML(FCKConfig.FormatOutput);if (FCKConfig.HtmlEncodeOutput) A=FCKTools.HTMLEncode(A);FCK.LinkedField.value=A;FCK.Events.FireEvent('OnAfterLinkedFieldUpdate');},RegisteredDoubleClickHandlers:{},OnDoubleClick:function(A){var B=FCK.RegisteredDoubleClickHandlers[A.tagName.toUpperCase()];if (B){for (var i=0;i0?'|ABBR|XML|EMBED|OBJECT':'ABBR|XML|EMBED|OBJECT';var C;if (B.length>0){C=new RegExp('<('+B+')(?!\w|:)','gi');A=A.replace(C,'','gi');A=A.replace(C,'<\/FCK:$1>');};B='META';if (FCKBrowserInfo.IsIE) B+='|HR';C=new RegExp('<(('+B+')(?=\\s|>|/)[\\s\\S]*?)/?>','gi');A=A.replace(C,'');return A;},SetData:function(A,B){this.EditingArea.Mode=FCK.EditMode;if (FCKBrowserInfo.IsIE&&FCK.EditorDocument){FCK.EditorDocument.detachEvent("onselectionchange",Doc_OnSelectionChange);};FCKTempBin.Reset();FCK.Selection.Release();if (FCK.EditMode==0){this._ForceResetIsDirty=(B===true);A=FCKConfig.ProtectedSource.Protect(A);A=FCK.DataProcessor.ConvertToHtml(A);A=A.replace(FCKRegexLib.InvalidSelfCloseTags,'$1>');A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);if (FCK.TempBaseTag.length>0&&!FCKRegexLib.HasBaseTag.test(A)) A=A.replace(FCKRegexLib.HeadOpener,'$&'+FCK.TempBaseTag);var C='';if (!FCKConfig.FullPage) C+=_FCK_GetEditorAreaStyleTags();if (FCKBrowserInfo.IsIE) C+=FCK._GetBehaviorsStyle();else if (FCKConfig.ShowBorders) C+=FCKTools.GetStyleHtml(FCK_ShowTableBordersCSS,true);C+=FCKTools.GetStyleHtml(FCK_InternalCSS,true);A=A.replace(FCKRegexLib.HeadCloser,C+'$&');this.EditingArea.OnLoad=_FCK_EditingArea_OnLoad;this.EditingArea.Start(A);}else{FCK.EditorWindow=null;FCK.EditorDocument=null;FCKDomTools.PaddingNode=null;this.EditingArea.OnLoad=null;this.EditingArea.Start(A);this.EditingArea.Textarea._FCKShowContextMenu=true;FCK.EnterKeyHandler=null;if (B) this.ResetIsDirty();FCK.KeystrokeHandler.AttachToElement(this.EditingArea.Textarea);this.EditingArea.Textarea.focus();FCK.Events.FireEvent('OnAfterSetHTML');};if (window.onresize) window.onresize();},RedirectNamedCommands:{},ExecuteNamedCommand:function(A,B,C,D){if (!D) FCKUndo.SaveUndoStep();if (!C&&FCK.RedirectNamedCommands[A]!=null) FCK.ExecuteRedirectedNamedCommand(A,B);else{FCK.Focus();FCK.EditorDocument.execCommand(A,false,B);FCK.Events.FireEvent('OnSelectionChange');};if (!D) FCKUndo.SaveUndoStep();},GetNamedCommandState:function(A){try{if (FCKBrowserInfo.IsSafari&&FCK.EditorWindow&&A.IEquals('Paste')) return 0;if (!FCK.EditorDocument.queryCommandEnabled(A)) return -1;else{return FCK.EditorDocument.queryCommandState(A)?1:0;}}catch (e){return 0;}},GetNamedCommandValue:function(A){var B='';var C=FCK.GetNamedCommandState(A);if (C==-1) return null;try{B=this.EditorDocument.queryCommandValue(A);}catch(e) {};return B?B:'';},Paste:function(A){if (FCK.Status!=2||!FCK.Events.FireEvent('OnPaste')) return false;return A||FCK._ExecPaste();},PasteFromWord:function(){FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteFromWord,'dialog/fck_paste.html',400,330,'Word');},Preview:function(){var A;if (FCKConfig.FullPage){if (FCK.TempBaseTag.length>0) A=FCK.TempBaseTag+FCK.GetXHTML();else A=FCK.GetXHTML();}else{A=FCKConfig.DocType+''+FCK.TempBaseTag+''+FCKLang.Preview+''+_FCK_GetEditorAreaStyleTags()+''+FCK.GetXHTML()+'';};var B=FCKConfig.ScreenWidth*0.8;var C=FCKConfig.ScreenHeight*0.7;var D=(FCKConfig.ScreenWidth-B)/2;var E='';if (FCK_IS_CUSTOM_DOMAIN&&FCKBrowserInfo.IsIE){window._FCKHtmlToLoad=A;E='javascript:void( (function(){document.open() ;document.domain="'+document.domain+'" ;document.write( window.opener._FCKHtmlToLoad );document.close() ;window.opener._FCKHtmlToLoad = null ;})() )';};var F=window.open(E,null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+B+',height='+C+',left='+D);if (!FCK_IS_CUSTOM_DOMAIN||!FCKBrowserInfo.IsIE){F.document.write(A);F.document.close();}},SwitchEditMode:function(A){var B=(FCK.EditMode==0);var C=FCK.IsDirty();var D;if (B){FCKCommands.GetCommand('ShowBlocks').SaveState();if (!A&&FCKBrowserInfo.IsIE) FCKUndo.SaveUndoStep();D=FCK.GetXHTML(FCKConfig.FormatSource);if (FCKBrowserInfo.IsIE) FCKTempBin.ToHtml();if (D==null) return false;}else D=this.EditingArea.Textarea.value;FCK.EditMode=B?1:0;FCK.SetData(D,!C);FCK.Focus();FCKTools.RunFunction(FCK.ToolbarSet.RefreshModeState,FCK.ToolbarSet);return true;},InsertElement:function(A){if (typeof A=='string') A=this.EditorDocument.createElement(A);var B=A.nodeName.toLowerCase();FCKSelection.Restore();var C=new FCKDomRange(this.EditorWindow);C.MoveToSelection();C.DeleteContents();if (FCKListsLib.BlockElements[B]!=null){if (C.StartBlock){if (C.CheckStartOfBlock()) C.MoveToPosition(C.StartBlock,3);else if (C.CheckEndOfBlock()) C.MoveToPosition(C.StartBlock,4);else C.SplitBlock();};C.InsertNode(A);var D=FCKDomTools.GetNextSourceElement(A,false,null,['hr','br','param','img','area','input'],true);if (!D&&FCKConfig.EnterMode!='br'){D=this.EditorDocument.body.appendChild(this.EditorDocument.createElement(FCKConfig.EnterMode));if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(D);};if (FCKListsLib.EmptyElements[B]==null) C.MoveToElementEditStart(A);else if (D) C.MoveToElementEditStart(D);else C.MoveToPosition(A,4);if (FCKBrowserInfo.IsGeckoLike){if (D) FCKDomTools.ScrollIntoView(D,false);FCKDomTools.ScrollIntoView(A,false);}}else{C.InsertNode(A);C.SetStart(A,4);C.SetEnd(A,4);};C.Select();C.Release();this.Focus();return A;},_InsertBlockElement:function(A){},_IsFunctionKey:function(A){if (A>=16&&A<=20) return true;if (A==27||(A>=33&&A<=40)) return true;if (A==45) return true;return false;},_KeyDownListener:function(A){if (!A) A=FCK.EditorWindow.event;if (FCK.EditorWindow){if (!FCK._IsFunctionKey(A.keyCode)&&!(A.ctrlKey||A.metaKey)&&!(A.keyCode==46)) FCK._KeyDownUndo();};return true;},_KeyDownUndo:function(){if (!FCKUndo.Typing){FCKUndo.SaveUndoStep();FCKUndo.Typing=true;FCK.Events.FireEvent("OnSelectionChange");};FCKUndo.TypesCount++;FCKUndo.Changed=1;if (FCKUndo.TypesCount>FCKUndo.MaxTypes){FCKUndo.TypesCount=0;FCKUndo.SaveUndoStep();}},_TabKeyHandler:function(A){if (!A) A=window.event;var B=A.keyCode;if (B==9&&FCK.EditMode!=0){if (FCKBrowserInfo.IsIE){var C=document.selection.createRange();if (C.parentElement()!=FCK.EditingArea.Textarea) return true;C.text='\t';C.select();}else{var a=[];var D=FCK.EditingArea.Textarea;var E=D.selectionStart;var F=D.selectionEnd;a.push(D.value.substr(0,E));a.push('\t');a.push(D.value.substr(F));D.value=a.join('');D.setSelectionRange(E+1,E+1);};if (A.preventDefault) return A.preventDefault();return A.returnValue=false;};return true;}};FCK.Events=new FCKEvents(FCK);FCK.GetHTML=FCK.GetXHTML=FCK.GetData;FCK.SetHTML=FCK.SetData;FCK.InsertElementAndGetIt=FCK.CreateElement=FCK.InsertElement;function _FCK_ProtectEvents_ReplaceTags(A){return A.replace(FCKRegexLib.EventAttributes,_FCK_ProtectEvents_ReplaceEvents);};function _FCK_ProtectEvents_ReplaceEvents(A,B){return ' '+B+'_fckprotectedatt="'+encodeURIComponent(A)+'"';};function _FCK_ProtectEvents_RestoreEvents(A,B){return decodeURIComponent(B);};function _FCK_MouseEventsListener(A){if (!A) A=window.event;if (A.type=='mousedown') FCK.MouseDownFlag=true;else if (A.type=='mouseup') FCK.MouseDownFlag=false;else if (A.type=='mousemove') FCK.Events.FireEvent('OnMouseMove',A);};function _FCK_PaddingNodeListener(){if (FCKConfig.EnterMode.IEquals('br')) return;FCKDomTools.EnforcePaddingNode(FCK.EditorDocument,FCKConfig.EnterMode);if (!FCKBrowserInfo.IsIE&&FCKDomTools.PaddingNode){var A=FCKSelection.GetSelection();if (A&&A.rangeCount==1){var B=A.getRangeAt(0);if (B.collapsed&&B.startContainer==FCK.EditorDocument.body&&B.startOffset==0){B.selectNodeContents(FCKDomTools.PaddingNode);B.collapse(true);A.removeAllRanges();A.addRange(B);}}}else if (FCKDomTools.PaddingNode){var C=FCKSelection.GetParentElement();var D=FCKDomTools.PaddingNode;if (C&&C.nodeName.IEquals('body')){if (FCK.EditorDocument.body.childNodes.length==1&&FCK.EditorDocument.body.firstChild==D){if (FCKSelection._GetSelectionDocument(FCK.EditorDocument.selection)!=FCK.EditorDocument) return;var B=FCK.EditorDocument.body.createTextRange();var F=false;if (!D.childNodes.firstChild){D.appendChild(FCKTools.GetElementDocument(D).createTextNode('\ufeff'));F=true;};B.moveToElementText(D);B.select();if (F) B.pasteHTML('');}}}};function _FCK_EditingArea_OnLoad(){FCK.EditorWindow=FCK.EditingArea.Window;FCK.EditorDocument=FCK.EditingArea.Document;if (FCKBrowserInfo.IsIE) FCKTempBin.ToElements();FCK.InitializeBehaviors();FCK.MouseDownFlag=false;FCKTools.AddEventListener(FCK.EditorDocument,'mousemove',_FCK_MouseEventsListener);FCKTools.AddEventListener(FCK.EditorDocument,'mousedown',_FCK_MouseEventsListener);FCKTools.AddEventListener(FCK.EditorDocument,'mouseup',_FCK_MouseEventsListener);if (FCKBrowserInfo.IsSafari){FCKTools.AddEventListener(FCK.EditorDocument,'paste',function(evt){var A=new FCKDomRange(FCK.EditorWindow);var B=FCK.EditorDocument.createTextNode('\ufeff');var C=FCK.EditorDocument.createElement('a');C.id='fck_paste_padding';C.innerHTML='';A.MoveToSelection();A.DeleteContents();A.InsertNode(B);A.Collapse();A.InsertNode(C);A.MoveToPosition(C,3);A.Select();setTimeout(function(){B.parentNode.removeChild(B);C=FCK.EditorDocument.getElementById('fck_paste_padding');C.parentNode.removeChild(C);},0);});};if (FCKBrowserInfo.IsSafari){var D=function(evt){if (!(evt.ctrlKey||evt.metaKey)) return;if (FCK.EditMode!=0) return;switch (evt.keyCode){case 89:FCKUndo.Redo();break;case 90:FCKUndo.Undo();break;}};FCKTools.AddEventListener(FCK.EditorDocument,'keyup',D);};FCK.EnterKeyHandler=new FCKEnterKey(FCK.EditorWindow,FCKConfig.EnterMode,FCKConfig.ShiftEnterMode,FCKConfig.TabSpaces);FCK.KeystrokeHandler.AttachToElement(FCK.EditorDocument);if (FCK._ForceResetIsDirty) FCK.ResetIsDirty();if (FCKBrowserInfo.IsIE&&FCK.HasFocus) FCK.EditorDocument.body.setActive();FCK.OnAfterSetHTML();FCKCommands.GetCommand('ShowBlocks').RestoreState();if (FCK.Status!=0) return;FCK.SetStatus(1);};function _FCK_GetEditorAreaStyleTags(){return FCKTools.GetStyleHtml(FCKConfig.EditorAreaCSS)+FCKTools.GetStyleHtml(FCKConfig.EditorAreaStyles);};function _FCK_KeystrokeHandler_OnKeystroke(A,B){if (FCK.Status!=2) return false;if (FCK.EditMode==0){switch (B){case 'Paste':return!FCK.Paste();case 'Cut':FCKUndo.SaveUndoStep();return false;}}else{if (B.Equals('Paste','Undo','Redo','SelectAll','Cut')) return false;};var C=FCK.Commands.GetCommand(B);if (C.GetState()==-1) return false;return (C.Execute.apply(C,FCKTools.ArgumentsToArray(arguments,2))!==false);};(function(){var A=window.parent.document;var B=A.getElementById(FCK.Name);var i=0;while (B||i==0){if (B&&B.tagName.toLowerCase().Equals('input','textarea')){FCK.LinkedField=B;break;};B=A.getElementsByName(FCK.Name)[i++];}})();var FCKTempBin={Elements:[],AddElement:function(A){var B=this.Elements.length;this.Elements[B]=A;return B;},RemoveElement:function(A){var e=this.Elements[A];this.Elements[A]=null;return e;},Reset:function(){var i=0;while (i '+this.Elements[i].outerHTML+'
';this.Elements[i].isHtml=true;}},ToElements:function(){var A=FCK.EditorDocument.createElement('div');for (var i=0;i40) return;};var C=function(H){if (H.nodeType!=1) return false;var D=H.tagName.toLowerCase();return (FCKListsLib.BlockElements[D]||FCKListsLib.EmptyElements[D]);};var E=function(){var F=FCKSelection.GetSelection();var G=F.getRangeAt(0);if (!G||!G.collapsed) return;var H=G.endContainer;if (H.nodeType!=3) return;if (H.nodeValue.length!=G.endOffset) return;var I=H.parentNode.tagName.toLowerCase();if (!(I=='a'||(!FCKBrowserInfo.IsOpera&&String(H.parentNode.contentEditable)=='false')||(!(FCKListsLib.BlockElements[I]||FCKListsLib.NonEmptyBlockElements[I])&&B==35))) return;var J=FCKTools.GetNextTextNode(H,H.parentNode,C);if (J) return;G=FCK.EditorDocument.createRange();J=FCKTools.GetNextTextNode(H,H.parentNode.parentNode,C);if (J){if (FCKBrowserInfo.IsOpera&&B==37) return;G.setStart(J,0);G.setEnd(J,0);}else{while (H.parentNode&&H.parentNode!=FCK.EditorDocument.body&&H.parentNode!=FCK.EditorDocument.documentElement&&H==H.parentNode.lastChild&&(!FCKListsLib.BlockElements[H.parentNode.tagName.toLowerCase()]&&!FCKListsLib.NonEmptyBlockElements[H.parentNode.tagName.toLowerCase()])) H=H.parentNode;if (FCKListsLib.BlockElements[I]||FCKListsLib.EmptyElements[I]||H==FCK.EditorDocument.body){G.setStart(H,H.childNodes.length);G.setEnd(H,H.childNodes.length);}else{var K=H.nextSibling;while (K){if (K.nodeType!=1){K=K.nextSibling;continue;};var L=K.tagName.toLowerCase();if (FCKListsLib.BlockElements[L]||FCKListsLib.EmptyElements[L]||FCKListsLib.NonEmptyBlockElements[L]) break;K=K.nextSibling;};var M=FCK.EditorDocument.createTextNode('');if (K) H.parentNode.insertBefore(M,K);else H.parentNode.appendChild(M);G.setStart(M,0);G.setEnd(M,0);}};F.removeAllRanges();F.addRange(G);FCK.Events.FireEvent("OnSelectionChange");};setTimeout(E,1);};this.ExecOnSelectionChangeTimer=function(){if (FCK.LastOnChangeTimer) window.clearTimeout(FCK.LastOnChangeTimer);FCK.LastOnChangeTimer=window.setTimeout(FCK.ExecOnSelectionChange,100);};this.EditorDocument.addEventListener('mouseup',this.ExecOnSelectionChange,false);this.EditorDocument.addEventListener('keyup',this.ExecOnSelectionChangeTimer,false);this._DblClickListener=function(e){FCK.OnDoubleClick(e.target);e.stopPropagation();};this.EditorDocument.addEventListener('dblclick',this._DblClickListener,true);this.EditorDocument.addEventListener('keydown',this._KeyDownListener,false);if (FCKBrowserInfo.IsGecko){this.EditorWindow.addEventListener('dragdrop',this._ExecDrop,true);}else if (FCKBrowserInfo.IsSafari){this.EditorDocument.addEventListener('dragover',function (evt){ if (!FCK.MouseDownFlag&&FCK.Config.ForcePasteAsPlainText) evt.returnValue=false;},true);this.EditorDocument.addEventListener('drop',this._ExecDrop,true);this.EditorDocument.addEventListener('mousedown',function(ev){var N=ev.srcElement;if (N.nodeName.IEquals('IMG','HR','INPUT','TEXTAREA','SELECT')){FCKSelection.SelectNode(N);}},true);this.EditorDocument.addEventListener('mouseup',function(ev){if (ev.srcElement.nodeName.IEquals('INPUT','TEXTAREA','SELECT')) ev.preventDefault()},true);this.EditorDocument.addEventListener('click',function(ev){if (ev.srcElement.nodeName.IEquals('INPUT','TEXTAREA','SELECT')) ev.preventDefault()},true);};if (FCKBrowserInfo.IsGecko||FCKBrowserInfo.IsOpera){this.EditorDocument.addEventListener('keypress',this._ExecCheckCaret,false);this.EditorDocument.addEventListener('click',this._ExecCheckCaret,false);};FCK.ContextMenu._InnerContextMenu.SetMouseClickWindow(FCK.EditorWindow);FCK.ContextMenu._InnerContextMenu.AttachToElement(FCK.EditorDocument);};FCK.MakeEditable=function(){this.EditingArea.MakeEditable();};function Document_OnContextMenu(e){if (!e.target._FCKShowContextMenu) e.preventDefault();};document.oncontextmenu=Document_OnContextMenu;FCK._BaseGetNamedCommandState=FCK.GetNamedCommandState;FCK.GetNamedCommandState=function(A){switch (A){case 'Unlink':return FCKSelection.HasAncestorNode('A')?0:-1;default:return FCK._BaseGetNamedCommandState(A);}};FCK.RedirectNamedCommands={Print:true,Paste:true};FCK.ExecuteRedirectedNamedCommand=function(A,B){switch (A){case 'Print':FCK.EditorWindow.print();break;case 'Paste':try{if (FCKBrowserInfo.IsSafari) throw '';if (FCK.Paste()) FCK.ExecuteNamedCommand('Paste',null,true);}catch (e) {if (FCKConfig.ForcePasteAsPlainText) FCK.PasteAsPlainText();else FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.Paste,'dialog/fck_paste.html',400,330,'Security');};break;default:FCK.ExecuteNamedCommand(A,B);}};FCK._ExecPaste=function(){FCKUndo.SaveUndoStep();if (FCKConfig.ForcePasteAsPlainText){FCK.PasteAsPlainText();return false;};return true;};FCK.InsertHtml=function(A){var B=FCK.EditorDocument,range;A=FCKConfig.ProtectedSource.Protect(A);A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);FCKUndo.SaveUndoStep();if (FCKBrowserInfo.IsGecko){A=A.replace(/ $/,'$&');var C=new FCKDocumentFragment(this.EditorDocument);C.AppendHtml(A);var D=C.RootNode.lastChild;range=new FCKDomRange(this.EditorWindow);range.MoveToSelection();var E=C.RootNode.firstChild;while (E&&E.nodeType!=1) E=E.nextSibling;if (E&&FCKListsLib.BlockElements[E.nodeName.toLowerCase()]) range.SplitBlock();range.DeleteContents();range.InsertNode(C.RootNode);range.MoveToPosition(D,4);}else B.execCommand('inserthtml',false,A);this.Focus();if (!range){range=new FCKDomRange(this.EditorWindow);range.MoveToSelection();};var F=range.CreateBookmark();FCKDocumentProcessor.Process(B);try{range.MoveToBookmark(F);range.Select();}catch (e) {};this.Events.FireEvent("OnSelectionChange");};FCK.PasteAsPlainText=function(){FCKTools.RunFunction(FCKDialog.OpenDialog,FCKDialog,['FCKDialog_Paste',FCKLang.PasteAsText,'dialog/fck_paste.html',400,330,'PlainText']);};FCK.GetClipboardHTML=function(){return '';};FCK.CreateLink=function(A,B){var C=[];if (FCKSelection.GetSelection().isCollapsed) return C;FCK.ExecuteNamedCommand('Unlink',null,false,!!B);if (A.length>0){var D='javascript:void(0);/*'+(new Date().getTime())+'*/';FCK.ExecuteNamedCommand('CreateLink',D,false,!!B);var E=this.EditorDocument.evaluate("//a[@href='"+D+"']",this.EditorDocument.body,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for (var i=0;i0&&!isNaN(E)) this.PageConfig[D]=parseFloat(E);else this.PageConfig[D]=E;}};function FCKConfig_LoadPageConfig(){var A=FCKConfig.PageConfig;for (var B in A) FCKConfig[B]=A[B];};function FCKConfig_PreProcess(){var A=FCKConfig;if (A.AllowQueryStringDebug){try{if ((/fckdebug=true/i).test(window.top.location.search)) A.Debug=true;}catch (e) { }};if (!A.PluginsPath.EndsWith('/')) A.PluginsPath+='/';var B=A.ToolbarComboPreviewCSS;if (!B||B.length==0) A.ToolbarComboPreviewCSS=A.EditorAreaCSS;A.RemoveAttributesArray=(A.RemoveAttributes||'').split(',');if (!FCKConfig.SkinEditorCSS||FCKConfig.SkinEditorCSS.length==0) FCKConfig.SkinEditorCSS=FCKConfig.SkinPath+'fck_editor.css';if (!FCKConfig.SkinDialogCSS||FCKConfig.SkinDialogCSS.length==0) FCKConfig.SkinDialogCSS=FCKConfig.SkinPath+'fck_dialog.css';};FCKConfig.ToolbarSets={};FCKConfig.Plugins={};FCKConfig.Plugins.Items=[];FCKConfig.Plugins.Add=function(A,B,C){FCKConfig.Plugins.Items.push([A,B,C]);};FCKConfig.ProtectedSource={};FCKConfig.ProtectedSource._CodeTag=(new Date()).valueOf();FCKConfig.ProtectedSource.RegexEntries=[//g,//gi,//gi];FCKConfig.ProtectedSource.Add=function(A){this.RegexEntries.push(A);};FCKConfig.ProtectedSource.Protect=function(A){var B=this._CodeTag;function _Replace(protectedSource){var C=FCKTempBin.AddElement(protectedSource);return '';};for (var i=0;i|>)","g");return A.replace(D,_Replace);};FCKConfig.GetBodyAttributes=function(){var A='';if (this.BodyId&&this.BodyId.length>0) A+=' id="'+this.BodyId+'"';if (this.BodyClass&&this.BodyClass.length>0) A+=' class="'+this.BodyClass+'"';return A;};FCKConfig.ApplyBodyAttributes=function(A){if (this.BodyId&&this.BodyId.length>0) A.id=FCKConfig.BodyId;if (this.BodyClass&&this.BodyClass.length>0) A.className+=' '+FCKConfig.BodyClass;}; +var FCKDebug={Output:function(){},OutputObject:function(){}}; +var FCKDomTools={MoveChildren:function(A,B,C){if (A==B) return;var D;if (C){while ((D=A.lastChild)) B.insertBefore(A.removeChild(D),B.firstChild);}else{while ((D=A.firstChild)) B.appendChild(A.removeChild(D));}},MoveNode:function(A,B,C){if (C) B.insertBefore(FCKDomTools.RemoveNode(A),B.firstChild);else B.appendChild(FCKDomTools.RemoveNode(A));},TrimNode:function(A){this.LTrimNode(A);this.RTrimNode(A);},LTrimNode:function(A){var B;while ((B=A.firstChild)){if (B.nodeType==3){var C=B.nodeValue.LTrim();var D=B.nodeValue.length;if (C.length==0){A.removeChild(B);continue;}else if (C.length0) break;if (A.lastChild) A=A.lastChild;else return this.GetPreviousSourceElement(A,B,C,D);};return null;},GetNextSourceElement:function(A,B,C,D,E){while((A=this.GetNextSourceNode(A,E))){if (A.nodeType==1){if (C&&A.nodeName.IEquals(C)) break;if (D&&A.nodeName.IEquals(D)) return this.GetNextSourceElement(A,B,C,D);return A;}else if (B&&A.nodeType==3&&A.nodeValue.RTrim().length>0) break;};return null;},GetNextSourceNode:function(A,B,C,D){if (!A) return null;var E;if (!B&&A.firstChild) E=A.firstChild;else{if (D&&A==D) return null;E=A.nextSibling;if (!E&&(!D||D!=A.parentNode)) return this.GetNextSourceNode(A.parentNode,true,C,D);};if (C&&E&&E.nodeType!=C) return this.GetNextSourceNode(E,false,C,D);return E;},GetPreviousSourceNode:function(A,B,C,D){if (!A) return null;var E;if (!B&&A.lastChild) E=A.lastChild;else{if (D&&A==D) return null;E=A.previousSibling;if (!E&&(!D||D!=A.parentNode)) return this.GetPreviousSourceNode(A.parentNode,true,C,D);};if (C&&E&&E.nodeType!=C) return this.GetPreviousSourceNode(E,false,C,D);return E;},InsertAfterNode:function(A,B){return A.parentNode.insertBefore(B,A.nextSibling);},GetParents:function(A){var B=[];while (A){B.unshift(A);A=A.parentNode;};return B;},GetCommonParents:function(A,B){var C=this.GetParents(A);var D=this.GetParents(B);var E=[];for (var i=0;i0) D[C.pop().toLowerCase()]=1;var E=this.GetCommonParents(A,B);var F=null;while ((F=E.pop())){if (D[F.nodeName.toLowerCase()]) return F;};return null;},GetIndexOf:function(A){var B=A.parentNode?A.parentNode.firstChild:null;var C=-1;while (B){C++;if (B==A) return C;B=B.nextSibling;};return-1;},PaddingNode:null,EnforcePaddingNode:function(A,B){try{if (!A||!A.body) return;}catch (e){return;};this.CheckAndRemovePaddingNode(A,B,true);try{if (A.body.lastChild&&(A.body.lastChild.nodeType!=1||A.body.lastChild.tagName.toLowerCase()==B.toLowerCase())) return;}catch (e){return;};var C=A.createElement(B);if (FCKBrowserInfo.IsGecko&&FCKListsLib.NonEmptyBlockElements[B]) FCKTools.AppendBogusBr(C);this.PaddingNode=C;if (A.body.childNodes.length==1&&A.body.firstChild.nodeType==1&&A.body.firstChild.tagName.toLowerCase()=='br'&&(A.body.firstChild.getAttribute('_moz_dirty')!=null||A.body.firstChild.getAttribute('type')=='_moz')) A.body.replaceChild(C,A.body.firstChild);else A.body.appendChild(C);},CheckAndRemovePaddingNode:function(A,B,C){var D=this.PaddingNode;if (!D) return;try{if (D.parentNode!=A.body||D.tagName.toLowerCase()!=B||(D.childNodes.length>1)||(D.firstChild&&D.firstChild.nodeValue!='\xa0'&&String(D.firstChild.tagName).toLowerCase()!='br')){this.PaddingNode=null;return;}}catch (e){this.PaddingNode=null;return;};if (!C){if (D.parentNode.childNodes.length>1) D.parentNode.removeChild(D);this.PaddingNode=null;}},HasAttribute:function(A,B){if (A.hasAttribute) return A.hasAttribute(B);else{var C=A.attributes[B];return (C!=undefined&&C.specified);}},HasAttributes:function(A){var B=A.attributes;for (var i=0;i0) return true;continue;}};if (B[i].specified) return true;};return false;},RemoveAttribute:function(A,B){if (FCKBrowserInfo.IsIE&&B.toLowerCase()=='class') B='className';return A.removeAttribute(B,0);},RemoveAttributes:function (A,B){for (var i=0;i0) return false;C=C.nextSibling;};return D?this.CheckIsEmptyElement(D,B):true;},SetElementStyles:function(A,B){var C=A.style;for (var D in B) C[D]=B[D];},SetOpacity:function(A,B){if (FCKBrowserInfo.IsIE){B=Math.round(B*100);A.style.filter=(B>100?'':'progid:DXImageTransform.Microsoft.Alpha(opacity='+B+')');}else A.style.opacity=B;},GetCurrentElementStyle:function(A,B){if (FCKBrowserInfo.IsIE) return A.currentStyle[B];else return A.ownerDocument.defaultView.getComputedStyle(A,'').getPropertyValue(B);},GetPositionedAncestor:function(A){var B=A;while (B!=FCKTools.GetElementDocument(B).documentElement){if (this.GetCurrentElementStyle(B,'position')!='static') return B;if (B==FCKTools.GetElementDocument(B).documentElement&¤tWindow!=w) B=currentWindow.frameElement;else B=B.parentNode;};return null;},ScrollIntoView:function(A,B){var C=FCKTools.GetElementWindow(A);var D=FCKTools.GetViewPaneSize(C).Height;var E=D*-1;if (B===false){E+=A.offsetHeight||0;E+=parseInt(this.GetCurrentElementStyle(A,'marginBottom')||0,10)||0;};var F=FCKTools.GetDocumentPosition(C,A);E+=F.y;var G=FCKTools.GetScrollPosition(C).Y;if (E>0&&(E>G||E'+styleDef+'';};var C=function(cssFileUrl,markTemp){if (cssFileUrl.length==0) return '';var B=markTemp?' _fcktemp="true"':'';return '';};return function(cssFileOrArrayOrDef,markTemp){if (!cssFileOrArrayOrDef) return '';if (typeof(cssFileOrArrayOrDef)=='string'){if (/[\\\/\.][^{}]*$/.test(cssFileOrArrayOrDef)){return this.GetStyleHtml(cssFileOrArrayOrDef.split(','),markTemp);}else return A(this._GetUrlFixedCss(cssFileOrArrayOrDef),markTemp);}else{var E='';for (var i=0;i/g,'>');return A;};FCKTools.HTMLDecode=function(A){if (!A) return '';A=A.replace(/>/g,'>');A=A.replace(/</g,'<');A=A.replace(/&/g,'&');return A;};FCKTools._ProcessLineBreaksForPMode=function(A,B,C,D,E){var F=0;var G="

";var H="

";var I="
";if (C){G="
  • ";H="
  • ";F=1;}while (D&&D!=A.FCK.EditorDocument.body){if (D.tagName.toLowerCase()=='p'){F=1;break;};D=D.parentNode;};for (var i=0;i0) return A[A.length-1];return null;};FCKTools.GetDocumentPosition=function(w,A){var x=0;var y=0;var B=A;var C=null;var D=FCKTools.GetElementWindow(B);while (B&&!(D==w&&(B==w.document.body||B==w.document.documentElement))){x+=B.offsetLeft-B.scrollLeft;y+=B.offsetTop-B.scrollTop;if (!FCKBrowserInfo.IsOpera){var E=C;while (E&&E!=B){x-=E.scrollLeft;y-=E.scrollTop;E=E.parentNode;}};C=B;if (B.offsetParent) B=B.offsetParent;else{if (D!=w){B=D.frameElement;C=null;if (B) D=B.contentWindow.parent;}else B=null;}};if (FCKDomTools.GetCurrentElementStyle(w.document.body,'position')!='static'||(FCKBrowserInfo.IsIE&&FCKDomTools.GetPositionedAncestor(A)==null)){x+=w.document.body.offsetLeft;y+=w.document.body.offsetTop;};return { "x":x,"y":y };};FCKTools.GetWindowPosition=function(w,A){var B=this.GetDocumentPosition(w,A);var C=FCKTools.GetScrollPosition(w);B.x-=C.X;B.y-=C.Y;return B;};FCKTools.ProtectFormStyles=function(A){if (!A||A.nodeType!=1||A.tagName.toLowerCase()!='form') return [];var B=[];var C=['style','className'];for (var i=0;i0){for (var i=B.length-1;i>=0;i--){var C=B[i][0];var D=B[i][1];if (D) A.insertBefore(C,D);else A.appendChild(C);}}};FCKTools.GetNextNode=function(A,B){if (A.firstChild) return A.firstChild;else if (A.nextSibling) return A.nextSibling;else{var C=A.parentNode;while (C){if (C==B) return null;if (C.nextSibling) return C.nextSibling;else C=C.parentNode;}};return null;};FCKTools.GetNextTextNode=function(A,B,C){node=this.GetNextNode(A,B);if (C&&node&&C(node)) return null;while (node&&node.nodeType!=3){node=this.GetNextNode(node,B);if (C&&node&&C(node)) return null;};return node;};FCKTools.Merge=function(){var A=arguments;var o=A[0];for (var i=1;i');document.domain = '"+FCK_RUNTIME_DOMAIN+"';document.close();}() ) ;";if (FCKBrowserInfo.IsIE){if (FCKBrowserInfo.IsIE7||!FCKBrowserInfo.IsIE6) return "";else return "javascript: '';";};return "javascript: void(0);";};FCKTools.ResetStyles=function(A){A.style.cssText='margin:0;padding:0;border:0;background-color:transparent;background-image:none;';}; +FCKTools.CancelEvent=function(e){if (e) e.preventDefault();};FCKTools.DisableSelection=function(A){if (FCKBrowserInfo.IsGecko) A.style.MozUserSelect='none';else if (FCKBrowserInfo.IsSafari) A.style.KhtmlUserSelect='none';else A.style.userSelect='none';};FCKTools._AppendStyleSheet=function(A,B){var e=A.createElement('LINK');e.rel='stylesheet';e.type='text/css';e.href=B;A.getElementsByTagName("HEAD")[0].appendChild(e);return e;};FCKTools.AppendStyleString=function(A,B){if (!B) return null;var e=A.createElement("STYLE");e.appendChild(A.createTextNode(B));A.getElementsByTagName("HEAD")[0].appendChild(e);return e;};FCKTools.ClearElementAttributes=function(A){for (var i=0;i0) B[B.length]=D;C(parent.childNodes[i]);}};C(A);return B;};FCKTools.RemoveOuterTags=function(e){var A=e.ownerDocument.createDocumentFragment();for (var i=0;i','text/xml');FCKDomTools.RemoveNode(B.firstChild);return B;};return null;};FCKTools.GetScrollPosition=function(A){return { X:A.pageXOffset,Y:A.pageYOffset };};FCKTools.AddEventListener=function(A,B,C){A.addEventListener(B,C,false);};FCKTools.RemoveEventListener=function(A,B,C){A.removeEventListener(B,C,false);};FCKTools.AddEventListenerEx=function(A,B,C,D){A.addEventListener(B,function(e){C.apply(A,[e].concat(D||[]));},false);};FCKTools.GetViewPaneSize=function(A){return { Width:A.innerWidth,Height:A.innerHeight };};FCKTools.SaveStyles=function(A){var B=FCKTools.ProtectFormStyles(A);var C={};if (A.className.length>0){C.Class=A.className;A.className='';};var D=A.getAttribute('style');if (D&&D.length>0){C.Inline=D;A.setAttribute('style','',0);};FCKTools.RestoreFormStyles(A,B);return C;};FCKTools.RestoreStyles=function(A,B){var C=FCKTools.ProtectFormStyles(A);A.className=B.Class||'';if (B.Inline) A.setAttribute('style',B.Inline,0);else A.removeAttribute('style',0);FCKTools.RestoreFormStyles(A,C);};FCKTools.RegisterDollarFunction=function(A){A.$=function(id){return A.document.getElementById(id);};};FCKTools.AppendElement=function(A,B){return A.appendChild(A.ownerDocument.createElement(B));};FCKTools.GetElementPosition=function(A,B){var c={ X:0,Y:0 };var C=B||window;var D=FCKTools.GetElementWindow(A);var E=null;while (A){var F=D.getComputedStyle(A,'').position;if (F&&F!='static'&&A.style.zIndex!=FCKConfig.FloatingPanelsZIndex) break;c.X+=A.offsetLeft-A.scrollLeft;c.Y+=A.offsetTop-A.scrollTop;if (!FCKBrowserInfo.IsOpera){var G=E;while (G&&G!=A){c.X-=G.scrollLeft;c.Y-=G.scrollTop;G=G.parentNode;}};E=A;if (A.offsetParent) A=A.offsetParent;else{if (D!=C){A=D.frameElement;E=null;if (A) D=FCKTools.GetElementWindow(A);}else{c.X+=A.scrollLeft;c.Y+=A.scrollTop;break;}}};return c;}; +var FCKeditorAPI;function InitializeAPI(){var A=window.parent;if (!(FCKeditorAPI=A.FCKeditorAPI)){var B='window.FCKeditorAPI = {Version : "2.6.5",VersionBuild : "23959",Instances : window.FCKeditorAPI && window.FCKeditorAPI.Instances || {},GetInstance : function( name ){return this.Instances[ name ];},_FormSubmit : function(){for ( var name in FCKeditorAPI.Instances ){var oEditor = FCKeditorAPI.Instances[ name ] ;if ( oEditor.GetParentForm && oEditor.GetParentForm() == this )oEditor.UpdateLinkedField() ;}this._FCKOriginalSubmit() ;},_FunctionQueue : window.FCKeditorAPI && window.FCKeditorAPI._FunctionQueue || {Functions : new Array(),IsRunning : false,Add : function( f ){this.Functions.push( f );if ( !this.IsRunning )this.StartNext();},StartNext : function(){var aQueue = this.Functions ;if ( aQueue.length > 0 ){this.IsRunning = true;aQueue[0].call();}else this.IsRunning = false;},Remove : function( f ){var aQueue = this.Functions;var i = 0, fFunc;while( (fFunc = aQueue[ i ]) ){if ( fFunc == f )aQueue.splice( i,1 );i++ ;}this.StartNext();}}}';if (A.execScript) A.execScript(B,'JavaScript');else{if (FCKBrowserInfo.IsGecko10){eval.call(A,B);}else if(FCKBrowserInfo.IsAIR){FCKAdobeAIR.FCKeditorAPI_Evaluate(A,B);}else if (FCKBrowserInfo.IsSafari){var C=A.document;var D=C.createElement('script');D.appendChild(C.createTextNode(B));C.documentElement.appendChild(D);}else A.eval(B);};FCKeditorAPI=A.FCKeditorAPI;FCKeditorAPI.__Instances=FCKeditorAPI.Instances;};FCKeditorAPI.Instances[FCK.Name]=FCK;};function _AttachFormSubmitToAPI(){var A=FCK.GetParentForm();if (A){FCKTools.AddEventListener(A,'submit',FCK.UpdateLinkedField);if (!A._FCKOriginalSubmit&&(typeof(A.submit)=='function'||(!A.submit.tagName&&!A.submit.length))){A._FCKOriginalSubmit=A.submit;A.submit=FCKeditorAPI._FormSubmit;}}};function FCKeditorAPI_Cleanup(){if (window.FCKConfig&&FCKConfig.MsWebBrowserControlCompat&&!window.FCKUnloadFlag) return;delete FCKeditorAPI.Instances[FCK.Name];};function FCKeditorAPI_ConfirmCleanup(){if (window.FCKConfig&&FCKConfig.MsWebBrowserControlCompat) window.FCKUnloadFlag=true;};FCKTools.AddEventListener(window,'unload',FCKeditorAPI_Cleanup);FCKTools.AddEventListener(window,'beforeunload',FCKeditorAPI_ConfirmCleanup); +var FCKImagePreloader=function(){this._Images=[];};FCKImagePreloader.prototype={AddImages:function(A){if (typeof(A)=='string') A=A.split(';');this._Images=this._Images.concat(A);},Start:function(){var A=this._Images;this._PreloadCount=A.length;for (var i=0;i]*\>)/i,AfterBody:/(\<\/body\>[\s\S]*$)/i,ToReplace:/___fcktoreplace:([\w]+)/ig,MetaHttpEquiv:/http-equiv\s*=\s*["']?([^"' ]+)/i,HasBaseTag:/]/i,HtmlOpener:/]*>/i,HeadOpener:/]*>/i,HeadCloser:/<\/head\s*>/i,FCK_Class:/\s*FCK__[^ ]*(?=\s+|$)/,ElementName:/(^[a-z_:][\w.\-:]*\w$)|(^[a-z_]$)/,ForceSimpleAmpersand:/___FCKAmp___/g,SpaceNoClose:/\/>/g,EmptyParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>\s*(<\/\1>)?$/,EmptyOutParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>(?:\s*| | )(<\/\1>)?$/,TagBody:/>]+))/gi,ProtectUrlsA:/]+))/gi,ProtectUrlsArea:/]+))/gi,Html4DocType:/HTML 4\.0 Transitional/i,DocTypeTag:/]*>/i,HtmlDocType:/DTD HTML/,TagsWithEvent:/<[^\>]+ on\w+[\s\r\n]*=[\s\r\n]*?('|")[\s\S]+?\>/g,EventAttributes:/\s(on\w+)[\s\r\n]*=[\s\r\n]*?('|")([\s\S]*?)\2/g,ProtectedEvents:/\s\w+_fckprotectedatt="([^"]+)"/g,StyleProperties:/\S+\s*:/g,InvalidSelfCloseTags:/(<(?!base|meta|link|hr|br|param|img|area|input)([a-zA-Z0-9:]+)[^>]*)\/>/gi,StyleVariableAttName:/#\(\s*("|')(.+?)\1[^\)]*\s*\)/g,RegExp:/^\/(.*)\/([gim]*)$/,HtmlTag:/<[^\s<>](?:"[^"]*"|'[^']*'|[^<])*>/}; +var FCKListsLib={BlockElements:{ address:1,blockquote:1,center:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,marquee:1,noscript:1,ol:1,p:1,pre:1,script:1,table:1,ul:1 },NonEmptyBlockElements:{ p:1,div:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,address:1,pre:1,ol:1,ul:1,li:1,td:1,th:1 },InlineChildReqElements:{ abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 },InlineNonEmptyElements:{ a:1,abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 },EmptyElements:{ base:1,col:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 },PathBlockElements:{ address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,li:1,dt:1,de:1 },PathBlockLimitElements:{ body:1,div:1,td:1,th:1,caption:1,form:1 },StyleBlockElements:{ address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1 },StyleObjectElements:{ img:1,hr:1,li:1,table:1,tr:1,td:1,embed:1,object:1,ol:1,ul:1 },NonEditableElements:{ button:1,option:1,script:1,iframe:1,textarea:1,object:1,embed:1,map:1,applet:1 },BlockBoundaries:{ p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,address:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1,table:1,thead:1,tbody:1,tfoot:1,tr:1,th:1,td:1,caption:1,col:1,colgroup:1,blockquote:1,body:1 },ListBoundaries:{ p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,address:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1,table:1,thead:1,tbody:1,tfoot:1,tr:1,th:1,td:1,caption:1,col:1,colgroup:1,blockquote:1,body:1,br:1 }}; +var FCKLanguageManager=FCK.Language={AvailableLanguages:{af:'Afrikaans',ar:'Arabic',bg:'Bulgarian',bn:'Bengali/Bangla',bs:'Bosnian',ca:'Catalan',cs:'Czech',da:'Danish',de:'German',el:'Greek',en:'English','en-au':'English (Australia)','en-ca':'English (Canadian)','en-uk':'English (United Kingdom)',eo:'Esperanto',es:'Spanish',et:'Estonian',eu:'Basque',fa:'Persian',fi:'Finnish',fo:'Faroese',fr:'French','fr-ca':'French (Canada)',gl:'Galician',gu:'Gujarati',he:'Hebrew',hi:'Hindi',hr:'Croatian',hu:'Hungarian',is:'Icelandic',it:'Italian',ja:'Japanese',km:'Khmer',ko:'Korean',lt:'Lithuanian',lv:'Latvian',mn:'Mongolian',ms:'Malay',nb:'Norwegian Bokmal',nl:'Dutch',no:'Norwegian',pl:'Polish',pt:'Portuguese (Portugal)','pt-br':'Portuguese (Brazil)',ro:'Romanian',ru:'Russian',sk:'Slovak',sl:'Slovenian',sr:'Serbian (Cyrillic)','sr-latn':'Serbian (Latin)',sv:'Swedish',th:'Thai',tr:'Turkish',uk:'Ukrainian',vi:'Vietnamese',zh:'Chinese Traditional','zh-cn':'Chinese Simplified'},GetActiveLanguage:function(){if (FCKConfig.AutoDetectLanguage){var A;if (navigator.userLanguage) A=navigator.userLanguage.toLowerCase();else if (navigator.language) A=navigator.language.toLowerCase();else{return FCKConfig.DefaultLanguage;};if (A.length>=5){A=A.substr(0,5);if (this.AvailableLanguages[A]) return A;};if (A.length>=2){A=A.substr(0,2);if (this.AvailableLanguages[A]) return A;}};return this.DefaultLanguage;},TranslateElements:function(A,B,C,D){var e=A.getElementsByTagName(B);var E,s;for (var i=0;i':'gt','ˆ':'circ','Ëœ':'tilde',' ':'ensp',' ':'emsp',' ':'thinsp','‌':'zwnj','â€':'zwj','‎':'lrm','â€':'rlm','–':'ndash','—':'mdash','‘':'lsquo','’':'rsquo','‚':'sbquo','“':'ldquo','â€':'rdquo','„':'bdquo','†':'dagger','‡':'Dagger','‰':'permil','‹':'lsaquo','›':'rsaquo','€':'euro'};for (e in FCKXHtmlEntities.Entities) A+=e;if (FCKConfig.IncludeLatinEntities){B={'À':'Agrave','Ã':'Aacute','Â':'Acirc','Ã':'Atilde','Ä':'Auml','Ã…':'Aring','Æ':'AElig','Ç':'Ccedil','È':'Egrave','É':'Eacute','Ê':'Ecirc','Ë':'Euml','ÃŒ':'Igrave','Ã':'Iacute','ÃŽ':'Icirc','Ã':'Iuml','Ã':'ETH','Ñ':'Ntilde','Ã’':'Ograve','Ó':'Oacute','Ô':'Ocirc','Õ':'Otilde','Ö':'Ouml','Ø':'Oslash','Ù':'Ugrave','Ú':'Uacute','Û':'Ucirc','Ãœ':'Uuml','Ã':'Yacute','Þ':'THORN','ß':'szlig','à':'agrave','á':'aacute','â':'acirc','ã':'atilde','ä':'auml','Ã¥':'aring','æ':'aelig','ç':'ccedil','è':'egrave','é':'eacute','ê':'ecirc','ë':'euml','ì':'igrave','í':'iacute','î':'icirc','ï':'iuml','ð':'eth','ñ':'ntilde','ò':'ograve','ó':'oacute','ô':'ocirc','õ':'otilde','ö':'ouml','ø':'oslash','ù':'ugrave','ú':'uacute','û':'ucirc','ü':'uuml','ý':'yacute','þ':'thorn','ÿ':'yuml','Å’':'OElig','Å“':'oelig','Å ':'Scaron','Å¡':'scaron','Ÿ':'Yuml'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;};if (FCKConfig.IncludeGreekEntities){B={'Α':'Alpha','Î’':'Beta','Γ':'Gamma','Δ':'Delta','Ε':'Epsilon','Ζ':'Zeta','Η':'Eta','Θ':'Theta','Ι':'Iota','Κ':'Kappa','Λ':'Lambda','Îœ':'Mu','Î':'Nu','Ξ':'Xi','Ο':'Omicron','Π':'Pi','Ρ':'Rho','Σ':'Sigma','Τ':'Tau','Î¥':'Upsilon','Φ':'Phi','Χ':'Chi','Ψ':'Psi','Ω':'Omega','α':'alpha','β':'beta','γ':'gamma','δ':'delta','ε':'epsilon','ζ':'zeta','η':'eta','θ':'theta','ι':'iota','κ':'kappa','λ':'lambda','μ':'mu','ν':'nu','ξ':'xi','ο':'omicron','Ï€':'pi','Ï':'rho','Ï‚':'sigmaf','σ':'sigma','Ï„':'tau','Ï…':'upsilon','φ':'phi','χ':'chi','ψ':'psi','ω':'omega','\u03d1':'thetasym','\u03d2':'upsih','\u03d6':'piv'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;}}else{FCKXHtmlEntities.Entities={'>':'gt'};A='>';A+=' ';};var C='['+A+']';if (FCKConfig.ProcessNumericEntities) C='[^ -~]|'+C;var D=FCKConfig.AdditionalNumericEntities;if (D&&D.length>0) C+='|'+FCKConfig.AdditionalNumericEntities;FCKXHtmlEntities.EntitiesRegex=new RegExp(C,'g');}; +var FCKXHtml={};FCKXHtml.CurrentJobNum=0;FCKXHtml.GetXHTML=function(A,B,C){FCKDomTools.CheckAndRemovePaddingNode(FCKTools.GetElementDocument(A),FCKConfig.EnterMode);FCKXHtmlEntities.Initialize();this._NbspEntity=(FCKConfig.ProcessHTMLEntities?'nbsp':'#160');var D=FCK.IsDirty();FCKXHtml.SpecialBlocks=[];this.XML=FCKTools.CreateXmlObject('DOMDocument');this.MainNode=this.XML.appendChild(this.XML.createElement('xhtml'));FCKXHtml.CurrentJobNum++;if (B) this._AppendNode(this.MainNode,A);else this._AppendChildNodes(this.MainNode,A,false);if (FCKBrowserInfo.IsIE) FCKXHtml._RemoveXHtmlJobProperties(A);var E=this._GetMainXmlString();this.XML=null;if (FCKBrowserInfo.IsSafari) E=E.replace(/^/,'');E=E.substr(7,E.length-15).Trim();if (FCKConfig.DocType.length>0&&FCKRegexLib.HtmlDocType.test(FCKConfig.DocType)) E=E.replace(FCKRegexLib.SpaceNoClose,'>');else E=E.replace(FCKRegexLib.SpaceNoClose,' />');if (FCKConfig.ForceSimpleAmpersand) E=E.replace(FCKRegexLib.ForceSimpleAmpersand,'&');if (C) E=FCKCodeFormatter.Format(E);for (var i=0;i0;if (C) A.appendChild(this.XML.createTextNode(B.replace(FCKXHtmlEntities.EntitiesRegex,FCKXHtml_GetEntity)));return C;};function FCKXHtml_GetEntity(A){var B=FCKXHtmlEntities.Entities[A]||('#'+A.charCodeAt(0));return '#?-:'+B+';';};FCKXHtml.TagProcessors={a:function(A,B){if (B.innerHTML.Trim().length==0&&!B.name) return false;var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'href',C);if (FCKBrowserInfo.IsIE){if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);};A=FCKXHtml._AppendChildNodes(A,B,false);return A;},area:function(A,B){var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'href',C);if (FCKBrowserInfo.IsIE){if (!A.attributes.getNamedItem('coords')){var D=B.getAttribute('coords',2);if (D&&D!='0,0,0') FCKXHtml._AppendAttribute(A,'coords',D);};if (!A.attributes.getNamedItem('shape')){var E=B.getAttribute('shape',2);if (E&&E.length>0) FCKXHtml._AppendAttribute(A,'shape',E.toLowerCase());}};return A;},body:function(A,B){A=FCKXHtml._AppendChildNodes(A,B,false);A.removeAttribute('spellcheck');return A;},iframe:function(A,B){var C=B.innerHTML;if (FCKBrowserInfo.IsGecko) C=FCKTools.HTMLDecode(C);C=C.replace(/\s_fcksavedurl="[^"]*"/g,'');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(C)));return A;},img:function(A,B){if (!A.attributes.getNamedItem('alt')) FCKXHtml._AppendAttribute(A,'alt','');var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'src',C);if (B.style.width) A.removeAttribute('width');if (B.style.height) A.removeAttribute('height');return A;},li:function(A,B,C){if (C.nodeName.IEquals(['ul','ol'])) return FCKXHtml._AppendChildNodes(A,B,true);var D=FCKXHtml.XML.createElement('ul');B._fckxhtmljob=null;do{FCKXHtml._AppendNode(D,B);do{B=FCKDomTools.GetNextSibling(B);} while (B&&B.nodeType==3&&B.nodeValue.Trim().length==0)} while (B&&B.nodeName.toLowerCase()=='li') return D;},ol:function(A,B,C){if (B.innerHTML.Trim().length==0) return false;var D=C.lastChild;if (D&&D.nodeType==3) D=D.previousSibling;if (D&&D.nodeName.toUpperCase()=='LI'){B._fckxhtmljob=null;FCKXHtml._AppendNode(D,B);return false;};A=FCKXHtml._AppendChildNodes(A,B);return A;},pre:function (A,B){var C=B.firstChild;if (C&&C.nodeType==3) A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem('\r\n')));FCKXHtml._AppendChildNodes(A,B,true);return A;},script:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/javascript');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(B.text)));return A;},span:function(A,B){if (B.innerHTML.length==0) return false;A=FCKXHtml._AppendChildNodes(A,B,false);return A;},style:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/css');var C=B.innerHTML;if (FCKBrowserInfo.IsIE) C=C.replace(/^(\r\n|\n|\r)/,'');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(C)));return A;},title:function(A,B){A.appendChild(FCKXHtml.XML.createTextNode(FCK.EditorDocument.title));return A;}};FCKXHtml.TagProcessors.ul=FCKXHtml.TagProcessors.ol; +FCKXHtml._GetMainXmlString=function(){return (new XMLSerializer()).serializeToString(this.MainNode);};FCKXHtml._AppendAttributes=function(A,B,C){var D=B.attributes;for (var n=0;n]*\>/gi;A.BlocksCloser=/\<\/(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DL|DT|DD|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.NewLineTags=/\<(BR|HR)[^\>]*\>/gi;A.MainTags=/\<\/?(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR)[^\>]*\>/gi;A.LineSplitter=/\s*\n+\s*/g;A.IncreaseIndent=/^\<(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL|DL)[ \/\>]/i;A.DecreaseIndent=/^\<\/(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL|DL)[ \>]/i;A.FormatIndentatorRemove=new RegExp('^'+FCKConfig.FormatIndentator);A.ProtectedTags=/(]*>)([\s\S]*?)(<\/PRE>)/gi;};FCKCodeFormatter._ProtectData=function(A,B,C,D){return B+'___FCKpd___'+(FCKCodeFormatter.ProtectedData.push(C)-1)+D;};FCKCodeFormatter.Format=function(A){if (!this.Regex) this.Init();FCKCodeFormatter.ProtectedData=[];var B=A.replace(this.Regex.ProtectedTags,FCKCodeFormatter._ProtectData);B=B.replace(this.Regex.BlocksOpener,'\n$&');B=B.replace(this.Regex.BlocksCloser,'$&\n');B=B.replace(this.Regex.NewLineTags,'$&\n');B=B.replace(this.Regex.MainTags,'\n$&\n');var C='';var D=B.split(this.Regex.LineSplitter);B='';for (var i=0;iB[i]) return 1;};if (A.lengthB.length) return 1;return 0;};FCKUndo._CheckIsBookmarksEqual=function(A,B){if (!(A&&B)) return false;if (FCKBrowserInfo.IsIE){var C=A[1].search(A[0].StartId);var D=B[1].search(B[0].StartId);var E=A[1].search(A[0].EndId);var F=B[1].search(B[0].EndId);return C==D&&E==F;}else{return this._CompareCursors(A.Start,B.Start)==0&&this._CompareCursors(A.End,B.End)==0;}};FCKUndo.SaveUndoStep=function(){if (FCK.EditMode!=0||this.SaveLocked) return;if (this.SavedData.length) this.Changed=true;var A=FCK.EditorDocument.body.innerHTML;var B=this._GetBookmark();this.SavedData=this.SavedData.slice(0,this.CurrentIndex+1);if (this.CurrentIndex>0&&A==this.SavedData[this.CurrentIndex][0]&&this._CheckIsBookmarksEqual(B,this.SavedData[this.CurrentIndex][1])) return;else if (this.CurrentIndex==0&&this.SavedData.length&&A==this.SavedData[0][0]){this.SavedData[0][1]=B;return;};if (this.CurrentIndex+1>=FCKConfig.MaxUndoLevels) this.SavedData.shift();else this.CurrentIndex++;this.SavedData[this.CurrentIndex]=[A,B];FCK.Events.FireEvent("OnSelectionChange");};FCKUndo.CheckUndoState=function(){return (this.Changed||this.CurrentIndex>0);};FCKUndo.CheckRedoState=function(){return (this.CurrentIndex<(this.SavedData.length-1));};FCKUndo.Undo=function(){if (this.CheckUndoState()){if (this.CurrentIndex==(this.SavedData.length-1)){this.SaveUndoStep();};this._ApplyUndoLevel(--this.CurrentIndex);FCK.Events.FireEvent("OnSelectionChange");}};FCKUndo.Redo=function(){if (this.CheckRedoState()){this._ApplyUndoLevel(++this.CurrentIndex);FCK.Events.FireEvent("OnSelectionChange");}};FCKUndo._ApplyUndoLevel=function(A){var B=this.SavedData[A];if (!B) return;if (FCKBrowserInfo.IsIE){if (B[1]&&B[1][1]) FCK.SetInnerHtml(B[1][1]);else FCK.SetInnerHtml(B[0]);}else FCK.EditorDocument.body.innerHTML=B[0];this._SelectBookmark(B[1]);this.TypesCount=0;this.Changed=false;this.Typing=false;}; +var FCKEditingArea=function(A){this.TargetElement=A;this.Mode=0;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKEditingArea_Cleanup);};FCKEditingArea.prototype.Start=function(A,B){var C=this.TargetElement;var D=FCKTools.GetElementDocument(C);while(C.firstChild) C.removeChild(C.firstChild);if (this.Mode==0){if (FCK_IS_CUSTOM_DOMAIN) A=''+A;if (FCKBrowserInfo.IsIE) A=A.replace(/(]*?)\s*\/?>(?!\s*<\/base>)/gi,'$1>');else if (!B){var E=A.match(FCKRegexLib.BeforeBody);var F=A.match(FCKRegexLib.AfterBody);if (E&&F){var G=A.substr(E[1].length,A.length-E[1].length-F[1].length);A=E[1]+' '+F[1];if (FCKBrowserInfo.IsGecko&&(G.length==0||FCKRegexLib.EmptyParagraph.test(G))) G='
    ';this._BodyHTML=G;}else this._BodyHTML=A;};var H=this.IFrame=D.createElement('iframe');var I='';H.frameBorder=0;H.style.width=H.style.height='100%';if (FCK_IS_CUSTOM_DOMAIN&&FCKBrowserInfo.IsIE){window._FCKHtmlToLoad=A.replace(//i,''+I);H.src='javascript:void( (function(){document.open() ;document.domain="'+document.domain+'" ;document.write( window.parent._FCKHtmlToLoad );document.close() ;window.parent._FCKHtmlToLoad = null ;})() )';}else if (!FCKBrowserInfo.IsGecko){H.src='javascript:void(0)';};C.appendChild(H);this.Window=H.contentWindow;if (!FCK_IS_CUSTOM_DOMAIN||!FCKBrowserInfo.IsIE){var J=this.Window.document;J.open();J.write(A.replace(//i,''+I));J.close();};if (FCKBrowserInfo.IsAIR) FCKAdobeAIR.EditingArea_Start(J,A);if (FCKBrowserInfo.IsGecko10&&!B){this.Start(A,true);return;};if (H.readyState&&H.readyState!='completed'){var K=this;setTimeout(function(){try{K.Window.document.documentElement.doScroll("left");}catch(e){setTimeout(arguments.callee,0);return;};K.Window._FCKEditingArea=K;FCKEditingArea_CompleteStart.call(K.Window);},0);}else{this.Window._FCKEditingArea=this;if (FCKBrowserInfo.IsGecko10) this.Window.setTimeout(FCKEditingArea_CompleteStart,500);else FCKEditingArea_CompleteStart.call(this.Window);}}else{var L=this.Textarea=D.createElement('textarea');L.className='SourceField';L.dir='ltr';FCKDomTools.SetElementStyles(L,{width:'100%',height:'100%',border:'none',resize:'none',outline:'none'});C.appendChild(L);L.value=A;FCKTools.RunFunction(this.OnLoad);}};function FCKEditingArea_CompleteStart(){if (!this.document.body){this.setTimeout(FCKEditingArea_CompleteStart,50);return;};var A=this._FCKEditingArea;A.Document=A.Window.document;A.MakeEditable();FCKTools.RunFunction(A.OnLoad);};FCKEditingArea.prototype.MakeEditable=function(){var A=this.Document;if (FCKBrowserInfo.IsIE){A.body.disabled=true;A.body.contentEditable=true;A.body.removeAttribute("disabled");}else{try{A.body.spellcheck=(this.FFSpellChecker!==false);if (this._BodyHTML){A.body.innerHTML=this._BodyHTML;A.body.offsetLeft;this._BodyHTML=null;};A.designMode='on';A.execCommand('enableObjectResizing',false,!FCKConfig.DisableObjectResizing);A.execCommand('enableInlineTableEditing',false,!FCKConfig.DisableFFTableHandles);}catch (e){FCKTools.AddEventListener(this.Window.frameElement,'DOMAttrModified',FCKEditingArea_Document_AttributeNodeModified);}}};function FCKEditingArea_Document_AttributeNodeModified(A){var B=A.currentTarget.contentWindow._FCKEditingArea;if (B._timer) window.clearTimeout(B._timer);B._timer=FCKTools.SetTimeout(FCKEditingArea_MakeEditableByMutation,1000,B);};function FCKEditingArea_MakeEditableByMutation(){delete this._timer;FCKTools.RemoveEventListener(this.Window.frameElement,'DOMAttrModified',FCKEditingArea_Document_AttributeNodeModified);this.MakeEditable();};FCKEditingArea.prototype.Focus=function(){try{if (this.Mode==0){if (FCKBrowserInfo.IsIE) this._FocusIE();else this.Window.focus();}else{var A=FCKTools.GetElementDocument(this.Textarea);if ((!A.hasFocus||A.hasFocus())&&A.activeElement==this.Textarea) return;this.Textarea.focus();}}catch(e) {}};FCKEditingArea.prototype._FocusIE=function(){this.Document.body.setActive();this.Window.focus();var A=this.Document.selection.createRange();var B=A.parentElement();var C=B.nodeName.toLowerCase();if (B.childNodes.length>0||!(FCKListsLib.BlockElements[C]||FCKListsLib.NonEmptyBlockElements[C])){return;};A=new FCKDomRange(this.Window);A.MoveToElementEditStart(B);A.Select();};function FCKEditingArea_Cleanup(){if (this.Document){this.Document.selection.empty();this.Document.body.innerHTML="";};this.TargetElement=null;this.IFrame=null;this.Document=null;this.Textarea=null;if (this.Window){this.Window._FCKEditingArea=null;this.Window=null;}}; +var FCKKeystrokeHandler=function(A){this.Keystrokes={};this.CancelCtrlDefaults=(A!==false);};FCKKeystrokeHandler.prototype.AttachToElement=function(A){FCKTools.AddEventListenerEx(A,'keydown',_FCKKeystrokeHandler_OnKeyDown,this);if (FCKBrowserInfo.IsGecko10||FCKBrowserInfo.IsOpera||(FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsMac)) FCKTools.AddEventListenerEx(A,'keypress',_FCKKeystrokeHandler_OnKeyPress,this);};FCKKeystrokeHandler.prototype.SetKeystrokes=function(){for (var i=0;i40))){B._CancelIt=true;if (A.preventDefault) return A.preventDefault();A.returnValue=false;A.cancelBubble=true;return false;};return true;};function _FCKKeystrokeHandler_OnKeyPress(A,B){if (B._CancelIt){if (A.preventDefault) return A.preventDefault();return false;};return true;}; +FCK.DTD=(function(){var X=FCKTools.Merge;var A,L,J,M,N,O,D,H,P,K,Q,F,G,C,B,E,I;A={isindex:1,fieldset:1};B={input:1,button:1,select:1,textarea:1,label:1};C=X({a:1},B);D=X({iframe:1},C);E={hr:1,ul:1,menu:1,div:1,blockquote:1,noscript:1,table:1,center:1,address:1,dir:1,pre:1,h5:1,dl:1,h4:1,noframes:1,h6:1,ol:1,h1:1,h3:1,h2:1};F={ins:1,del:1,script:1};G=X({b:1,acronym:1,bdo:1,'var':1,'#':1,abbr:1,code:1,br:1,i:1,cite:1,kbd:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,dfn:1,span:1},F);H=X({sub:1,img:1,object:1,sup:1,basefont:1,map:1,applet:1,font:1,big:1,small:1},G);I=X({p:1},H);J=X({iframe:1},H,B);K={img:1,noscript:1,br:1,kbd:1,center:1,button:1,basefont:1,h5:1,h4:1,samp:1,h6:1,ol:1,h1:1,h3:1,h2:1,form:1,font:1,'#':1,select:1,menu:1,ins:1,abbr:1,label:1,code:1,table:1,script:1,cite:1,input:1,iframe:1,strong:1,textarea:1,noframes:1,big:1,small:1,span:1,hr:1,sub:1,bdo:1,'var':1,div:1,object:1,sup:1,strike:1,dir:1,map:1,dl:1,applet:1,del:1,isindex:1,fieldset:1,ul:1,b:1,acronym:1,a:1,blockquote:1,i:1,u:1,s:1,tt:1,address:1,q:1,pre:1,p:1,em:1,dfn:1};L=X({a:1},J);M={tr:1};N={'#':1};O=X({param:1},K);P=X({form:1},A,D,E,I);Q={li:1};return {col:{},tr:{td:1,th:1},img:{},colgroup:{col:1},noscript:P,td:P,br:{},th:P,center:P,kbd:L,button:X(I,E),basefont:{},h5:L,h4:L,samp:L,h6:L,ol:Q,h1:L,h3:L,option:N,h2:L,form:X(A,D,E,I),select:{optgroup:1,option:1},font:J,ins:P,menu:Q,abbr:L,label:L,table:{thead:1,col:1,tbody:1,tr:1,colgroup:1,caption:1,tfoot:1},code:L,script:N,tfoot:M,cite:L,li:P,input:{},iframe:P,strong:J,textarea:N,noframes:P,big:J,small:J,span:J,hr:{},dt:L,sub:J,optgroup:{option:1},param:{},bdo:L,'var':J,div:P,object:O,sup:J,dd:P,strike:J,area:{},dir:Q,map:X({area:1,form:1,p:1},A,F,E),applet:O,dl:{dt:1,dd:1},del:P,isindex:{},fieldset:X({legend:1},K),thead:M,ul:Q,acronym:L,b:J,a:J,blockquote:P,caption:L,i:J,u:J,tbody:M,s:L,address:X(D,I),tt:J,legend:L,q:L,pre:X(G,C),p:L,em:J,dfn:L};})(); +var FCKStyle=function(A){this.Element=(A.Element||'span').toLowerCase();this._StyleDesc=A;};FCKStyle.prototype={GetType:function(){var A=this.GetType_$;if (A!=undefined) return A;var B=this.Element;if (B=='#'||FCKListsLib.StyleBlockElements[B]) A=0;else if (FCKListsLib.StyleObjectElements[B]) A=2;else A=1;return (this.GetType_$=A);},ApplyToSelection:function(A){var B=new FCKDomRange(A);B.MoveToSelection();this.ApplyToRange(B,true);},ApplyToRange:function(A,B,C){switch (this.GetType()){case 0:this.ApplyToRange=this._ApplyBlockStyle;break;case 1:this.ApplyToRange=this._ApplyInlineStyle;break;default:return;};this.ApplyToRange(A,B,C);},ApplyToObject:function(A){if (!A) return;this.BuildElement(null,A);},RemoveFromSelection:function(A){var B=new FCKDomRange(A);B.MoveToSelection();this.RemoveFromRange(B,true);},RemoveFromRange:function(A,B,C){var D;var E=this._GetAttribsForComparison();var F=this._GetOverridesForComparison();if (A.CheckIsCollapsed()){var D=A.CreateBookmark(true);var H=A.GetBookmarkNode(D,true);var I=new FCKElementPath(H.parentNode);var J=[];var K=!FCKDomTools.GetNextSibling(H);var L=K||!FCKDomTools.GetPreviousSibling(H);var M;var N=-1;for (var i=0;i=0;i--){var E=D[i];for (var F in B){if (FCKDomTools.HasAttribute(E,F)){switch (F){case 'style':this._RemoveStylesFromElement(E);break;case 'class':if (FCKDomTools.GetAttributeValue(E,F)!=this.GetFinalAttributeValue(F)) continue;default:FCKDomTools.RemoveAttribute(E,F);}}};this._RemoveOverrides(E,C[this.Element]);this._RemoveNoAttribElement(E);};for (var G in C){if (G!=this.Element){D=A.getElementsByTagName(G);for (var i=D.length-1;i>=0;i--){var E=D[i];this._RemoveOverrides(E,C[G]);this._RemoveNoAttribElement(E);}}}},_RemoveStylesFromElement:function(A){var B=A.style.cssText;var C=this.GetFinalStyleValue();if (B.length>0&&C.length==0) return;C='(^|;)\\s*('+C.replace(/\s*([^ ]+):.*?(;|$)/g,'$1|').replace(/\|$/,'')+'):[^;]+';var D=new RegExp(C,'gi');B=B.replace(D,'').Trim();if (B.length==0||B==';') FCKDomTools.RemoveAttribute(A,'style');else A.style.cssText=B.replace(D,'');},_RemoveOverrides:function(A,B){var C=B&&B.Attributes;if (C){for (var i=0;i0) C.style.cssText=this.GetFinalStyleValue();return C;},_CompareAttributeValues:function(A,B,C){if (A=='style'&&B&&C){B=B.replace(/;$/,'').toLowerCase();C=C.replace(/;$/,'').toLowerCase();};return (B==C||((B===null||B==='')&&(C===null||C==='')))},GetFinalAttributeValue:function(A){var B=this._StyleDesc.Attributes;var B=B?B[A]:null;if (!B&&A=='style') return this.GetFinalStyleValue();if (B&&this._Variables) B=B.Replace(FCKRegexLib.StyleVariableAttName,this._GetVariableReplace,this);return B;},GetFinalStyleValue:function(){var A=this._GetStyleText();if (A.length>0&&this._Variables){A=A.Replace(FCKRegexLib.StyleVariableAttName,this._GetVariableReplace,this);A=FCKTools.NormalizeCssText(A);};return A;},_GetVariableReplace:function(){return this._Variables[arguments[2]]||arguments[0];},SetVariable:function(A,B){var C=this._Variables;if (!C) C=this._Variables={};this._Variables[A]=B;},_FromPre:function(A,B,C){var D=B.innerHTML;D=D.replace(/(\r\n|\r)/g,'\n');D=D.replace(/^[ \t]*\n/,'');D=D.replace(/\n$/,'');D=D.replace(/^[ \t]+|[ \t]+$/g,function(match,offset,s){if (match.length==1) return ' ';else if (offset==0) return new Array(match.length).join(' ')+' ';else return ' '+new Array(match.length).join(' ');});var E=new FCKHtmlIterator(D);var F=[];E.Each(function(isTag,value){if (!isTag){value=value.replace(/\n/g,'
    ');value=value.replace(/[ \t]{2,}/g,function (match){return new Array(match.length).join(' ')+' ';});};F.push(value);});C.innerHTML=F.join('');return C;},_ToPre:function(A,B,C){var D=B.innerHTML.Trim();D=D.replace(/[ \t\r\n]*(]*>)[ \t\r\n]*/gi,'
    ');var E=new FCKHtmlIterator(D);var F=[];E.Each(function(isTag,value){if (!isTag) value=value.replace(/([ \t\n\r]+| )/g,' ');else if (isTag&&value=='
    ') value='\n';F.push(value);});if (FCKBrowserInfo.IsIE){var G=A.createElement('div');G.appendChild(C);C.outerHTML='
    \n'+F.join('')+'
    ';C=G.removeChild(G.firstChild);}else C.innerHTML=F.join('');return C;},_CheckAndMergePre:function(A,B){if (A!=FCKDomTools.GetPreviousSourceElement(B,true)) return;var C=A.innerHTML.replace(/\n$/,'')+'\n\n'+B.innerHTML.replace(/^\n/,'');if (FCKBrowserInfo.IsIE) B.outerHTML='
    '+C+'
    ';else B.innerHTML=C;FCKDomTools.RemoveNode(A);},_CheckAndSplitPre:function(A){var B;var C=A.firstChild;C=C&&C.nextSibling;while (C){var D=C.nextSibling;if (D&&D.nextSibling&&C.nodeName.IEquals('br')&&D.nodeName.IEquals('br')){FCKDomTools.RemoveNode(C);C=D.nextSibling;FCKDomTools.RemoveNode(D);B=FCKDomTools.InsertAfterNode(B||A,FCKDomTools.CloneElement(A));continue;};if (B){C=C.previousSibling;FCKDomTools.MoveNode(C.nextSibling,B);};C=C.nextSibling;}},_ApplyBlockStyle:function(A,B,C){var D;if (B) D=A.CreateBookmark();var E=new FCKDomRangeIterator(A);E.EnforceRealBlocks=true;var F;var G=A.Window.document;var H;while((F=E.GetNextParagraph())){var I=this.BuildElement(G);var J=I.nodeName.IEquals('pre');var K=F.nodeName.IEquals('pre');var L=J&&!K;var M=!J&&K;if (L) I=this._ToPre(G,F,I);else if (M) I=this._FromPre(G,F,I);else FCKDomTools.MoveChildren(F,I);F.parentNode.insertBefore(I,F);FCKDomTools.RemoveNode(F);if (J){if (H) this._CheckAndMergePre(H,I);H=I;}else if (M) this._CheckAndSplitPre(I);};if (B) A.SelectBookmark(D);if (C) A.MoveToBookmark(D);},_ApplyInlineStyle:function(A,B,C){var D=A.Window.document;if (A.CheckIsCollapsed()){var E=this.BuildElement(D);A.InsertNode(E);A.MoveToPosition(E,2);A.Select();return;};var F=this.Element;var G=FCK.DTD[F]||FCK.DTD.span;var H=this._GetAttribsForComparison();var I;A.Expand('inline_elements');var J=A.CreateBookmark(true);var K=A.GetBookmarkNode(J,true);var L=A.GetBookmarkNode(J,false);A.Release(true);var M=FCKDomTools.GetNextSourceNode(K,true);while (M){var N=false;var O=M.nodeType;var P=O==1?M.nodeName.toLowerCase():null;if (!P||G[P]){if ((FCK.DTD[M.parentNode.nodeName.toLowerCase()]||FCK.DTD.span)[F]||!FCK.DTD[F]){if (!A.CheckHasRange()) A.SetStart(M,3);if (O!=1||M.childNodes.length==0){var Q=M;var R=Q.parentNode;while (Q==R.lastChild&&G[R.nodeName.toLowerCase()]){Q=R;};A.SetEnd(Q,4);if (Q==Q.parentNode.lastChild&&!G[Q.parentNode.nodeName.toLowerCase()]) N=true;}else{A.SetEnd(M,3);}}else N=true;}else N=true;M=FCKDomTools.GetNextSourceNode(M);if (M==L){M=null;N=true;};if (N&&A.CheckHasRange()&&!A.CheckIsCollapsed()){I=this.BuildElement(D);A.ExtractContents().AppendTo(I);if (I.innerHTML.RTrim().length>0){A.InsertNode(I);this.RemoveFromElement(I);this._MergeSiblings(I,this._GetAttribsForComparison());if (!FCKBrowserInfo.IsIE) I.normalize();};A.Release(true);}};this._FixBookmarkStart(K);if (B) A.SelectBookmark(J);if (C) A.MoveToBookmark(J);},_FixBookmarkStart:function(A){var B;while ((B=A.nextSibling)){if (B.nodeType==1&&FCKListsLib.InlineNonEmptyElements[B.nodeName.toLowerCase()]){if (!B.firstChild) FCKDomTools.RemoveNode(B);else FCKDomTools.MoveNode(A,B,true);continue;};if (B.nodeType==3&&B.length==0){FCKDomTools.RemoveNode(B);continue;};break;}},_MergeSiblings:function(A,B){if (!A||A.nodeType!=1||!FCKListsLib.InlineNonEmptyElements[A.nodeName.toLowerCase()]) return;this._MergeNextSibling(A,B);this._MergePreviousSibling(A,B);},_MergeNextSibling:function(A,B){var C=A.nextSibling;var D=(C&&C.nodeType==1&&C.getAttribute('_fck_bookmark'));if (D) C=C.nextSibling;if (C&&C.nodeType==1&&C.nodeName==A.nodeName){if (!B) B=this._CreateElementAttribsForComparison(A);if (this._CheckAttributesMatch(C,B)){var E=A.lastChild;if (D) FCKDomTools.MoveNode(A.nextSibling,A);FCKDomTools.MoveChildren(C,A);FCKDomTools.RemoveNode(C);if (E) this._MergeNextSibling(E);}}},_MergePreviousSibling:function(A,B){var C=A.previousSibling;var D=(C&&C.nodeType==1&&C.getAttribute('_fck_bookmark'));if (D) C=C.previousSibling;if (C&&C.nodeType==1&&C.nodeName==A.nodeName){if (!B) B=this._CreateElementAttribsForComparison(A);if (this._CheckAttributesMatch(C,B)){var E=A.firstChild;if (D) FCKDomTools.MoveNode(A.previousSibling,A,true);FCKDomTools.MoveChildren(C,A,true);FCKDomTools.RemoveNode(C);if (E) this._MergePreviousSibling(E);}}},_GetStyleText:function(){var A=this._StyleDesc.Styles;var B=(this._StyleDesc.Attributes?this._StyleDesc.Attributes['style']||'':'');if (B.length>0) B+=';';for (var C in A) B+=C+':'+A[C]+';';if (B.length>0&&!(/#\(/.test(B))){B=FCKTools.NormalizeCssText(B);};return (this._GetStyleText=function() { return B;})();},_GetAttribsForComparison:function(){var A=this._GetAttribsForComparison_$;if (A) return A;A={};var B=this._StyleDesc.Attributes;if (B){for (var C in B){A[C.toLowerCase()]=B[C].toLowerCase();}};if (this._GetStyleText().length>0){A['style']=this._GetStyleText().toLowerCase();};FCKTools.AppendLengthProperty(A,'_length');return (this._GetAttribsForComparison_$=A);},_GetOverridesForComparison:function(){var A=this._GetOverridesForComparison_$;if (A) return A;A={};var B=this._StyleDesc.Overrides;if (B){if (!FCKTools.IsArray(B)) B=[B];for (var i=0;i0) return true;};B=B.nextSibling;};return false;}}; +var FCKElementPath=function(A){var B=null;var C=null;var D=[];var e=A;while (e){if (e.nodeType==1){if (!this.LastElement) this.LastElement=e;var E=e.nodeName.toLowerCase();if (FCKBrowserInfo.IsIE&&e.scopeName!='HTML') E=e.scopeName.toLowerCase()+':'+E;if (!C){if (!B&&FCKListsLib.PathBlockElements[E]!=null) B=e;if (FCKListsLib.PathBlockLimitElements[E]!=null){if (!B&&E=='div'&&!FCKElementPath._CheckHasBlock(e)) B=e;else C=e;}};D.push(e);if (E=='body') break;};e=e.parentNode;};this.Block=B;this.BlockLimit=C;this.Elements=D;};FCKElementPath._CheckHasBlock=function(A){var B=A.childNodes;for (var i=0,count=B.length;i0){if (D.nodeType==3){var G=D.nodeValue.substr(0,E).Trim();if (G.length!=0) return A.IsStartOfBlock=false;}else F=D.childNodes[E-1];};if (!F) F=FCKDomTools.GetPreviousSourceNode(D,true,null,C);while (F){switch (F.nodeType){case 1:if (!FCKListsLib.InlineChildReqElements[F.nodeName.toLowerCase()]) return A.IsStartOfBlock=false;break;case 3:if (F.nodeValue.Trim().length>0) return A.IsStartOfBlock=false;};F=FCKDomTools.GetPreviousSourceNode(F,false,null,C);};return A.IsStartOfBlock=true;},CheckEndOfBlock:function(A){var B=this._Cache.IsEndOfBlock;if (B!=undefined) return B;var C=this.EndBlock||this.EndBlockLimit;var D=this._Range.endContainer;var E=this._Range.endOffset;var F;if (D.nodeType==3){var G=D.nodeValue;if (E0) return this._Cache.IsEndOfBlock=false;};F=FCKDomTools.GetNextSourceNode(F,false,null,C);};if (A) this.Select();return this._Cache.IsEndOfBlock=true;},CreateBookmark:function(A){var B={StartId:(new Date()).valueOf()+Math.floor(Math.random()*1000)+'S',EndId:(new Date()).valueOf()+Math.floor(Math.random()*1000)+'E'};var C=this.Window.document;var D;var E;var F;if (!this.CheckIsCollapsed()){E=C.createElement('span');E.style.display='none';E.id=B.EndId;E.setAttribute('_fck_bookmark',true);E.innerHTML=' ';F=this.Clone();F.Collapse(false);F.InsertNode(E);};D=C.createElement('span');D.style.display='none';D.id=B.StartId;D.setAttribute('_fck_bookmark',true);D.innerHTML=' ';F=this.Clone();F.Collapse(true);F.InsertNode(D);if (A){B.StartNode=D;B.EndNode=E;};if (E){this.SetStart(D,4);this.SetEnd(E,3);}else this.MoveToPosition(D,4);return B;},GetBookmarkNode:function(A,B){var C=this.Window.document;if (B) return A.StartNode||C.getElementById(A.StartId);else return A.EndNode||C.getElementById(A.EndId);},MoveToBookmark:function(A,B){var C=this.GetBookmarkNode(A,true);var D=this.GetBookmarkNode(A,false);this.SetStart(C,3);if (!B) FCKDomTools.RemoveNode(C);if (D){this.SetEnd(D,3);if (!B) FCKDomTools.RemoveNode(D);}else this.Collapse(true);this._UpdateElementInfo();},CreateBookmark2:function(){if (!this._Range) return { "Start":0,"End":0 };var A={"Start":[this._Range.startOffset],"End":[this._Range.endOffset]};var B=this._Range.startContainer.previousSibling;var C=this._Range.endContainer.previousSibling;var D=this._Range.startContainer;var E=this._Range.endContainer;while (B&&B.nodeType==3&&D.nodeType==3){A.Start[0]+=B.length;D=B;B=B.previousSibling;}while (C&&C.nodeType==3&&E.nodeType==3){A.End[0]+=C.length;E=C;C=C.previousSibling;};if (D.nodeType==1&&D.childNodes[A.Start[0]]&&D.childNodes[A.Start[0]].nodeType==3){var F=D.childNodes[A.Start[0]];var G=0;while (F.previousSibling&&F.previousSibling.nodeType==3){F=F.previousSibling;G+=F.length;};D=F;A.Start[0]=G;};if (E.nodeType==1&&E.childNodes[A.End[0]]&&E.childNodes[A.End[0]].nodeType==3){var F=E.childNodes[A.End[0]];var G=0;while (F.previousSibling&&F.previousSibling.nodeType==3){F=F.previousSibling;G+=F.length;};E=F;A.End[0]=G;};A.Start=FCKDomTools.GetNodeAddress(D,true).concat(A.Start);A.End=FCKDomTools.GetNodeAddress(E,true).concat(A.End);return A;},MoveToBookmark2:function(A){var B=FCKDomTools.GetNodeFromAddress(this.Window.document,A.Start.slice(0,-1),true);var C=FCKDomTools.GetNodeFromAddress(this.Window.document,A.End.slice(0,-1),true);this.Release(true);this._Range=new FCKW3CRange(this.Window.document);var D=A.Start[A.Start.length-1];var E=A.End[A.End.length-1];while (B.nodeType==3&&D>B.length){if (!B.nextSibling||B.nextSibling.nodeType!=3) break;D-=B.length;B=B.nextSibling;}while (C.nodeType==3&&E>C.length){if (!C.nextSibling||C.nextSibling.nodeType!=3) break;E-=C.length;C=C.nextSibling;};this._Range.setStart(B,D);this._Range.setEnd(C,E);this._UpdateElementInfo();},MoveToPosition:function(A,B){this.SetStart(A,B);this.Collapse(true);},SetStart:function(A,B,C){var D=this._Range;if (!D) D=this._Range=this.CreateRange();switch(B){case 1:D.setStart(A,0);break;case 2:D.setStart(A,A.childNodes.length);break;case 3:D.setStartBefore(A);break;case 4:D.setStartAfter(A);};if (!C) this._UpdateElementInfo();},SetEnd:function(A,B,C){var D=this._Range;if (!D) D=this._Range=this.CreateRange();switch(B){case 1:D.setEnd(A,0);break;case 2:D.setEnd(A,A.childNodes.length);break;case 3:D.setEndBefore(A);break;case 4:D.setEndAfter(A);};if (!C) this._UpdateElementInfo();},Expand:function(A){var B,oSibling;switch (A){case 'inline_elements':if (this._Range.startOffset==0){B=this._Range.startContainer;if (B.nodeType!=1) B=B.previousSibling?null:B.parentNode;if (B){while (FCKListsLib.InlineNonEmptyElements[B.nodeName.toLowerCase()]){this._Range.setStartBefore(B);if (B!=B.parentNode.firstChild) break;B=B.parentNode;}}};B=this._Range.endContainer;var C=this._Range.endOffset;if ((B.nodeType==3&&C>=B.nodeValue.length)||(B.nodeType==1&&C>=B.childNodes.length)||(B.nodeType!=1&&B.nodeType!=3)){if (B.nodeType!=1) B=B.nextSibling?null:B.parentNode;if (B){while (FCKListsLib.InlineNonEmptyElements[B.nodeName.toLowerCase()]){this._Range.setEndAfter(B);if (B!=B.parentNode.lastChild) break;B=B.parentNode;}}};break;case 'block_contents':case 'list_contents':var D=FCKListsLib.BlockBoundaries;if (A=='list_contents'||FCKConfig.EnterMode=='br') D=FCKListsLib.ListBoundaries;if (this.StartBlock&&FCKConfig.EnterMode!='br'&&A=='block_contents') this.SetStart(this.StartBlock,1);else{B=this._Range.startContainer;if (B.nodeType==1){var E=B.childNodes[this._Range.startOffset];if (E) B=FCKDomTools.GetPreviousSourceNode(E,true);else B=B.lastChild||B;}while (B&&(B.nodeType!=1||(B!=this.StartBlockLimit&&!D[B.nodeName.toLowerCase()]))){this._Range.setStartBefore(B);B=B.previousSibling||B.parentNode;}};if (this.EndBlock&&FCKConfig.EnterMode!='br'&&A=='block_contents'&&this.EndBlock.nodeName.toLowerCase()!='li') this.SetEnd(this.EndBlock,2);else{B=this._Range.endContainer;if (B.nodeType==1) B=B.childNodes[this._Range.endOffset]||B.lastChild;while (B&&(B.nodeType!=1||(B!=this.StartBlockLimit&&!D[B.nodeName.toLowerCase()]))){this._Range.setEndAfter(B);B=B.nextSibling||B.parentNode;};if (B&&B.nodeName.toLowerCase()=='br') this._Range.setEndAfter(B);};this._UpdateElementInfo();}},SplitBlock:function(A){var B=A||FCKConfig.EnterMode;if (!this._Range) this.MoveToSelection();if (this.StartBlockLimit==this.EndBlockLimit){var C=this.StartBlock;var D=this.EndBlock;var E=null;if (B!='br'){if (!C){C=this.FixBlock(true,B);D=this.EndBlock;};if (!D) D=this.FixBlock(false,B);};var F=(C!=null&&this.CheckStartOfBlock());var G=(D!=null&&this.CheckEndOfBlock());if (!this.CheckIsEmpty()) this.DeleteContents();if (C&&D&&C==D){if (G){E=new FCKElementPath(this.StartContainer);this.MoveToPosition(D,4);D=null;}else if (F){E=new FCKElementPath(this.StartContainer);this.MoveToPosition(C,3);C=null;}else{this.SetEnd(C,2);var H=this.ExtractContents();D=C.cloneNode(false);D.removeAttribute('id',false);H.AppendTo(D);FCKDomTools.InsertAfterNode(C,D);this.MoveToPosition(C,4);if (FCKBrowserInfo.IsGecko&&!C.nodeName.IEquals(['ul','ol'])) FCKTools.AppendBogusBr(C);}};return {PreviousBlock:C,NextBlock:D,WasStartOfBlock:F,WasEndOfBlock:G,ElementPath:E};};return null;},FixBlock:function(A,B){var C=this.CreateBookmark();this.Collapse(A);this.Expand('block_contents');var D=this.Window.document.createElement(B);this.ExtractContents().AppendTo(D);FCKDomTools.TrimNode(D);if (FCKDomTools.CheckIsEmptyElement(D,function(element) { return element.getAttribute('_fck_bookmark')!='true';})&&FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(D);this.InsertNode(D);this.MoveToBookmark(C);return D;},Release:function(A){if (!A) this.Window=null;this.StartNode=null;this.StartContainer=null;this.StartBlock=null;this.StartBlockLimit=null;this.EndNode=null;this.EndContainer=null;this.EndBlock=null;this.EndBlockLimit=null;this._Range=null;this._Cache=null;},CheckHasRange:function(){return!!this._Range;},GetTouchedStartNode:function(){var A=this._Range;var B=A.startContainer;if (A.collapsed||B.nodeType!=1) return B;return B.childNodes[A.startOffset]||B;},GetTouchedEndNode:function(){var A=this._Range;var B=A.endContainer;if (A.collapsed||B.nodeType!=1) return B;return B.childNodes[A.endOffset-1]||B;}}; +FCKDomRange.prototype.MoveToSelection=function(){this.Release(true);var A=this.Window.getSelection();if (A&&A.rangeCount>0){this._Range=FCKW3CRange.CreateFromRange(this.Window.document,A.getRangeAt(0));this._UpdateElementInfo();}else if (this.Window.document) this.MoveToElementStart(this.Window.document.body);};FCKDomRange.prototype.Select=function(){var A=this._Range;if (A){var B=A.startContainer;if (A.collapsed&&B.nodeType==1&&B.childNodes.length==0) B.appendChild(A._Document.createTextNode(''));var C=this.Window.document.createRange();C.setStart(B,A.startOffset);try{C.setEnd(A.endContainer,A.endOffset);}catch (e){if (e.toString().Contains('NS_ERROR_ILLEGAL_VALUE')){A.collapse(true);C.setEnd(A.endContainer,A.endOffset);}else throw(e);};var D=this.Window.getSelection();D.removeAllRanges();D.addRange(C);}};FCKDomRange.prototype.SelectBookmark=function(A){var B=this.Window.document.createRange();var C=this.GetBookmarkNode(A,true);var D=this.GetBookmarkNode(A,false);B.setStart(C.parentNode,FCKDomTools.GetIndexOf(C));FCKDomTools.RemoveNode(C);if (D){B.setEnd(D.parentNode,FCKDomTools.GetIndexOf(D));FCKDomTools.RemoveNode(D);};var E=this.Window.getSelection();E.removeAllRanges();E.addRange(B);}; +var FCKDomRangeIterator=function(A){this.Range=A;this.ForceBrBreak=false;this.EnforceRealBlocks=false;};FCKDomRangeIterator.CreateFromSelection=function(A){var B=new FCKDomRange(A);B.MoveToSelection();return new FCKDomRangeIterator(B);};FCKDomRangeIterator.prototype={GetNextParagraph:function(){var A;var B;var C;var D;var E;var F=this.ForceBrBreak?FCKListsLib.ListBoundaries:FCKListsLib.BlockBoundaries;if (!this._LastNode){var B=this.Range.Clone();B.Expand(this.ForceBrBreak?'list_contents':'block_contents');this._NextNode=B.GetTouchedStartNode();this._LastNode=B.GetTouchedEndNode();B=null;};var H=this._NextNode;var I=this._LastNode;this._NextNode=null;while (H){var J=false;var K=(H.nodeType!=1);var L=false;if (!K){var M=H.nodeName.toLowerCase();if (F[M]&&(!FCKBrowserInfo.IsIE||H.scopeName=='HTML')){if (M=='br') K=true;else if (!B&&H.childNodes.length==0&&M!='hr'){A=H;C=H==I;break;};if (B){B.SetEnd(H,3,true);if (M!='br') this._NextNode=FCKDomTools.GetNextSourceNode(H,true,null,I)||H;};J=true;}else{if (H.firstChild){if (!B){B=new FCKDomRange(this.Range.Window);B.SetStart(H,3,true);};H=H.firstChild;continue;};K=true;}}else if (H.nodeType==3){if (/^[\r\n\t ]+$/.test(H.nodeValue)) K=false;};if (K&&!B){B=new FCKDomRange(this.Range.Window);B.SetStart(H,3,true);};C=((!J||K)&&H==I);if (B&&!J){while (!H.nextSibling&&!C){var N=H.parentNode;if (F[N.nodeName.toLowerCase()]){J=true;C=C||(N==I);break;};H=N;K=true;C=(H==I);L=true;}};if (K) B.SetEnd(H,4,true);if ((J||C)&&B){B._UpdateElementInfo();if (B.StartNode==B.EndNode&&B.StartNode.parentNode==B.StartBlockLimit&&B.StartNode.getAttribute&&B.StartNode.getAttribute('_fck_bookmark')) B=null;else break;};if (C) break;H=FCKDomTools.GetNextSourceNode(H,L,null,I);};if (!A){if (!B){this._NextNode=null;return null;};A=B.StartBlock;if (!A&&!this.EnforceRealBlocks&&B.StartBlockLimit.nodeName.IEquals('DIV','TH','TD')&&B.CheckStartOfBlock()&&B.CheckEndOfBlock()){A=B.StartBlockLimit;}else if (!A||(this.EnforceRealBlocks&&A.nodeName.toLowerCase()=='li')){A=this.Range.Window.document.createElement(FCKConfig.EnterMode=='p'?'p':'div');B.ExtractContents().AppendTo(A);FCKDomTools.TrimNode(A);B.InsertNode(A);D=true;E=true;}else if (A.nodeName.toLowerCase()!='li'){if (!B.CheckStartOfBlock()||!B.CheckEndOfBlock()){A=A.cloneNode(false);B.ExtractContents().AppendTo(A);FCKDomTools.TrimNode(A);var O=B.SplitBlock();D=!O.WasStartOfBlock;E=!O.WasEndOfBlock;B.InsertNode(A);}}else if (!C){this._NextNode=A==I?null:FCKDomTools.GetNextSourceNode(B.EndNode,true,null,I);return A;}};if (D){var P=A.previousSibling;if (P&&P.nodeType==1){if (P.nodeName.toLowerCase()=='br') P.parentNode.removeChild(P);else if (P.lastChild&&P.lastChild.nodeName.IEquals('br')) P.removeChild(P.lastChild);}};if (E){var Q=A.lastChild;if (Q&&Q.nodeType==1&&Q.nodeName.toLowerCase()=='br') A.removeChild(Q);};if (!this._NextNode) this._NextNode=(C||A==I)?null:FCKDomTools.GetNextSourceNode(A,true,null,I);return A;}}; +var FCKDocumentFragment=function(A,B){this.RootNode=B||A.createDocumentFragment();};FCKDocumentFragment.prototype={AppendTo:function(A){A.appendChild(this.RootNode);},AppendHtml:function(A){var B=this.RootNode.ownerDocument.createElement('div');B.innerHTML=A;FCKDomTools.MoveChildren(B,this.RootNode);},InsertAfterNode:function(A){FCKDomTools.InsertAfterNode(A,this.RootNode);}}; +var FCKW3CRange=function(A){this._Document=A;this.startContainer=null;this.startOffset=null;this.endContainer=null;this.endOffset=null;this.collapsed=true;};FCKW3CRange.CreateRange=function(A){return new FCKW3CRange(A);};FCKW3CRange.CreateFromRange=function(A,B){var C=FCKW3CRange.CreateRange(A);C.setStart(B.startContainer,B.startOffset);C.setEnd(B.endContainer,B.endOffset);return C;};FCKW3CRange.prototype={_UpdateCollapsed:function(){this.collapsed=(this.startContainer==this.endContainer&&this.startOffset==this.endOffset);},setStart:function(A,B){this.startContainer=A;this.startOffset=B;if (!this.endContainer){this.endContainer=A;this.endOffset=B;};this._UpdateCollapsed();},setEnd:function(A,B){this.endContainer=A;this.endOffset=B;if (!this.startContainer){this.startContainer=A;this.startOffset=B;};this._UpdateCollapsed();},setStartAfter:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setStartBefore:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A));},setEndAfter:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setEndBefore:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A));},collapse:function(A){if (A){this.endContainer=this.startContainer;this.endOffset=this.startOffset;}else{this.startContainer=this.endContainer;this.startOffset=this.endOffset;};this.collapsed=true;},selectNodeContents:function(A){this.setStart(A,0);this.setEnd(A,A.nodeType==3?A.data.length:A.childNodes.length);},insertNode:function(A){var B=this.startContainer;var C=this.startOffset;if (B.nodeType==3){B.splitText(C);if (B==this.endContainer) this.setEnd(B.nextSibling,this.endOffset-this.startOffset);FCKDomTools.InsertAfterNode(B,A);return;}else{B.insertBefore(A,B.childNodes[C]||null);if (B==this.endContainer){this.endOffset++;this.collapsed=false;}}},deleteContents:function(){if (this.collapsed) return;this._ExecContentsAction(0);},extractContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(1,A);return A;},cloneContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(2,A);return A;},_ExecContentsAction:function(A,B){var C=this.startContainer;var D=this.endContainer;var E=this.startOffset;var F=this.endOffset;var G=false;var H=false;if (D.nodeType==3) D=D.splitText(F);else{if (D.childNodes.length>0){if (F>D.childNodes.length-1){D=FCKDomTools.InsertAfterNode(D.lastChild,this._Document.createTextNode(''));H=true;}else D=D.childNodes[F];}};if (C.nodeType==3){C.splitText(E);if (C==D) D=C.nextSibling;}else{if (E==0){C=C.insertBefore(this._Document.createTextNode(''),C.firstChild);G=true;}else if (E>C.childNodes.length-1){C=C.appendChild(this._Document.createTextNode(''));G=true;}else C=C.childNodes[E].previousSibling;};var I=FCKDomTools.GetParents(C);var J=FCKDomTools.GetParents(D);var i,topStart,topEnd;for (i=0;i0&&levelStartNode!=D) levelClone=K.appendChild(levelStartNode.cloneNode(levelStartNode==D));if (!I[k]||levelStartNode.parentNode!=I[k].parentNode){currentNode=levelStartNode.previousSibling;while(currentNode){if (currentNode==I[k]||currentNode==C) break;currentSibling=currentNode.previousSibling;if (A==2) K.insertBefore(currentNode.cloneNode(true),K.firstChild);else{currentNode.parentNode.removeChild(currentNode);if (A==1) K.insertBefore(currentNode,K.firstChild);};currentNode=currentSibling;}};if (K) K=levelClone;};if (A==2){var L=this.startContainer;if (L.nodeType==3){L.data+=L.nextSibling.data;L.parentNode.removeChild(L.nextSibling);};var M=this.endContainer;if (M.nodeType==3&&M.nextSibling){M.data+=M.nextSibling.data;M.parentNode.removeChild(M.nextSibling);}}else{if (topStart&&topEnd&&(C.parentNode!=topStart.parentNode||D.parentNode!=topEnd.parentNode)){var N=FCKDomTools.GetIndexOf(topEnd);if (G&&topEnd.parentNode==C.parentNode) N--;this.setStart(topEnd.parentNode,N);};this.collapse(true);};if(G) C.parentNode.removeChild(C);if(H&&D.parentNode) D.parentNode.removeChild(D);},cloneRange:function(){return FCKW3CRange.CreateFromRange(this._Document,this);}}; +var FCKEnterKey=function(A,B,C,D){this.Window=A;this.EnterMode=B||'p';this.ShiftEnterMode=C||'br';var E=new FCKKeystrokeHandler(false);E._EnterKey=this;E.OnKeystroke=FCKEnterKey_OnKeystroke;E.SetKeystrokes([[13,'Enter'],[SHIFT+13,'ShiftEnter'],[8,'Backspace'],[CTRL+8,'CtrlBackspace'],[46,'Delete']]);this.TabText='';if (D>0||FCKBrowserInfo.IsSafari){while (D--) this.TabText+='\xa0';E.SetKeystrokes([9,'Tab']);};E.AttachToElement(A.document);};function FCKEnterKey_OnKeystroke(A,B){var C=this._EnterKey;try{switch (B){case 'Enter':return C.DoEnter();break;case 'ShiftEnter':return C.DoShiftEnter();break;case 'Backspace':return C.DoBackspace();break;case 'Delete':return C.DoDelete();break;case 'Tab':return C.DoTab();break;case 'CtrlBackspace':return C.DoCtrlBackspace();break;}}catch (e){};return false;};FCKEnterKey.prototype.DoEnter=function(A,B){FCKUndo.SaveUndoStep();this._HasShift=(B===true);var C=FCKSelection.GetParentElement();var D=new FCKElementPath(C);var E=A||this.EnterMode;if (E=='br'||D.Block&&D.Block.tagName.toLowerCase()=='pre') return this._ExecuteEnterBr();else return this._ExecuteEnterBlock(E);};FCKEnterKey.prototype.DoShiftEnter=function(){return this.DoEnter(this.ShiftEnterMode,true);};FCKEnterKey.prototype.DoBackspace=function(){var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (FCKBrowserInfo.IsIE&&this._CheckIsAllContentsIncluded(B,this.Window.document.body)){this._FixIESelectAllBug(B);return true;};var C=B.CheckIsCollapsed();if (!C){if (FCKBrowserInfo.IsIE&&this.Window.document.selection.type.toLowerCase()=="control"){var D=this.Window.document.selection.createRange();for (var i=D.length-1;i>=0;i--){var E=D.item(i);E.parentNode.removeChild(E);};return true;};return false;};if (FCKBrowserInfo.IsIE){var F=FCKDomTools.GetPreviousSourceElement(B.StartNode,true);if (F&&F.nodeName.toLowerCase()=='br'){var G=B.Clone();G.SetStart(F,4);if (G.CheckIsEmpty()){F.parentNode.removeChild(F);return true;}}};var H=B.StartBlock;var I=B.EndBlock;if (B.StartBlockLimit==B.EndBlockLimit&&H&&I){if (!C){var J=B.CheckEndOfBlock();B.DeleteContents();if (H!=I){B.SetStart(I,1);B.SetEnd(I,1);};B.Select();A=(H==I);};if (B.CheckStartOfBlock()){var K=B.StartBlock;var L=FCKDomTools.GetPreviousSourceElement(K,true,['BODY',B.StartBlockLimit.nodeName],['UL','OL']);A=this._ExecuteBackspace(B,L,K);}else if (FCKBrowserInfo.IsGeckoLike){B.Select();}};B.Release();return A;};FCKEnterKey.prototype.DoCtrlBackspace=function(){FCKUndo.SaveUndoStep();var A=new FCKDomRange(this.Window);A.MoveToSelection();if (FCKBrowserInfo.IsIE&&this._CheckIsAllContentsIncluded(A,this.Window.document.body)){this._FixIESelectAllBug(A);return true;};return false;};FCKEnterKey.prototype._ExecuteBackspace=function(A,B,C){var D=false;if (!B&&C&&C.nodeName.IEquals('LI')&&C.parentNode.parentNode.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};if (B&&B.nodeName.IEquals('LI')){var E=FCKDomTools.GetLastChild(B,['UL','OL']);while (E){B=FCKDomTools.GetLastChild(E,'LI');E=FCKDomTools.GetLastChild(B,['UL','OL']);}};if (B&&C){if (C.nodeName.IEquals('LI')&&!B.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};var F=C.parentNode;var G=B.nodeName.toLowerCase();if (FCKListsLib.EmptyElements[G]!=null||G=='table'){FCKDomTools.RemoveNode(B);D=true;}else{FCKDomTools.RemoveNode(C);while (F.innerHTML.Trim().length==0){var H=F.parentNode;H.removeChild(F);F=H;};FCKDomTools.LTrimNode(C);FCKDomTools.RTrimNode(B);A.SetStart(B,2,true);A.Collapse(true);var I=A.CreateBookmark(true);if (!C.tagName.IEquals(['TABLE'])) FCKDomTools.MoveChildren(C,B);A.SelectBookmark(I);D=true;}};return D;};FCKEnterKey.prototype.DoDelete=function(){FCKUndo.SaveUndoStep();var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (FCKBrowserInfo.IsIE&&this._CheckIsAllContentsIncluded(B,this.Window.document.body)){this._FixIESelectAllBug(B);return true;};if (B.CheckIsCollapsed()&&B.CheckEndOfBlock(FCKBrowserInfo.IsGeckoLike)){var C=B.StartBlock;var D=FCKTools.GetElementAscensor(C,'td');var E=FCKDomTools.GetNextSourceElement(C,true,[B.StartBlockLimit.nodeName],['UL','OL','TR'],true);if (D){var F=FCKTools.GetElementAscensor(E,'td');if (F!=D) return true;};A=this._ExecuteBackspace(B,C,E);};B.Release();return A;};FCKEnterKey.prototype.DoTab=function(){var A=new FCKDomRange(this.Window);A.MoveToSelection();var B=A._Range.startContainer;while (B){if (B.nodeType==1){var C=B.tagName.toLowerCase();if (C=="tr"||C=="td"||C=="th"||C=="tbody"||C=="table") return false;else break;};B=B.parentNode;};if (this.TabText){A.DeleteContents();A.InsertNode(this.Window.document.createTextNode(this.TabText));A.Collapse(false);A.Select();};return true;};FCKEnterKey.prototype._ExecuteEnterBlock=function(A,B){var C=B||new FCKDomRange(this.Window);var D=C.SplitBlock(A);if (D){var E=D.PreviousBlock;var F=D.NextBlock;var G=D.WasStartOfBlock;var H=D.WasEndOfBlock;if (F){if (F.parentNode.nodeName.IEquals('li')){FCKDomTools.BreakParent(F,F.parentNode);FCKDomTools.MoveNode(F,F.nextSibling,true);}}else if (E&&E.parentNode.nodeName.IEquals('li')){FCKDomTools.BreakParent(E,E.parentNode);C.MoveToElementEditStart(E.nextSibling);FCKDomTools.MoveNode(E,E.previousSibling);};if (!G&&!H){if (F.nodeName.IEquals('li')&&F.firstChild&&F.firstChild.nodeName.IEquals(['ul','ol'])) F.insertBefore(FCKTools.GetElementDocument(F).createTextNode('\xa0'),F.firstChild);if (F) C.MoveToElementEditStart(F);}else{if (G&&H&&E.tagName.toUpperCase()=='LI'){C.MoveToElementStart(E);this._OutdentWithSelection(E,C);C.Release();return true;};var I;if (E){var J=E.tagName.toUpperCase();if (!this._HasShift&&!(/^H[1-6]$/).test(J)){I=FCKDomTools.CloneElement(E);}}else if (F) I=FCKDomTools.CloneElement(F);if (!I) I=this.Window.document.createElement(A);var K=D.ElementPath;if (K){for (var i=0,len=K.Elements.length;i=0&&(C=B[i--])){if (C.name.length>0){if (C.innerHTML!==''){if (FCKBrowserInfo.IsIE) C.className+=' FCK__AnchorC';}else{var D=FCKDocumentProcessor_CreateFakeImage('FCK__Anchor',C.cloneNode(true));D.setAttribute('_fckanchor','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}}}};var FCKPageBreaksProcessor=FCKDocumentProcessor.AppendNew();FCKPageBreaksProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('DIV');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.style.pageBreakAfter=='always'&&C.childNodes.length==1&&C.childNodes[0].style&&C.childNodes[0].style.display=='none'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',C.cloneNode(true));C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}};var FCKEmbedAndObjectProcessor=(function(){var A=[];var B=function(el){var C=el.cloneNode(true);var D;var E=D=FCKDocumentProcessor_CreateFakeImage('FCK__UnknownObject',C);FCKEmbedAndObjectProcessor.RefreshView(E,el);for (var i=0;i=0;i--) B(G[i]);};var H=function(doc){F('object',doc);F('embed',doc);};return FCKTools.Merge(FCKDocumentProcessor.AppendNew(),{ProcessDocument:function(doc){if (FCKBrowserInfo.IsGecko) FCKTools.RunFunction(H,this,[doc]);else H(doc);},RefreshView:function(placeHolder,original){if (original.getAttribute('width')>0) placeHolder.style.width=FCKTools.ConvertHtmlSizeToStyle(original.getAttribute('width'));if (original.getAttribute('height')>0) placeHolder.style.height=FCKTools.ConvertHtmlSizeToStyle(original.getAttribute('height'));},AddCustomHandler:function(func){A.push(func);}});})();FCK.GetRealElement=function(A){var e=FCKTempBin.Elements[A.getAttribute('_fckrealelement')];if (A.getAttribute('_fckflash')){if (A.style.width.length>0) e.width=FCKTools.ConvertStyleSizeToHtml(A.style.width);if (A.style.height.length>0) e.height=FCKTools.ConvertStyleSizeToHtml(A.style.height);};return e;};if (FCKBrowserInfo.IsIE){FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('HR');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){var D=A.createElement('hr');D.mergeAttributes(C,true);FCKDomTools.InsertAfterNode(C,D);C.parentNode.removeChild(C);}}};FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('INPUT');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.type=='hidden'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__InputHidden',C.cloneNode(true));D.setAttribute('_fckinputhidden','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}};FCKEmbedAndObjectProcessor.AddCustomHandler(function(A,B){if (!(A.nodeName.IEquals('embed')&&(A.type=='application/x-shockwave-flash'||/\.swf($|#|\?)/i.test(A.src)))) return;B.className='FCK__Flash';B.setAttribute('_fckflash','true',0);});if (FCKBrowserInfo.IsSafari){FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByClassName?A.getElementsByClassName('Apple-style-span'):Array.prototype.filter.call(A.getElementsByTagName('span'),function(item){ return item.className=='Apple-style-span';});for (var i=B.length-1;i>=0;i--) FCKDomTools.RemoveNode(B[i],true);}}; +var FCKSelection=FCK.Selection={GetParentBlock:function(){var A=this.GetParentElement();while (A){if (FCKListsLib.BlockBoundaries[A.nodeName.toLowerCase()]) break;A=A.parentNode;};return A;},ApplyStyle:function(A){FCKStyles.ApplyStyle(new FCKStyle(A));}}; +FCKSelection.GetType=function(){var A='Text';var B;try { B=this.GetSelection();} catch (e) {};if (B&&B.rangeCount==1){var C=B.getRangeAt(0);if (C.startContainer==C.endContainer&&(C.endOffset-C.startOffset)==1&&C.startContainer.nodeType==1&&FCKListsLib.StyleObjectElements[C.startContainer.childNodes[C.startOffset].nodeName.toLowerCase()]){A='Control';}};return A;};FCKSelection.GetSelectedElement=function(){var A=!!FCK.EditorWindow&&this.GetSelection();if (!A||A.rangeCount<1) return null;var B=A.getRangeAt(0);if (B.startContainer!=B.endContainer||B.startContainer.nodeType!=1||B.startOffset!=B.endOffset-1) return null;var C=B.startContainer.childNodes[B.startOffset];if (C.nodeType!=1) return null;return C;};FCKSelection.GetParentElement=function(){if (this.GetType()=='Control') return FCKSelection.GetSelectedElement().parentNode;else{var A=this.GetSelection();if (A){if (A.anchorNode&&A.anchorNode==A.focusNode){var B=A.getRangeAt(0);if (B.collapsed||B.startContainer.nodeType==3) return A.anchorNode.parentNode;else return A.anchorNode;};var C=new FCKElementPath(A.anchorNode);var D=new FCKElementPath(A.focusNode);var E=null;var F=null;if (C.Elements.length>D.Elements.length){E=C.Elements;F=D.Elements;}else{E=D.Elements;F=C.Elements;};var G=E.length-F.length;for(var i=0;i0){var C=B.getRangeAt(A?0:(B.rangeCount-1));var D=A?C.startContainer:C.endContainer;return (D.nodeType==1?D:D.parentNode);}};return null;};FCKSelection.SelectNode=function(A){var B=FCK.EditorDocument.createRange();B.selectNode(A);var C=this.GetSelection();C.removeAllRanges();C.addRange(B);};FCKSelection.Collapse=function(A){var B=this.GetSelection();if (A==null||A===true) B.collapseToStart();else B.collapseToEnd();};FCKSelection.HasAncestorNode=function(A){var B=this.GetSelectedElement();if (!B&&FCK.EditorWindow){try { B=this.GetSelection().getRangeAt(0).startContainer;}catch(e){}}while (B){if (B.nodeType==1&&B.nodeName.IEquals(A)) return true;B=B.parentNode;};return false;};FCKSelection.MoveToAncestorNode=function(A){var B;var C=this.GetSelectedElement();if (!C) C=this.GetSelection().getRangeAt(0).startContainer;while (C){if (C.nodeName.IEquals(A)) return C;C=C.parentNode;};return null;};FCKSelection.Delete=function(){var A=this.GetSelection();for (var i=0;i=0;i--){if (C[i]) FCKTableHandler.DeleteRows(C[i]);};return;};var E=FCKTools.GetElementAscensor(A,'TABLE');if (E.rows.length==1){FCKTableHandler.DeleteTable(E);return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteTable=function(A){if (!A){A=FCKSelection.GetSelectedElement();if (!A||A.tagName!='TABLE') A=FCKSelection.MoveToAncestorNode('TABLE');};if (!A) return;FCKSelection.SelectNode(A);FCKSelection.Collapse();if (A.parentNode.childNodes.length==1) A.parentNode.parentNode.removeChild(A.parentNode);else A.parentNode.removeChild(A);};FCKTableHandler.InsertColumn=function(A){var B=null;var C=this.GetSelectedCells();if (C&&C.length) B=C[A?0:(C.length-1)];if (!B) return;var D=FCKTools.GetElementAscensor(B,'TABLE');var E=B.cellIndex;for (var i=0;i=0;i--){if (B[i]) FCKTableHandler.DeleteColumns(B[i]);};return;};if (!A) return;var C=FCKTools.GetElementAscensor(A,'TABLE');var D=A.cellIndex;for (var i=C.rows.length-1;i>=0;i--){var E=C.rows[i];if (D==0&&E.cells.length==1){FCKTableHandler.DeleteRows(E);continue;};if (E.cells[D]) E.removeChild(E.cells[D]);}};FCKTableHandler.InsertCell=function(A,B){var C=null;var D=this.GetSelectedCells();if (D&&D.length) C=D[B?0:(D.length-1)];if (!C) return null;var E=FCK.EditorDocument.createElement('TD');if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(E);if (!B&&C.cellIndex==C.parentNode.cells.length-1) C.parentNode.appendChild(E);else C.parentNode.insertBefore(E,B?C:C.nextSibling);return E;};FCKTableHandler.DeleteCell=function(A){if (A.parentNode.cells.length==1){FCKTableHandler.DeleteRows(A.parentNode);return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteCells=function(){var A=FCKTableHandler.GetSelectedCells();for (var i=A.length-1;i>=0;i--){FCKTableHandler.DeleteCell(A[i]);}};FCKTableHandler._MarkCells=function(A,B){for (var i=0;i=E.height){for (D=F;D0){var L=K.removeChild(K.firstChild);if (L.nodeType!=1||(L.getAttribute('type',2)!='_moz'&&L.getAttribute('_moz_dirty')!=null)){I.appendChild(L);J++;}}};if (J>0) I.appendChild(FCK.EditorDocument.createElement('br'));};this._ReplaceCellsByMarker(C,'_SelectedCells',B);this._UnmarkCells(A,'_SelectedCells');this._InstallTableMap(C,B.parentNode.parentNode.parentNode);B.appendChild(I);if (FCKBrowserInfo.IsGeckoLike&&(!B.firstChild)) FCKTools.AppendBogusBr(B);this._MoveCaretToCell(B,false);};FCKTableHandler.MergeRight=function(){var A=this.GetMergeRightTarget();if (A==null) return;var B=A.refCell;var C=A.tableMap;var D=A.nextCell;var E=FCK.EditorDocument.createDocumentFragment();while (D&&D.childNodes&&D.childNodes.length>0) E.appendChild(D.removeChild(D.firstChild));D.parentNode.removeChild(D);B.appendChild(E);this._MarkCells([D],'_Replace');this._ReplaceCellsByMarker(C,'_Replace',B);this._InstallTableMap(C,B.parentNode.parentNode.parentNode);this._MoveCaretToCell(B,false);};FCKTableHandler.MergeDown=function(){var A=this.GetMergeDownTarget();if (A==null) return;var B=A.refCell;var C=A.tableMap;var D=A.nextCell;var E=FCKTools.GetElementDocument(B).createDocumentFragment();while (D&&D.childNodes&&D.childNodes.length>0) E.appendChild(D.removeChild(D.firstChild));if (E.firstChild) E.insertBefore(FCK.EditorDocument.createElement('br'),E.firstChild);B.appendChild(E);this._MarkCells([D],'_Replace');this._ReplaceCellsByMarker(C,'_Replace',B);this._InstallTableMap(C,B.parentNode.parentNode.parentNode);this._MoveCaretToCell(B,false);};FCKTableHandler.HorizontalSplitCell=function(){var A=FCKTableHandler.GetSelectedCells();if (A.length!=1) return;var B=A[0];var C=this._CreateTableMap(B);var D=B.parentNode.rowIndex;var E=FCKTableHandler._GetCellIndexSpan(C,D,B);var F=isNaN(B.colSpan)?1:B.colSpan;if (F>1){var G=Math.ceil(F/2);var H=FCK.EditorDocument.createElement(B.nodeName);if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(H);var I=E+G;var J=E+F;var K=isNaN(B.rowSpan)?1:B.rowSpan;for (var r=D;r1){B.rowSpan=Math.ceil(G/2);var H=D+Math.ceil(G/2);var I=C[H];var J=null;for (var i=E+1;i1) K.colSpan=F;if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(K);B.parentNode.parentNode.parentNode.rows[H].insertBefore(K,J);}else{var L=B.parentNode.sectionRowIndex+1;var M=FCK.EditorDocument.createElement('tr');var N=B.parentNode.parentNode;if (N.rows.length>L) N.insertBefore(M,N.rows[L]);else N.appendChild(M);for (var i=0;i1) K.colSpan=F;if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(K);M.appendChild(K);}};FCKTableHandler._GetCellIndexSpan=function(A,B,C){if (A.lengthE) E=j;if (D._colScanned===true) continue;if (A[i][j-1]==D) D.colSpan++;if (A[i][j+1]!=D) D._colScanned=true;}};for (var i=0;i<=E;i++){for (var j=0;j 
    ';var A=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',e);var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=B.SplitBlock();B.InsertNode(A);FCK.Events.FireEvent('OnSelectionChange');};FCKPageBreakCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;return 0;};var FCKUnlinkCommand=function(){this.Name='Unlink';};FCKUnlinkCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();if (FCKBrowserInfo.IsGeckoLike){var A=FCK.Selection.MoveToAncestorNode('A');if (A) FCKTools.RemoveOuterTags(A);return;};FCK.ExecuteNamedCommand(this.Name);};FCKUnlinkCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;var A=FCK.GetNamedCommandState(this.Name);if (A==0&&FCK.EditMode==0){var B=FCKSelection.MoveToAncestorNode('A');var C=(B&&B.name.length>0&&B.href.length==0);if (C) A=-1;};return A;};var FCKVisitLinkCommand=function(){this.Name='VisitLink';};FCKVisitLinkCommand.prototype={GetState:function(){if (FCK.EditMode!=0) return -1;var A=FCK.GetNamedCommandState('Unlink');if (A==0){var B=FCKSelection.MoveToAncestorNode('A');if (!B.href) A=-1;};return A;},Execute:function(){var A=FCKSelection.MoveToAncestorNode('A');var B=A.getAttribute('_fcksavedurl')||A.getAttribute('href',2);if (!/:\/\//.test(B)){var C=FCKConfig.BaseHref;var D=FCK.GetInstanceObject('parent');if (!C){C=D.document.location.href;C=C.substring(0,C.lastIndexOf('/')+1);};if (/^\//.test(B)){try{C=C.match(/^.*:\/\/+[^\/]+/)[0];}catch (e){C=D.document.location.protocol+'://'+D.parent.document.location.host;}};B=C+B;};if (!window.open(B,'_blank')) alert(FCKLang.VisitLinkBlocked);}};var FCKSelectAllCommand=function(){this.Name='SelectAll';};FCKSelectAllCommand.prototype.Execute=function(){if (FCK.EditMode==0){FCK.ExecuteNamedCommand('SelectAll');}else{var A=FCK.EditingArea.Textarea;if (FCKBrowserInfo.IsIE){A.createTextRange().execCommand('SelectAll');}else{A.selectionStart=0;A.selectionEnd=A.value.length;};A.focus();}};FCKSelectAllCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;return 0;};var FCKPasteCommand=function(){this.Name='Paste';};FCKPasteCommand.prototype={Execute:function(){if (FCKBrowserInfo.IsIE) FCK.Paste();else FCK.ExecuteNamedCommand('Paste');},GetState:function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('Paste');}};var FCKRuleCommand=function(){this.Name='Rule';};FCKRuleCommand.prototype={Execute:function(){FCKUndo.SaveUndoStep();FCK.InsertElement('hr');},GetState:function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('InsertHorizontalRule');}};var FCKCutCopyCommand=function(A){this.Name=A?'Cut':'Copy';};FCKCutCopyCommand.prototype={Execute:function(){var A=false;if (FCKBrowserInfo.IsIE){var B=function(){A=true;};var C='on'+this.Name.toLowerCase();FCK.EditorDocument.body.attachEvent(C,B);FCK.ExecuteNamedCommand(this.Name);FCK.EditorDocument.body.detachEvent(C,B);}else{try{FCK.ExecuteNamedCommand(this.Name);A=true;}catch(e){}};if (!A) alert(FCKLang['PasteError'+this.Name]);},GetState:function(){return FCK.EditMode!=0?-1:FCK.GetNamedCommandState('Cut');}};var FCKAnchorDeleteCommand=function(){this.Name='AnchorDelete';};FCKAnchorDeleteCommand.prototype={Execute:function(){if (FCK.Selection.GetType()=='Control'){FCK.Selection.Delete();}else{var A=FCK.Selection.GetSelectedElement();if (A){if (A.tagName=='IMG'&&A.getAttribute('_fckanchor')) oAnchor=FCK.GetRealElement(A);else A=null;};if (!A){oAnchor=FCK.Selection.MoveToAncestorNode('A');if (oAnchor) FCK.Selection.SelectNode(oAnchor);};if (oAnchor.href.length!=0){oAnchor.removeAttribute('name');if (FCKBrowserInfo.IsIE) oAnchor.className=oAnchor.className.replace(FCKRegexLib.FCK_Class,'');return;};if (A){A.parentNode.removeChild(A);return;};if (oAnchor.innerHTML.length==0){oAnchor.parentNode.removeChild(oAnchor);return;};FCKTools.RemoveOuterTags(oAnchor);};if (FCKBrowserInfo.IsGecko) FCK.Selection.Collapse(true);},GetState:function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('Unlink');}};var FCKDeleteDivCommand=function(){};FCKDeleteDivCommand.prototype={GetState:function(){if (FCK.EditMode!=0) return -1;var A=FCKSelection.GetParentElement();var B=new FCKElementPath(A);return B.BlockLimit&&B.BlockLimit.nodeName.IEquals('div')?0:-1;},Execute:function(){FCKUndo.SaveUndoStep();var A=FCKDomTools.GetSelectedDivContainers();var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=B.CreateBookmark();for (var i=0;i\n \n
    \n '+FCKLang.ColorAutomatic+'\n \n ';FCKTools.AddEventListenerEx(C,'click',FCKTextColorCommand_AutoOnClick,this);if (!FCKBrowserInfo.IsIE) C.style.width='96%';var G=FCKConfig.FontColors.toString().split(',');var H=0;while (H
    ';if (H>=G.length) C.style.visibility='hidden';else FCKTools.AddEventListenerEx(C,'click',FCKTextColorCommand_OnClick,[this,L]);}};if (FCKConfig.EnableMoreFontColors){E=D.insertRow(-1).insertCell(-1);E.colSpan=8;C=E.appendChild(CreateSelectionDiv());C.innerHTML='
    '+FCKLang.ColorMoreColors+'
    ';FCKTools.AddEventListenerEx(C,'click',FCKTextColorCommand_MoreOnClick,this);if (!FCKBrowserInfo.IsIE) C.style.width='96%';}}; +var FCKPastePlainTextCommand=function(){this.Name='PasteText';};FCKPastePlainTextCommand.prototype.Execute=function(){FCK.PasteAsPlainText();};FCKPastePlainTextCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('Paste');}; +var FCKPasteWordCommand=function(){this.Name='PasteWord';};FCKPasteWordCommand.prototype.Execute=function(){FCK.PasteFromWord();};FCKPasteWordCommand.prototype.GetState=function(){if (FCK.EditMode!=0||FCKConfig.ForcePasteAsPlainText) return -1;else return FCK.GetNamedCommandState('Paste');}; +var FCKTableCommand=function(A){this.Name=A;};FCKTableCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();if (!FCKBrowserInfo.IsGecko){switch (this.Name){case 'TableMergeRight':return FCKTableHandler.MergeRight();case 'TableMergeDown':return FCKTableHandler.MergeDown();}};switch (this.Name){case 'TableInsertRowAfter':return FCKTableHandler.InsertRow(false);case 'TableInsertRowBefore':return FCKTableHandler.InsertRow(true);case 'TableDeleteRows':return FCKTableHandler.DeleteRows();case 'TableInsertColumnAfter':return FCKTableHandler.InsertColumn(false);case 'TableInsertColumnBefore':return FCKTableHandler.InsertColumn(true);case 'TableDeleteColumns':return FCKTableHandler.DeleteColumns();case 'TableInsertCellAfter':return FCKTableHandler.InsertCell(null,false);case 'TableInsertCellBefore':return FCKTableHandler.InsertCell(null,true);case 'TableDeleteCells':return FCKTableHandler.DeleteCells();case 'TableMergeCells':return FCKTableHandler.MergeCells();case 'TableHorizontalSplitCell':return FCKTableHandler.HorizontalSplitCell();case 'TableVerticalSplitCell':return FCKTableHandler.VerticalSplitCell();case 'TableDelete':return FCKTableHandler.DeleteTable();default:return alert(FCKLang.UnknownCommand.replace(/%1/g,this.Name));}};FCKTableCommand.prototype.GetState=function(){if (FCK.EditorDocument!=null&&FCKSelection.HasAncestorNode('TABLE')){switch (this.Name){case 'TableHorizontalSplitCell':case 'TableVerticalSplitCell':if (FCKTableHandler.GetSelectedCells().length==1) return 0;else return -1;case 'TableMergeCells':if (FCKTableHandler.CheckIsSelectionRectangular()&&FCKTableHandler.GetSelectedCells().length>1) return 0;else return -1;case 'TableMergeRight':return FCKTableHandler.GetMergeRightTarget()?0:-1;case 'TableMergeDown':return FCKTableHandler.GetMergeDownTarget()?0:-1;default:return 0;}}else return -1;}; +var FCKFitWindow=function(){this.Name='FitWindow';};FCKFitWindow.prototype.Execute=function(){var A=window.frameElement;var B=A.style;var C=parent;var D=C.document.documentElement;var E=C.document.body;var F=E.style;var G;var H,oEditorScrollPos;if (FCK.EditMode==0){H=new FCKDomRange(FCK.EditorWindow);H.MoveToSelection();oEditorScrollPos=FCKTools.GetScrollPosition(FCK.EditorWindow);}else{var I=FCK.EditingArea.Textarea;H=!FCKBrowserInfo.IsIE&&[I.selectionStart,I.selectionEnd];oEditorScrollPos=[I.scrollLeft,I.scrollTop];};if (!this.IsMaximized){if(FCKBrowserInfo.IsIE) C.attachEvent('onresize',FCKFitWindow_Resize);else C.addEventListener('resize',FCKFitWindow_Resize,true);this._ScrollPos=FCKTools.GetScrollPosition(C);G=A;while((G=G.parentNode)){if (G.nodeType==1){G._fckSavedStyles=FCKTools.SaveStyles(G);G.style.zIndex=FCKConfig.FloatingPanelsZIndex-1;}};if (FCKBrowserInfo.IsIE){this.documentElementOverflow=D.style.overflow;D.style.overflow='hidden';F.overflow='hidden';}else{F.overflow='hidden';F.width='0px';F.height='0px';};this._EditorFrameStyles=FCKTools.SaveStyles(A);var J=FCKTools.GetViewPaneSize(C);B.position="absolute";A.offsetLeft;B.zIndex=FCKConfig.FloatingPanelsZIndex-1;B.left="0px";B.top="0px";B.width=J.Width+"px";B.height=J.Height+"px";if (!FCKBrowserInfo.IsIE){B.borderRight=B.borderBottom="9999px solid white";B.backgroundColor="white";};C.scrollTo(0,0);var K=FCKTools.GetWindowPosition(C,A);if (K.x!=0) B.left=(-1*K.x)+"px";if (K.y!=0) B.top=(-1*K.y)+"px";this.IsMaximized=true;}else{if(FCKBrowserInfo.IsIE) C.detachEvent("onresize",FCKFitWindow_Resize);else C.removeEventListener("resize",FCKFitWindow_Resize,true);G=A;while((G=G.parentNode)){if (G._fckSavedStyles){FCKTools.RestoreStyles(G,G._fckSavedStyles);G._fckSavedStyles=null;}};if (FCKBrowserInfo.IsIE) D.style.overflow=this.documentElementOverflow;FCKTools.RestoreStyles(A,this._EditorFrameStyles);C.scrollTo(this._ScrollPos.X,this._ScrollPos.Y);this.IsMaximized=false;};FCKToolbarItems.GetItem('FitWindow').RefreshState();if (FCK.EditMode==0) FCK.EditingArea.MakeEditable();FCK.Focus();if (FCK.EditMode==0){H.Select();FCK.EditorWindow.scrollTo(oEditorScrollPos.X,oEditorScrollPos.Y);}else{if (!FCKBrowserInfo.IsIE){I.selectionStart=H[0];I.selectionEnd=H[1];};I.scrollLeft=oEditorScrollPos[0];I.scrollTop=oEditorScrollPos[1];}};FCKFitWindow.prototype.GetState=function(){if (FCKConfig.ToolbarLocation!='In') return -1;else return (this.IsMaximized?1:0);};function FCKFitWindow_Resize(){var A=FCKTools.GetViewPaneSize(parent);var B=window.frameElement.style;B.width=A.Width+'px';B.height=A.Height+'px';}; +var FCKListCommand=function(A,B){this.Name=A;this.TagName=B;};FCKListCommand.prototype={GetState:function(){if (FCK.EditMode!=0||!FCK.EditorWindow) return -1;var A=FCKSelection.GetBoundaryParentElement(true);var B=A;while (B){if (B.nodeName.IEquals(['ul','ol'])) break;B=B.parentNode;};if (B&&B.nodeName.IEquals(this.TagName)) return 1;else return 0;},Execute:function(){FCKUndo.SaveUndoStep();var A=FCK.EditorDocument;var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=this.GetState();if (C==0){FCKDomTools.TrimNode(A.body);if (!A.body.firstChild){var D=A.createElement('p');A.body.appendChild(D);B.MoveToNodeContents(D);}};var E=B.CreateBookmark();var F=[];var G={};var H=new FCKDomRangeIterator(B);var I;H.ForceBrBreak=(C==0);var J=true;var K=null;while (J){while ((I=H.GetNextParagraph())){var L=new FCKElementPath(I);var M=null;var N=false;var O=L.BlockLimit;for (var i=L.Elements.length-1;i>=0;i--){var P=L.Elements[i];if (P.nodeName.IEquals(['ol','ul'])){if (O._FCK_ListGroupObject) O._FCK_ListGroupObject=null;var Q=P._FCK_ListGroupObject;if (Q) Q.contents.push(I);else{Q={ 'root':P,'contents':[I] };F.push(Q);FCKDomTools.SetElementMarker(G,P,'_FCK_ListGroupObject',Q);};N=true;break;}};if (N) continue;var R=O;if (R._FCK_ListGroupObject) R._FCK_ListGroupObject.contents.push(I);else{var Q={ 'root':R,'contents':[I] };FCKDomTools.SetElementMarker(G,R,'_FCK_ListGroupObject',Q);F.push(Q);}};if (FCKBrowserInfo.IsIE) J=false;else{if (K==null){K=[];var T=FCKSelection.GetSelection();if (T&&F.length==0) K.push(T.getRangeAt(0));for (var i=1;T&&i0){var Q=F.shift();if (C==0){if (Q.root.nodeName.IEquals(['ul','ol'])) this._ChangeListType(Q,G,W);else this._CreateList(Q,W);}else if (C==1&&Q.root.nodeName.IEquals(['ul','ol'])) this._RemoveList(Q,G);};for (var i=0;iC[i-1].indent+1){var H=C[i-1].indent+1-C[i].indent;var I=C[i].indent;while (C[i]&&C[i].indent>=I){C[i].indent+=H;i++;};i--;}};var J=FCKDomTools.ArrayToList(C,B);if (A.root.nextSibling==null||A.root.nextSibling.nodeName.IEquals('br')){if (J.listNode.lastChild.nodeName.IEquals('br')) J.listNode.removeChild(J.listNode.lastChild);};A.root.parentNode.replaceChild(J.listNode,A.root);}}; +var FCKJustifyCommand=function(A){this.AlignValue=A;var B=FCKConfig.ContentLangDirection.toLowerCase();this.IsDefaultAlign=(A=='left'&&B=='ltr')||(A=='right'&&B=='rtl');var C=this._CssClassName=(function(){var D=FCKConfig.JustifyClasses;if (D){switch (A){case 'left':return D[0]||null;case 'center':return D[1]||null;case 'right':return D[2]||null;case 'justify':return D[3]||null;}};return null;})();if (C&&C.length>0) this._CssClassRegex=new RegExp('(?:^|\\s+)'+C+'(?=$|\\s)');};FCKJustifyCommand._GetClassNameRegex=function(){var A=FCKJustifyCommand._ClassRegex;if (A!=undefined) return A;var B=[];var C=FCKConfig.JustifyClasses;if (C){for (var i=0;i<4;i++){var D=C[i];if (D&&D.length>0) B.push(D);}};if (B.length>0) A=new RegExp('(?:^|\\s+)(?:'+B.join('|')+')(?=$|\\s)');else A=null;return FCKJustifyCommand._ClassRegex=A;};FCKJustifyCommand.prototype={Execute:function(){FCKUndo.SaveUndoStep();var A=new FCKDomRange(FCK.EditorWindow);A.MoveToSelection();var B=this.GetState();if (B==-1) return;var C=A.CreateBookmark();var D=this._CssClassName;var E=new FCKDomRangeIterator(A);var F;while ((F=E.GetNextParagraph())){F.removeAttribute('align');if (D){var G=F.className.replace(FCKJustifyCommand._GetClassNameRegex(),'');if (B==0){if (G.length>0) G+=' ';F.className=G+D;}else if (G.length==0) FCKDomTools.RemoveAttribute(F,'class');}else{var H=F.style;if (B==0) H.textAlign=this.AlignValue;else{H.textAlign='';if (H.cssText.length==0) F.removeAttribute('style');}}};A.MoveToBookmark(C);A.Select();FCK.Focus();FCK.Events.FireEvent('OnSelectionChange');},GetState:function(){if (FCK.EditMode!=0||!FCK.EditorWindow) return -1;var A=new FCKElementPath(FCKSelection.GetBoundaryParentElement(true));var B=A.Block||A.BlockLimit;if (!B||B.nodeName.toLowerCase()=='body') return 0;var C;if (FCKBrowserInfo.IsIE) C=B.currentStyle.textAlign;else C=FCK.EditorWindow.getComputedStyle(B,'').getPropertyValue('text-align');C=C.replace(/(-moz-|-webkit-|start|auto)/i,'');if ((!C&&this.IsDefaultAlign)||C==this.AlignValue) return 1;return 0;}}; +var FCKIndentCommand=function(A,B){this.Name=A;this.Offset=B;this.IndentCSSProperty=FCKConfig.ContentLangDirection.IEquals('ltr')?'marginLeft':'marginRight';};FCKIndentCommand._InitIndentModeParameters=function(){if (FCKConfig.IndentClasses&&FCKConfig.IndentClasses.length>0){this._UseIndentClasses=true;this._IndentClassMap={};for (var i=0;i0?H+' ':'')+FCKConfig.IndentClasses[G-1];}else{var I=parseInt(E.style[this.IndentCSSProperty],10);if (isNaN(I)) I=0;I+=this.Offset;I=Math.max(I,0);I=Math.ceil(I/this.Offset)*this.Offset;E.style[this.IndentCSSProperty]=I?I+FCKConfig.IndentUnit:'';if (E.getAttribute('style')=='') E.removeAttribute('style');}}},_IndentList:function(A,B){var C=A.StartContainer;var D=A.EndContainer;while (C&&C.parentNode!=B) C=C.parentNode;while (D&&D.parentNode!=B) D=D.parentNode;if (!C||!D) return;var E=C;var F=[];var G=false;while (G==false){if (E==D) G=true;F.push(E);E=E.nextSibling;};if (F.length<1) return;var H=FCKDomTools.GetParents(B);for (var i=0;iN;i++) M[i].indent+=I;var O=FCKDomTools.ArrayToList(M);if (O) B.parentNode.replaceChild(O.listNode,B);FCKDomTools.ClearAllMarkers(L);}}; +var FCKBlockQuoteCommand=function(){};FCKBlockQuoteCommand.prototype={Execute:function(){FCKUndo.SaveUndoStep();var A=this.GetState();var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=B.CreateBookmark();if (FCKBrowserInfo.IsIE){var D=B.GetBookmarkNode(C,true);var E=B.GetBookmarkNode(C,false);var F;if (D&&D.parentNode.nodeName.IEquals('blockquote')&&!D.previousSibling){F=D;while ((F=F.nextSibling)){if (FCKListsLib.BlockElements[F.nodeName.toLowerCase()]) FCKDomTools.MoveNode(D,F,true);}};if (E&&E.parentNode.nodeName.IEquals('blockquote')&&!E.previousSibling){F=E;while ((F=F.nextSibling)){if (FCKListsLib.BlockElements[F.nodeName.toLowerCase()]){if (F.firstChild==D) FCKDomTools.InsertAfterNode(D,E);else FCKDomTools.MoveNode(E,F,true);}}}};var G=new FCKDomRangeIterator(B);var H;if (A==0){var I=[];while ((H=G.GetNextParagraph())) I.push(H);if (I.length<1){para=B.Window.document.createElement(FCKConfig.EnterMode.IEquals('p')?'p':'div');B.InsertNode(para);para.appendChild(B.Window.document.createTextNode('\ufeff'));B.MoveToBookmark(C);B.MoveToNodeContents(para);B.Collapse(true);C=B.CreateBookmark();I.push(para);};var J=I[0].parentNode;var K=[];for (var i=0;i0){H=I.shift();while (H.parentNode!=J) H=H.parentNode;if (H!=L) K.push(H);L=H;}while (K.length>0){H=K.shift();if (H.nodeName.IEquals('blockquote')){var M=FCKTools.GetElementDocument(H).createDocumentFragment();while (H.firstChild){M.appendChild(H.removeChild(H.firstChild));I.push(M.lastChild);};H.parentNode.replaceChild(M,H);}else I.push(H);};var N=B.Window.document.createElement('blockquote');J.insertBefore(N,I[0]);while (I.length>0){H=I.shift();N.appendChild(H);}}else if (A==1){var O=[];var P={};while ((H=G.GetNextParagraph())){var Q=null;var R=null;while (H.parentNode){if (H.parentNode.nodeName.IEquals('blockquote')){Q=H.parentNode;R=H;break;};H=H.parentNode;};if (Q&&R&&!R._fckblockquotemoveout){O.push(R);FCKDomTools.SetElementMarker(P,R,'_fckblockquotemoveout',true);}};FCKDomTools.ClearAllMarkers(P);var S=[];var T=[],P={};var U=function(N){for (var i=0;i0){var W=O.shift();var N=W.parentNode;if (W==W.parentNode.firstChild) N.parentNode.insertBefore(N.removeChild(W),N);else if (W==W.parentNode.lastChild) N.parentNode.insertBefore(N.removeChild(W),N.nextSibling);else FCKDomTools.BreakParent(W,W.parentNode,B);if (!N._fckbqprocessed){T.push(N);FCKDomTools.SetElementMarker(P,N,'_fckbqprocessed',true);};S.push(W);};for (var i=T.length-1;i>=0;i--){var N=T[i];if (U(N)) FCKDomTools.RemoveNode(N);};FCKDomTools.ClearAllMarkers(P);if (FCKConfig.EnterMode.IEquals('br')){while (S.length){var W=S.shift();var a=true;if (W.nodeName.IEquals('div')){var M=FCKTools.GetElementDocument(W).createDocumentFragment();var c=a&&W.previousSibling&&!FCKListsLib.BlockBoundaries[W.previousSibling.nodeName.toLowerCase()];if (a&&c) M.appendChild(FCKTools.GetElementDocument(W).createElement('br'));var d=W.nextSibling&&!FCKListsLib.BlockBoundaries[W.nextSibling.nodeName.toLowerCase()];while (W.firstChild) M.appendChild(W.removeChild(W.firstChild));if (d) M.appendChild(FCKTools.GetElementDocument(W).createElement('br'));W.parentNode.replaceChild(M,W);a=false;}}}};B.MoveToBookmark(C);B.Select();FCK.Focus();FCK.Events.FireEvent('OnSelectionChange');},GetState:function(){if (FCK.EditMode!=0||!FCK.EditorWindow) return -1;var A=new FCKElementPath(FCKSelection.GetBoundaryParentElement(true));var B=A.Block||A.BlockLimit;if (!B||B.nodeName.toLowerCase()=='body') return 0;for (var i=0;i';B.open();B.write(''+F+'<\/head><\/body><\/html>');B.close();if(FCKBrowserInfo.IsAIR) FCKAdobeAIR.Panel_Contructor(B,window.document.location);FCKTools.AddEventListenerEx(E,'focus',FCKPanel_Window_OnFocus,this);FCKTools.AddEventListenerEx(E,'blur',FCKPanel_Window_OnBlur,this);};B.dir=FCKLang.Dir;FCKTools.AddEventListener(B,'contextmenu',FCKTools.CancelEvent);this.MainNode=B.body.appendChild(B.createElement('DIV'));this.MainNode.style.cssFloat=this.IsRTL?'right':'left';};FCKPanel.prototype.AppendStyleSheet=function(A){FCKTools.AppendStyleSheet(this.Document,A);};FCKPanel.prototype.Preload=function(x,y,A){if (this._Popup) this._Popup.show(x,y,0,0,A);};FCKPanel.prototype.ResizeForSubpanel=function(A,B,C){if (!FCKBrowserInfo.IsIE7) return false;if (!this._Popup.isOpen){this.Subpanel=null;return false;};if (B==0&&C==0){if (this.Subpanel!==A) return false;this.Subpanel=null;this.IncreasedX=0;}else{this.Subpanel=A;if ((this.IncreasedX>=B)&&(this.IncreasedY>=C)) return false;this.IncreasedX=Math.max(this.IncreasedX,B);this.IncreasedY=Math.max(this.IncreasedY,C);};var x=this.ShowRect.x;var w=this.IncreasedX;if (this.IsRTL) x=x-w;var D=this.ShowRect.w+w;var E=Math.max(this.ShowRect.h,this.IncreasedY);if (this.ParentPanel) this.ParentPanel.ResizeForSubpanel(this,D,E);this._Popup.show(x,this.ShowRect.y,D,E,this.RelativeElement);return this.IsRTL;};FCKPanel.prototype.Show=function(x,y,A,B,C){var D;var E=this.MainNode;if (this._Popup){this._Popup.show(x,y,0,0,A);FCKDomTools.SetElementStyles(E,{B:B?B+'px':'',C:C?C+'px':''});D=E.offsetWidth;if (FCKBrowserInfo.IsIE7){if (this.ParentPanel&&this.ParentPanel.ResizeForSubpanel(this,D,E.offsetHeight)){FCKTools.RunFunction(this.Show,this,[x,y,A]);return;}};if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=(x*-1)+A.offsetWidth-D;};if (FCKBrowserInfo.IsIE7){this.ShowRect={x:x,y:y,w:D,h:E.offsetHeight};this.IncreasedX=0;this.IncreasedY=0;this.RelativeElement=A;};this._PopupArgs=[x,y,D,E.offsetHeight,A];this._Popup.show(x,y,D,E.offsetHeight,A);if (this.OnHide){if (this._Timer) CheckPopupOnHide.call(this,true);this._Timer=FCKTools.SetInterval(CheckPopupOnHide,100,this);}}else{if (typeof(FCK.ToolbarSet.CurrentInstance.FocusManager)!='undefined') FCK.ToolbarSet.CurrentInstance.FocusManager.Lock();if (this.ParentPanel){this.ParentPanel.Lock();FCKPanel_Window_OnBlur(null,this.ParentPanel);};if (FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsMac){this._IFrame.scrolling='';FCKTools.RunFunction(function(){ this._IFrame.scrolling='no';},this);};if (FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel&&FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel!=this) FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel.Hide(false,true);FCKDomTools.SetElementStyles(E,{B:B?B+'px':'',C:C?C+'px':''});D=E.offsetWidth;if (!B) this._IFrame.width=1;if (!C) this._IFrame.height=1;D=E.offsetWidth||E.firstChild.offsetWidth;var F=FCKTools.GetDocumentPosition(this._Window,A.nodeType==9?(FCKTools.IsStrictMode(A)?A.documentElement:A.body):A);var G=FCKDomTools.GetPositionedAncestor(this._IFrame.parentNode);if (G){var H=FCKTools.GetDocumentPosition(FCKTools.GetElementWindow(G),G);F.x-=H.x;F.y-=H.y;};if (this.IsRTL&&!this.IsContextMenu) x=(x*-1);x+=F.x;y+=F.y;if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=x+A.offsetWidth-D;}else{var I=FCKTools.GetViewPaneSize(this._Window);var J=FCKTools.GetScrollPosition(this._Window);var K=I.Height+J.Y;var L=I.Width+J.X;if ((x+D)>L) x-=x+D-L;if ((y+E.offsetHeight)>K) y-=y+E.offsetHeight-K;};FCKDomTools.SetElementStyles(this._IFrame,{left:x+'px',top:y+'px'});this._IFrame.contentWindow.focus();this._IsOpened=true;var M=this;this._resizeTimer=setTimeout(function(){var N=E.offsetWidth||E.firstChild.offsetWidth;var O=E.offsetHeight;M._IFrame.style.width=N+'px';M._IFrame.style.height=O+'px';},0);FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel=this;};FCKTools.RunFunction(this.OnShow,this);};FCKPanel.prototype.Hide=function(A,B){if (this._Popup) this._Popup.hide();else{if (!this._IsOpened||this._LockCounter>0) return;if (typeof(FCKFocusManager)!='undefined'&&!B) FCKFocusManager.Unlock();this._IFrame.style.width=this._IFrame.style.height='0px';this._IsOpened=false;if (this._resizeTimer){clearTimeout(this._resizeTimer);this._resizeTimer=null;};if (this.ParentPanel) this.ParentPanel.Unlock();if (!A) FCKTools.RunFunction(this.OnHide,this);}};FCKPanel.prototype.CheckIsOpened=function(){if (this._Popup) return this._Popup.isOpen;else return this._IsOpened;};FCKPanel.prototype.CreateChildPanel=function(){var A=this._Popup?FCKTools.GetDocumentWindow(this.Document):this._Window;var B=new FCKPanel(A);B.ParentPanel=this;return B;};FCKPanel.prototype.Lock=function(){this._LockCounter++;};FCKPanel.prototype.Unlock=function(){if (--this._LockCounter==0&&!this.HasFocus) this.Hide();};function FCKPanel_Window_OnFocus(e,A){A.HasFocus=true;};function FCKPanel_Window_OnBlur(e,A){A.HasFocus=false;if (A._LockCounter==0) FCKTools.RunFunction(A.Hide,A);};function CheckPopupOnHide(A){if (A||!this._Popup.isOpen){window.clearInterval(this._Timer);this._Timer=null;if (this._Popup&&this.ParentPanel&&!A) this.ParentPanel.ResizeForSubpanel(this,0,0);FCKTools.RunFunction(this.OnHide,this);}};function FCKPanel_Cleanup(){this._Popup=null;this._Window=null;this.Document=null;this.MainNode=null;this.RelativeElement=null;}; +var FCKIcon=function(A){var B=A?typeof(A):'undefined';switch (B){case 'number':this.Path=FCKConfig.SkinPath+'fck_strip.gif';this.Size=16;this.Position=A;break;case 'undefined':this.Path=FCK_SPACER_PATH;break;case 'string':this.Path=A;break;default:this.Path=A[0];this.Size=A[1];this.Position=A[2];}};FCKIcon.prototype.CreateIconElement=function(A){var B,eIconImage;if (this.Position){var C='-'+((this.Position-1)*this.Size)+'px';if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path;eIconImage.style.top=C;}else{B=A.createElement('IMG');B.src=FCK_SPACER_PATH;B.style.backgroundPosition='0px '+C;B.style.backgroundImage='url("'+this.Path+'")';}}else{if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path?this.Path:FCK_SPACER_PATH;}else{B=A.createElement('IMG');B.src=this.Path?this.Path:FCK_SPACER_PATH;}};B.className='TB_Button_Image';return B;}; +var FCKToolbarButtonUI=function(A,B,C,D,E,F){this.Name=A;this.Label=B||A;this.Tooltip=C||this.Label;this.Style=E||0;this.State=F||0;this.Icon=new FCKIcon(D);if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarButtonUI_Cleanup);};FCKToolbarButtonUI.prototype._CreatePaddingElement=function(A){var B=A.createElement('IMG');B.className='TB_Button_Padding';B.src=FCK_SPACER_PATH;return B;};FCKToolbarButtonUI.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var C=this.MainElement=B.createElement('DIV');C.title=this.Tooltip;if (FCKBrowserInfo.IsGecko) C.onmousedown=FCKTools.CancelEvent;FCKTools.AddEventListenerEx(C,'mouseover',FCKToolbarButtonUI_OnMouseOver,this);FCKTools.AddEventListenerEx(C,'mouseout',FCKToolbarButtonUI_OnMouseOut,this);FCKTools.AddEventListenerEx(C,'click',FCKToolbarButtonUI_OnClick,this);this.ChangeState(this.State,true);if (this.Style==0&&!this.ShowArrow){C.appendChild(this.Icon.CreateIconElement(B));}else{var D=C.appendChild(B.createElement('TABLE'));D.cellPadding=0;D.cellSpacing=0;var E=D.insertRow(-1);var F=E.insertCell(-1);if (this.Style==0||this.Style==2) F.appendChild(this.Icon.CreateIconElement(B));else F.appendChild(this._CreatePaddingElement(B));if (this.Style==1||this.Style==2){F=E.insertCell(-1);F.className='TB_Button_Text';F.noWrap=true;F.appendChild(B.createTextNode(this.Label));};if (this.ShowArrow){if (this.Style!=0){E.insertCell(-1).appendChild(this._CreatePaddingElement(B));};F=E.insertCell(-1);var G=F.appendChild(B.createElement('IMG'));G.src=FCKConfig.SkinPath+'images/toolbar.buttonarrow.gif';G.width=5;G.height=3;};F=E.insertCell(-1);F.appendChild(this._CreatePaddingElement(B));};A.appendChild(C);};FCKToolbarButtonUI.prototype.ChangeState=function(A,B){if (!B&&this.State==A) return;var e=this.MainElement;if (!e) return;switch (parseInt(A,10)){case 0:e.className='TB_Button_Off';break;case 1:e.className='TB_Button_On';break;case -1:e.className='TB_Button_Disabled';break;};this.State=A;};function FCKToolbarButtonUI_OnMouseOver(A,B){if (B.State==0) this.className='TB_Button_Off_Over';else if (B.State==1) this.className='TB_Button_On_Over';};function FCKToolbarButtonUI_OnMouseOut(A,B){if (B.State==0) this.className='TB_Button_Off';else if (B.State==1) this.className='TB_Button_On';};function FCKToolbarButtonUI_OnClick(A,B){if (B.OnClick&&B.State!=-1) B.OnClick(B);};function FCKToolbarButtonUI_Cleanup(){this.MainElement=null;}; +var FCKToolbarButton=function(A,B,C,D,E,F,G){this.CommandName=A;this.Label=B;this.Tooltip=C;this.Style=D;this.SourceView=E?true:false;this.ContextSensitive=F?true:false;if (G==null) this.IconPath=FCKConfig.SkinPath+'toolbar/'+A.toLowerCase()+'.gif';else if (typeof(G)=='number') this.IconPath=[FCKConfig.SkinPath+'fck_strip.gif',16,G];else this.IconPath=G;};FCKToolbarButton.prototype.Create=function(A){this._UIButton=new FCKToolbarButtonUI(this.CommandName,this.Label,this.Tooltip,this.IconPath,this.Style);this._UIButton.OnClick=this.Click;this._UIButton._ToolbarButton=this;this._UIButton.Create(A);};FCKToolbarButton.prototype.RefreshState=function(){var A=this._UIButton;if (!A) return;var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (B==A.State) return;A.ChangeState(B);};FCKToolbarButton.prototype.Click=function(){var A=this._ToolbarButton||this;FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(A.CommandName).Execute();};FCKToolbarButton.prototype.Enable=function(){this.RefreshState();};FCKToolbarButton.prototype.Disable=function(){this._UIButton.ChangeState(-1);}; +var FCKSpecialCombo=function(A,B,C,D,E){this.FieldWidth=B||100;this.PanelWidth=C||150;this.PanelMaxHeight=D||150;this.Label=' ';this.Caption=A;this.Tooltip=A;this.Style=2;this.Enabled=true;this.Items={};this._Panel=new FCKPanel(E||window);this._Panel.AppendStyleSheet(FCKConfig.SkinEditorCSS);this._PanelBox=this._Panel.MainNode.appendChild(this._Panel.Document.createElement('DIV'));this._PanelBox.className='SC_Panel';this._PanelBox.style.width=this.PanelWidth+'px';this._PanelBox.innerHTML='
    ';this._ItemsHolderEl=this._PanelBox.getElementsByTagName('TD')[0];if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKSpecialCombo_Cleanup);};function FCKSpecialCombo_ItemOnMouseOver(){this.className+=' SC_ItemOver';};function FCKSpecialCombo_ItemOnMouseOut(){this.className=this.originalClass;};function FCKSpecialCombo_ItemOnClick(A,B,C){this.className=this.originalClass;B._Panel.Hide();B.SetLabel(this.FCKItemLabel);if (typeof(B.OnSelect)=='function') B.OnSelect(C,this);};FCKSpecialCombo.prototype.ClearItems=function (){if (this.Items) this.Items={};var A=this._ItemsHolderEl;while (A.firstChild) A.removeChild(A.firstChild);};FCKSpecialCombo.prototype.AddItem=function(A,B,C,D){var E=this._ItemsHolderEl.appendChild(this._Panel.Document.createElement('DIV'));E.className=E.originalClass='SC_Item';E.innerHTML=B;E.FCKItemLabel=C||A;E.Selected=false;if (FCKBrowserInfo.IsIE) E.style.width='100%';if (D) E.style.backgroundColor=D;FCKTools.AddEventListenerEx(E,'mouseover',FCKSpecialCombo_ItemOnMouseOver);FCKTools.AddEventListenerEx(E,'mouseout',FCKSpecialCombo_ItemOnMouseOut);FCKTools.AddEventListenerEx(E,'click',FCKSpecialCombo_ItemOnClick,[this,A]);this.Items[A.toString().toLowerCase()]=E;return E;};FCKSpecialCombo.prototype.SelectItem=function(A){if (typeof A=='string') A=this.Items[A.toString().toLowerCase()];if (A){A.className=A.originalClass='SC_ItemSelected';A.Selected=true;}};FCKSpecialCombo.prototype.SelectItemByLabel=function(A,B){for (var C in this.Items){var D=this.Items[C];if (D.FCKItemLabel==A){D.className=D.originalClass='SC_ItemSelected';D.Selected=true;if (B) this.SetLabel(A);}}};FCKSpecialCombo.prototype.DeselectAll=function(A){for (var i in this.Items){if (!this.Items[i]) continue;this.Items[i].className=this.Items[i].originalClass='SC_Item';this.Items[i].Selected=false;};if (A) this.SetLabel('');};FCKSpecialCombo.prototype.SetLabelById=function(A){A=A?A.toString().toLowerCase():'';var B=this.Items[A];this.SetLabel(B?B.FCKItemLabel:'');};FCKSpecialCombo.prototype.SetLabel=function(A){A=(!A||A.length==0)?' ':A;if (A==this.Label) return;this.Label=A;var B=this._LabelEl;if (B){B.innerHTML=A;FCKTools.DisableSelection(B);}};FCKSpecialCombo.prototype.SetEnabled=function(A){this.Enabled=A;if (this._OuterTable) this._OuterTable.className=A?'':'SC_FieldDisabled';};FCKSpecialCombo.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var C=this._OuterTable=A.appendChild(B.createElement('TABLE'));C.cellPadding=0;C.cellSpacing=0;C.insertRow(-1);var D;var E;switch (this.Style){case 0:D='TB_ButtonType_Icon';E=false;break;case 1:D='TB_ButtonType_Text';E=false;break;case 2:E=true;break;};if (this.Caption&&this.Caption.length>0&&E){var F=C.rows[0].insertCell(-1);F.innerHTML=this.Caption;F.className='SC_FieldCaption';};var G=FCKTools.AppendElement(C.rows[0].insertCell(-1),'div');if (E){G.className='SC_Field';G.style.width=this.FieldWidth+'px';G.innerHTML='
     
    ';this._LabelEl=G.getElementsByTagName('label')[0];this._LabelEl.innerHTML=this.Label;}else{G.className='TB_Button_Off';G.innerHTML='
    '+this.Caption+'
    ';};FCKTools.AddEventListenerEx(G,'mouseover',FCKSpecialCombo_OnMouseOver,this);FCKTools.AddEventListenerEx(G,'mouseout',FCKSpecialCombo_OnMouseOut,this);FCKTools.AddEventListenerEx(G,'click',FCKSpecialCombo_OnClick,this);FCKTools.DisableSelection(this._Panel.Document.body);};function FCKSpecialCombo_Cleanup(){this._LabelEl=null;this._OuterTable=null;this._ItemsHolderEl=null;this._PanelBox=null;if (this.Items){for (var A in this.Items) this.Items[A]=null;}};function FCKSpecialCombo_OnMouseOver(A,B){if (B.Enabled){switch (B.Style){case 0:this.className='TB_Button_On_Over';break;case 1:this.className='TB_Button_On_Over';break;case 2:this.className='SC_Field SC_FieldOver';break;}}};function FCKSpecialCombo_OnMouseOut(A,B){switch (B.Style){case 0:this.className='TB_Button_Off';break;case 1:this.className='TB_Button_Off';break;case 2:this.className='SC_Field';break;}};function FCKSpecialCombo_OnClick(e,A){if (A.Enabled){var B=A._Panel;var C=A._PanelBox;var D=A._ItemsHolderEl;var E=A.PanelMaxHeight;if (A.OnBeforeClick) A.OnBeforeClick(A);if (FCKBrowserInfo.IsIE) B.Preload(0,this.offsetHeight,this);if (D.offsetHeight>E) C.style.height=E+'px';else C.style.height='';B.Show(0,this.offsetHeight,this);}}; +var FCKToolbarSpecialCombo=function(){this.SourceView=false;this.ContextSensitive=true;this.FieldWidth=null;this.PanelWidth=null;this.PanelMaxHeight=null;};FCKToolbarSpecialCombo.prototype.DefaultLabel='';function FCKToolbarSpecialCombo_OnSelect(A,B){FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).Execute(A,B);};FCKToolbarSpecialCombo.prototype.Create=function(A){this._Combo=new FCKSpecialCombo(this.GetLabel(),this.FieldWidth,this.PanelWidth,this.PanelMaxHeight,FCKBrowserInfo.IsIE?window:FCKTools.GetElementWindow(A).parent);this._Combo.Tooltip=this.Tooltip;this._Combo.Style=this.Style;this.CreateItems(this._Combo);this._Combo.Create(A);this._Combo.CommandName=this.CommandName;this._Combo.OnSelect=FCKToolbarSpecialCombo_OnSelect;};function FCKToolbarSpecialCombo_RefreshActiveItems(A,B){A.DeselectAll();A.SelectItem(B);A.SetLabelById(B);};FCKToolbarSpecialCombo.prototype.RefreshState=function(){var A;var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (B!=-1){A=1;if (this.RefreshActiveItems) this.RefreshActiveItems(this._Combo,B);else{if (this._LastValue!==B){this._LastValue=B;if (!B||B.length==0){this._Combo.DeselectAll();this._Combo.SetLabel(this.DefaultLabel);}else FCKToolbarSpecialCombo_RefreshActiveItems(this._Combo,B);}}}else A=-1;if (A==this.State) return;if (A==-1){this._Combo.DeselectAll();this._Combo.SetLabel('');};this.State=A;this._Combo.SetEnabled(A!=-1);};FCKToolbarSpecialCombo.prototype.Enable=function(){this.RefreshState();};FCKToolbarSpecialCombo.prototype.Disable=function(){this.State=-1;this._Combo.DeselectAll();this._Combo.SetLabel('');this._Combo.SetEnabled(false);}; +var FCKToolbarStyleCombo=function(A,B){if (A===false) return;this.CommandName='Style';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;this.DefaultLabel=FCKConfig.DefaultStyleLabel||'';};FCKToolbarStyleCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarStyleCombo.prototype.GetLabel=function(){return FCKLang.Style;};FCKToolbarStyleCombo.prototype.GetStyles=function(){var A={};var B=FCK.ToolbarSet.CurrentInstance.Styles.GetStyles();for (var C in B){var D=B[C];if (!D.IsCore) A[C]=D;};return A;};FCKToolbarStyleCombo.prototype.CreateItems=function(A){var B=A._Panel.Document;FCKTools.AppendStyleSheet(B,FCKConfig.ToolbarComboPreviewCSS);FCKTools.AppendStyleString(B,FCKConfig.EditorAreaStyles);B.body.className+=' ForceBaseFont';FCKConfig.ApplyBodyAttributes(B.body);var C=this.GetStyles();for (var D in C){var E=C[D];var F=E.GetType()==2?D:FCKToolbarStyleCombo_BuildPreview(E,E.Label||D);var G=A.AddItem(D,F);G.Style=E;};A.OnBeforeClick=this.StyleCombo_OnBeforeClick;};FCKToolbarStyleCombo.prototype.RefreshActiveItems=function(A){var B=FCK.ToolbarSet.CurrentInstance.Selection.GetBoundaryParentElement(true);if (B){var C=new FCKElementPath(B);var D=C.Elements;for (var e=0;e');var E=A.Element;if (E=='bdo') E='span';D=['<',E];var F=A._StyleDesc.Attributes;if (F){for (var G in F){D.push(' ',G,'="',A.GetFinalAttributeValue(G),'"');}};if (A._GetStyleText().length>0) D.push(' style="',A.GetFinalStyleValue(),'"');D.push('>',B,'');if (C==0) D.push('');return D.join('');}; +var FCKToolbarFontFormatCombo=function(A,B){if (A===false) return;this.CommandName='FontFormat';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;this.NormalLabel='Normal';this.PanelWidth=190;this.DefaultLabel=FCKConfig.DefaultFontFormatLabel||'';};FCKToolbarFontFormatCombo.prototype=new FCKToolbarStyleCombo(false);FCKToolbarFontFormatCombo.prototype.GetLabel=function(){return FCKLang.FontFormat;};FCKToolbarFontFormatCombo.prototype.GetStyles=function(){var A={};var B=FCKLang['FontFormats'].split(';');var C={p:B[0],pre:B[1],address:B[2],h1:B[3],h2:B[4],h3:B[5],h4:B[6],h5:B[7],h6:B[8],div:B[9]||(B[0]+' (DIV)')};var D=FCKConfig.FontFormats.split(';');for (var i=0;iEnable SCAYT
    ';return C?'Disable SCAYT':'Enable SCAYT';};var Z=function(tooltip,style){this.Command=FCKCommands.GetCommand('Scayt');this.CommandName='Scayt';this.Label=this.GetLabel();this.Tooltip=FCKLang.ScaytTitle;this.Style=1;};Z.prototype=new FCKToolbarSpecialCombo;Z.prototype.CreateItems=function(){this._Combo.AddItem('Trigger','Enable SCAYT');this._Combo.AddItem('Options',FCKLang.ScaytTitleOptions||"Options");this._Combo.AddItem('Langs',FCKLang.ScaytTitleLangs||"Languages");this._Combo.AddItem('About',FCKLang.ScaytTitleAbout||"About");};Z.prototype.GetLabel=function(){var a=FCKConfig.SkinPath+'fck_strip.gif';return FCKBrowserInfo.IsIE?'
    ':'';};function ScaytMessage(m){m&&alert(m);};var b=function(){name='ScaytContext';};b.prototype.Execute=function(contextInfo){var c=contextInfo&&contextInfo.action,g=c&&contextInfo.node,Q=window.scayt_control;if (g){switch (c){case 'Suggestion':Q.replace(g,contextInfo.suggestion);break;case 'Ignore':Q.ignore(g);break;case 'Ignore All':Q.ignoreAll(g);break;case 'Add Word':var E=FCK.EditorWindow.parent.parent;E.scayt.addWordToUserDictionary(g);break;}}};function InitSetup(){FCK.ContextMenu.RegisterListener({AddItems:function(menu){var E=FCK.EditorWindow.parent.parent;var Q=window.scayt_control,P=E.scayt;if (!Q) return;var g=Q.getScaytNode();if (!g) return;var h=P.getSuggestion(Q.getWord(g),Q.getLang());if (!h||!h.length) return;menu.AddSeparator();var j=FCK.Config.ScaytMaxSuggestions||5;var k=(j==-1)?h.length:j;for (var i=0;i';G.open();G.write(''+H+''+document.getElementById('xToolbarSpace').innerHTML+'');G.close();if(FCKBrowserInfo.IsAIR) FCKAdobeAIR.ToolbarSet_InitOutFrame(G);FCKTools.AddEventListener(G,'contextmenu',FCKTools.CancelEvent);FCKTools.AppendStyleSheet(G,FCKConfig.SkinEditorCSS);B=D.__FCKToolbarSet=new FCKToolbarSet(G);B._IFrame=F;if (FCK.IECleanup) FCK.IECleanup.AddItem(D,FCKToolbarSet_Target_Cleanup);};B.CurrentInstance=FCK;if (!B.ToolbarItems) B.ToolbarItems=FCKToolbarItems;FCK.AttachToOnSelectionChange(B.RefreshItemsState);return B;};function FCK_OnBlur(A){var B=A.ToolbarSet;if (B.CurrentInstance==A) B.Disable();};function FCK_OnFocus(A){var B=A.ToolbarSet;var C=A||FCK;B.CurrentInstance.FocusManager.RemoveWindow(B._IFrame.contentWindow);B.CurrentInstance=C;C.FocusManager.AddWindow(B._IFrame.contentWindow,true);B.Enable();};function FCKToolbarSet_Cleanup(){this._TargetElement=null;this._IFrame=null;};function FCKToolbarSet_Target_Cleanup(){this.__FCKToolbarSet=null;};var FCKToolbarSet=function(A){this._Document=A;this._TargetElement=A.getElementById('xToolbar');var B=A.getElementById('xExpandHandle');var C=A.getElementById('xCollapseHandle');B.title=FCKLang.ToolbarExpand;FCKTools.AddEventListener(B,'click',FCKToolbarSet_Expand_OnClick);C.title=FCKLang.ToolbarCollapse;FCKTools.AddEventListener(C,'click',FCKToolbarSet_Collapse_OnClick);if (!FCKConfig.ToolbarCanCollapse||FCKConfig.ToolbarStartExpanded) this.Expand();else this.Collapse();C.style.display=FCKConfig.ToolbarCanCollapse?'':'none';if (FCKConfig.ToolbarCanCollapse) C.style.display='';else A.getElementById('xTBLeftBorder').style.display='';this.Toolbars=[];this.IsLoaded=false;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarSet_Cleanup);};function FCKToolbarSet_Expand_OnClick(){FCK.ToolbarSet.Expand();};function FCKToolbarSet_Collapse_OnClick(){FCK.ToolbarSet.Collapse();};FCKToolbarSet.prototype.Expand=function(){this._ChangeVisibility(false);};FCKToolbarSet.prototype.Collapse=function(){this._ChangeVisibility(true);};FCKToolbarSet.prototype._ChangeVisibility=function(A){this._Document.getElementById('xCollapsed').style.display=A?'':'none';this._Document.getElementById('xExpanded').style.display=A?'none':'';if (window.onresize){FCKTools.RunFunction(window.onresize);}};FCKToolbarSet.prototype.Load=function(A){this.Name=A;this.Items=[];this.ItemsWysiwygOnly=[];this.ItemsContextSensitive=[];this._TargetElement.innerHTML='';var B=FCKConfig.ToolbarSets[A];if (!B){alert(FCKLang.UnknownToolbarSet.replace(/%1/g,A));return;};this.Toolbars=[];for (var x=0;x0) break;}catch (e){break;};D=D.parent;};var E=D.document;var F=function(){if (!B) B=FCKConfig.FloatingPanelsZIndex+999;return++B;};var G=function(){if (!C) return;var H=FCKTools.IsStrictMode(E)?E.documentElement:E.body;FCKDomTools.SetElementStyles(C,{'width':Math.max(H.scrollWidth,H.clientWidth,E.scrollWidth||0)-1+'px','height':Math.max(H.scrollHeight,H.clientHeight,E.scrollHeight||0)-1+'px'});};return {OpenDialog:function(dialogName,dialogTitle,dialogPage,width,height,customValue,resizable){if (!A) this.DisplayMainCover();var I={Title:dialogTitle,Page:dialogPage,Editor:window,CustomValue:customValue,TopWindow:D};FCK.ToolbarSet.CurrentInstance.Selection.Save(true);var J=FCKTools.GetViewPaneSize(D);var K={ 'X':0,'Y':0 };var L=FCKBrowserInfo.IsIE&&(!FCKBrowserInfo.IsIE7||!FCKTools.IsStrictMode(D.document));if (L) K=FCKTools.GetScrollPosition(D);var M=Math.max(K.Y+(J.Height-height-20)/2,0);var N=Math.max(K.X+(J.Width-width-20)/2,0);var O=E.createElement('iframe');FCKTools.ResetStyles(O);O.src=FCKConfig.BasePath+'fckdialog.html';O.frameBorder=0;O.allowTransparency=true;FCKDomTools.SetElementStyles(O,{'position':(L)?'absolute':'fixed','top':M+'px','left':N+'px','width':width+'px','height':height+'px','zIndex':F()});O._DialogArguments=I;E.body.appendChild(O);O._ParentDialog=A;A=O;},OnDialogClose:function(dialogWindow){var O=dialogWindow.frameElement;FCKDomTools.RemoveNode(O);if (O._ParentDialog){A=O._ParentDialog;O._ParentDialog.contentWindow.SetEnabled(true);}else{if (!FCKBrowserInfo.IsIE) FCK.Focus();this.HideMainCover();setTimeout(function(){ A=null;},0);FCK.ToolbarSet.CurrentInstance.Selection.Release();}},DisplayMainCover:function(){C=E.createElement('div');FCKTools.ResetStyles(C);FCKDomTools.SetElementStyles(C,{'position':'absolute','zIndex':F(),'top':'0px','left':'0px','backgroundColor':FCKConfig.BackgroundBlockerColor});FCKDomTools.SetOpacity(C,FCKConfig.BackgroundBlockerOpacity);if (FCKBrowserInfo.IsIE&&!FCKBrowserInfo.IsIE7){var Q=E.createElement('iframe');FCKTools.ResetStyles(Q);Q.hideFocus=true;Q.frameBorder=0;Q.src=FCKTools.GetVoidUrl();FCKDomTools.SetElementStyles(Q,{'width':'100%','height':'100%','position':'absolute','left':'0px','top':'0px','filter':'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'});C.appendChild(Q);};FCKTools.AddEventListener(D,'resize',G);G();E.body.appendChild(C);FCKFocusManager.Lock();var R=FCK.ToolbarSet.CurrentInstance.GetInstanceObject('frameElement');R._fck_originalTabIndex=R.tabIndex;R.tabIndex=-1;},HideMainCover:function(){FCKDomTools.RemoveNode(C);FCKFocusManager.Unlock();var R=FCK.ToolbarSet.CurrentInstance.GetInstanceObject('frameElement');R.tabIndex=R._fck_originalTabIndex;FCKDomTools.ClearElementJSProperty(R,'_fck_originalTabIndex');},GetCover:function(){return C;}};})(); +var FCKMenuItem=function(A,B,C,D,E,F){this.Name=B;this.Label=C||B;this.IsDisabled=E;this.Icon=new FCKIcon(D);this.SubMenu=new FCKMenuBlockPanel();this.SubMenu.Parent=A;this.SubMenu.OnClick=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnClick,this);this.CustomData=F;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuItem_Cleanup);};FCKMenuItem.prototype.AddItem=function(A,B,C,D,E){this.HasSubMenu=true;return this.SubMenu.AddItem(A,B,C,D,E);};FCKMenuItem.prototype.AddSeparator=function(){this.SubMenu.AddSeparator();};FCKMenuItem.prototype.Create=function(A){var B=this.HasSubMenu;var C=FCKTools.GetElementDocument(A);var r=this.MainElement=A.insertRow(-1);r.className=this.IsDisabled?'MN_Item_Disabled':'MN_Item';if (!this.IsDisabled){FCKTools.AddEventListenerEx(r,'mouseover',FCKMenuItem_OnMouseOver,[this]);FCKTools.AddEventListenerEx(r,'click',FCKMenuItem_OnClick,[this]);if (!B) FCKTools.AddEventListenerEx(r,'mouseout',FCKMenuItem_OnMouseOut,[this]);};var D=r.insertCell(-1);D.className='MN_Icon';D.appendChild(this.Icon.CreateIconElement(C));D=r.insertCell(-1);D.className='MN_Label';D.noWrap=true;D.appendChild(C.createTextNode(this.Label));D=r.insertCell(-1);if (B){D.className='MN_Arrow';var E=D.appendChild(C.createElement('IMG'));E.src=FCK_IMAGES_PATH+'arrow_'+FCKLang.Dir+'.gif';E.width=4;E.height=7;this.SubMenu.Create();this.SubMenu.Panel.OnHide=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnHide,this);}};FCKMenuItem.prototype.Activate=function(){this.MainElement.className='MN_Item_Over';if (this.HasSubMenu){this.SubMenu.Show(this.MainElement.offsetWidth+2,-2,this.MainElement);};FCKTools.RunFunction(this.OnActivate,this);};FCKMenuItem.prototype.Deactivate=function(){this.MainElement.className='MN_Item';if (this.HasSubMenu) this.SubMenu.Hide();};function FCKMenuItem_SubMenu_OnClick(A,B){FCKTools.RunFunction(B.OnClick,B,[A]);};function FCKMenuItem_SubMenu_OnHide(A){A.Deactivate();};function FCKMenuItem_OnClick(A,B){if (B.HasSubMenu) B.Activate();else{B.Deactivate();FCKTools.RunFunction(B.OnClick,B,[B]);}};function FCKMenuItem_OnMouseOver(A,B){B.Activate();};function FCKMenuItem_OnMouseOut(A,B){B.Deactivate();};function FCKMenuItem_Cleanup(){this.MainElement=null;}; +var FCKMenuBlock=function(){this._Items=[];};FCKMenuBlock.prototype.Count=function(){return this._Items.length;};FCKMenuBlock.prototype.AddItem=function(A,B,C,D,E){var F=new FCKMenuItem(this,A,B,C,D,E);F.OnClick=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnClick,this);F.OnActivate=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnActivate,this);this._Items.push(F);return F;};FCKMenuBlock.prototype.AddSeparator=function(){this._Items.push(new FCKMenuSeparator());};FCKMenuBlock.prototype.RemoveAllItems=function(){this._Items=[];var A=this._ItemsTable;if (A){while (A.rows.length>0) A.deleteRow(0);}};FCKMenuBlock.prototype.Create=function(A){if (!this._ItemsTable){if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuBlock_Cleanup);this._Window=FCKTools.GetElementWindow(A);var B=FCKTools.GetElementDocument(A);var C=A.appendChild(B.createElement('table'));C.cellPadding=0;C.cellSpacing=0;FCKTools.DisableSelection(C);var D=C.insertRow(-1).insertCell(-1);D.className='MN_Menu';var E=this._ItemsTable=D.appendChild(B.createElement('table'));E.cellPadding=0;E.cellSpacing=0;};for (var i=0;i0&&F.href.length==0);if (G) return;menu.AddSeparator();menu.AddItem('VisitLink',FCKLang.VisitLink);menu.AddSeparator();if (E) menu.AddItem('Link',FCKLang.EditLink,34);menu.AddItem('Unlink',FCKLang.RemoveLink,35);}}};case 'Image':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&!tag.getAttribute('_fckfakelement')){menu.AddSeparator();menu.AddItem('Image',FCKLang.ImageProperties,37);}}};case 'Anchor':return {AddItems:function(menu,tag,tagName){var F=FCKSelection.MoveToAncestorNode('A');var G=(F&&F.name.length>0);if (G||(tagName=='IMG'&&tag.getAttribute('_fckanchor'))){menu.AddSeparator();menu.AddItem('Anchor',FCKLang.AnchorProp,36);menu.AddItem('AnchorDelete',FCKLang.AnchorDelete);}}};case 'Flash':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckflash')){menu.AddSeparator();menu.AddItem('Flash',FCKLang.FlashProperties,38);}}};case 'Form':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('FORM')){menu.AddSeparator();menu.AddItem('Form',FCKLang.FormProp,48);}}};case 'Checkbox':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='checkbox'){menu.AddSeparator();menu.AddItem('Checkbox',FCKLang.CheckboxProp,49);}}};case 'Radio':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='radio'){menu.AddSeparator();menu.AddItem('Radio',FCKLang.RadioButtonProp,50);}}};case 'TextField':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='text'||tag.type=='password')){menu.AddSeparator();menu.AddItem('TextField',FCKLang.TextFieldProp,51);}}};case 'HiddenField':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckinputhidden')){menu.AddSeparator();menu.AddItem('HiddenField',FCKLang.HiddenFieldProp,56);}}};case 'ImageButton':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='image'){menu.AddSeparator();menu.AddItem('ImageButton',FCKLang.ImageButtonProp,55);}}};case 'Button':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='button'||tag.type=='submit'||tag.type=='reset')){menu.AddSeparator();menu.AddItem('Button',FCKLang.ButtonProp,54);}}};case 'Select':return {AddItems:function(menu,tag,tagName){if (tagName=='SELECT'){menu.AddSeparator();menu.AddItem('Select',FCKLang.SelectionFieldProp,53);}}};case 'Textarea':return {AddItems:function(menu,tag,tagName){if (tagName=='TEXTAREA'){menu.AddSeparator();menu.AddItem('Textarea',FCKLang.TextareaProp,52);}}};case 'BulletedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('UL')){menu.AddSeparator();menu.AddItem('BulletedList',FCKLang.BulletedListProp,27);}}};case 'NumberedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('OL')){menu.AddSeparator();menu.AddItem('NumberedList',FCKLang.NumberedListProp,26);}}};case 'DivContainer':return {AddItems:function(menu,tag,tagName){var J=FCKDomTools.GetSelectedDivContainers();if (J.length>0){menu.AddSeparator();menu.AddItem('EditDiv',FCKLang.EditDiv,75);menu.AddItem('DeleteDiv',FCKLang.DeleteDiv,76);}}};};return null;};function FCK_ContextMenu_OnBeforeOpen(){FCK.Events.FireEvent('OnSelectionChange');var A,sTagName;if ((A=FCKSelection.GetSelectedElement())) sTagName=A.tagName;var B=FCK.ContextMenu._InnerContextMenu;B.RemoveAllItems();var C=FCK.ContextMenu.Listeners;for (var i=0;i0){D=A.substr(0,B.index);this._sourceHtml=A.substr(B.index);}else{C=true;D=B[0];this._sourceHtml=A.substr(B[0].length);}}else{D=A;this._sourceHtml=null;};return { 'isTag':C,'value':D };},Each:function(A){var B;while ((B=this.Next())) A(B.isTag,B.value);}};var FCKHtmlIterator=function(A){this._sourceHtml=A;};FCKHtmlIterator.prototype={Next:function(){var A=this._sourceHtml;if (A==null) return null;var B=FCKRegexLib.HtmlTag.exec(A);var C=false;var D="";if (B){if (B.index>0){D=A.substr(0,B.index);this._sourceHtml=A.substr(B.index);}else{C=true;D=B[0];this._sourceHtml=A.substr(B[0].length);}}else{D=A;this._sourceHtml=null;};return { 'isTag':C,'value':D };},Each:function(A){var B;while ((B=this.Next())) A(B.isTag,B.value);}}; +var FCKPlugin=function(A,B,C){this.Name=A;this.BasePath=C?C:FCKConfig.PluginsPath;this.Path=this.BasePath+A+'/';if (!B||B.length==0) this.AvailableLangs=[];else this.AvailableLangs=B.split(',');};FCKPlugin.prototype.Load=function(){if (this.AvailableLangs.length>0){var A;if (this.AvailableLangs.IndexOf(FCKLanguageManager.ActiveLanguage.Code)>=0) A=FCKLanguageManager.ActiveLanguage.Code;else A=this.AvailableLangs[0];LoadScript(this.Path+'lang/'+A+'.js');};LoadScript(this.Path+'fckplugin.js');}; +var FCKPlugins=FCK.Plugins={};FCKPlugins.ItemsCount=0;FCKPlugins.Items={};FCKPlugins.Load=function(){var A=FCKPlugins.Items;for (var i=0;i-1);};String.prototype.Equals=function(){var A=arguments;if (A.length==1&&A[0].pop) A=A[0];for (var i=0;iC) return false;if (B){var E=new RegExp(A+'$','i');return E.test(this);}else return (D==0||this.substr(C-D,D)==A);};String.prototype.Remove=function(A,B){var s='';if (A>0) s=this.substring(0,A);if (A+B0){var B=A.pop();if (B) B[1].call(B[0]);};this._FCKCleanupObj=null;if (CollectGarbage) CollectGarbage();}; +var s=navigator.userAgent.toLowerCase();var FCKBrowserInfo={IsIE:/*@cc_on!@*/false,IsIE7:/*@cc_on!@*/false&&(parseInt(s.match(/msie (\d+)/)[1],10)>=7),IsIE6:/*@cc_on!@*/false&&(parseInt(s.match(/msie (\d+)/)[1],10)>=6),IsSafari:s.Contains(' applewebkit/'),IsOpera:!!window.opera,IsAIR:s.Contains(' adobeair/'),IsMac:s.Contains('macintosh')};(function(A){A.IsGecko=(navigator.product=='Gecko')&&!A.IsSafari&&!A.IsOpera;A.IsGeckoLike=(A.IsGecko||A.IsSafari||A.IsOpera);if (A.IsGecko){var B=s.match(/rv:(\d+\.\d+)/);var C=B&&parseFloat(B[1]);if (C){A.IsGecko10=(C<1.8);A.IsGecko19=(C>1.8);}}})(FCKBrowserInfo); +var FCKURLParams={};(function(){var A=document.location.search.substr(1).split('&');for (var i=0;i';if (!FCKRegexLib.HtmlOpener.test(A)) A=''+A+'';if (!FCKRegexLib.HeadOpener.test(A)) A=A.replace(FCKRegexLib.HtmlOpener,'$&');return A;}else{var B=FCKConfig.DocType+'0&&!FCKRegexLib.Html4DocType.test(FCKConfig.DocType)) B+=' style="overflow-y: scroll"';B+='>'+A+'';return B;}},ConvertToDataFormat:function(A,B,C,D){var E=FCKXHtml.GetXHTML(A,!B,D);if (C&&FCKRegexLib.EmptyOutParagraph.test(E)) return '';return E;},FixHtml:function(A){return A;}}; +var FCK={Name:FCKURLParams['InstanceName'],Status:0,EditMode:0,Toolbar:null,HasFocus:false,DataProcessor:new FCKDataProcessor(),GetInstanceObject:(function(){var w=window;return function(name){return w[name];}})(),AttachToOnSelectionChange:function(A){this.Events.AttachEvent('OnSelectionChange',A);},GetLinkedFieldValue:function(){return this.LinkedField.value;},GetParentForm:function(){return this.LinkedField.form;},StartupValue:'',IsDirty:function(){if (this.EditMode==1) return (this.StartupValue!=this.EditingArea.Textarea.value);else{if (!this.EditorDocument) return false;return (this.StartupValue!=this.EditorDocument.body.innerHTML);}},ResetIsDirty:function(){if (this.EditMode==1) this.StartupValue=this.EditingArea.Textarea.value;else if (this.EditorDocument.body) this.StartupValue=this.EditorDocument.body.innerHTML;},StartEditor:function(){this.TempBaseTag=FCKConfig.BaseHref.length>0?'':'';var A=FCK.KeystrokeHandler=new FCKKeystrokeHandler();A.OnKeystroke=_FCK_KeystrokeHandler_OnKeystroke;A.SetKeystrokes(FCKConfig.Keystrokes);if (FCKBrowserInfo.IsIE7){if ((CTRL+86) in A.Keystrokes) A.SetKeystrokes([CTRL+86,true]);if ((SHIFT+45) in A.Keystrokes) A.SetKeystrokes([SHIFT+45,true]);};A.SetKeystrokes([CTRL+8,true]);this.EditingArea=new FCKEditingArea(document.getElementById('xEditingArea'));this.EditingArea.FFSpellChecker=FCKConfig.FirefoxSpellChecker;this.SetData(this.GetLinkedFieldValue(),true);FCKTools.AddEventListener(document,"keydown",this._TabKeyHandler);this.AttachToOnSelectionChange(_FCK_PaddingNodeListener);if (FCKBrowserInfo.IsGecko) this.AttachToOnSelectionChange(this._ExecCheckEmptyBlock);},Focus:function(){FCK.EditingArea.Focus();},SetStatus:function(A){this.Status=A;if (A==1){FCKFocusManager.AddWindow(window,true);if (FCKBrowserInfo.IsIE) FCKFocusManager.AddWindow(window.frameElement,true);if (FCKConfig.StartupFocus) FCK.Focus();};this.Events.FireEvent('OnStatusChange',A);},FixBody:function(){var A=FCKConfig.EnterMode;if (A!='p'&&A!='div') return;var B=this.EditorDocument;if (!B) return;var C=B.body;if (!C) return;FCKDomTools.TrimNode(C);var D=C.firstChild;var E;while (D){var F=false;switch (D.nodeType){case 1:var G=D.nodeName.toLowerCase();if (!FCKListsLib.BlockElements[G]&&G!='li'&&!D.getAttribute('_fckfakelement')&&D.getAttribute('_moz_dirty')==null) F=true;break;case 3:if (E||D.nodeValue.Trim().length>0) F=true;break;case 8:if (E) F=true;break;};if (F){var H=D.parentNode;if (!E) E=H.insertBefore(B.createElement(A),D);E.appendChild(H.removeChild(D));D=E.nextSibling;}else{if (E){FCKDomTools.TrimNode(E);E=null;};D=D.nextSibling;}};if (E) FCKDomTools.TrimNode(E);},GetData:function(A){FCK.Events.FireEvent("OnBeforeGetData");if (FCK.EditMode==1) return FCK.EditingArea.Textarea.value;this.FixBody();var B=FCK.EditorDocument;if (!B) return null;var C=FCKConfig.FullPage;var D=FCK.DataProcessor.ConvertToDataFormat(C?B.documentElement:B.body,!C,FCKConfig.IgnoreEmptyParagraphValue,A);D=FCK.ProtectEventsRestore(D);if (FCKBrowserInfo.IsIE) D=D.replace(FCKRegexLib.ToReplace,'$1');if (C){if (FCK.DocTypeDeclaration&&FCK.DocTypeDeclaration.length>0) D=FCK.DocTypeDeclaration+'\n'+D;if (FCK.XmlDeclaration&&FCK.XmlDeclaration.length>0) D=FCK.XmlDeclaration+'\n'+D;};D=FCKConfig.ProtectedSource.Revert(D);setTimeout(function() { FCK.Events.FireEvent("OnAfterGetData");},0);return D;},UpdateLinkedField:function(){var A=FCK.GetXHTML(FCKConfig.FormatOutput);if (FCKConfig.HtmlEncodeOutput) A=FCKTools.HTMLEncode(A);FCK.LinkedField.value=A;FCK.Events.FireEvent('OnAfterLinkedFieldUpdate');},RegisteredDoubleClickHandlers:{},OnDoubleClick:function(A){var B=FCK.RegisteredDoubleClickHandlers[A.tagName.toUpperCase()];if (B){for (var i=0;i0?'|ABBR|XML|EMBED|OBJECT':'ABBR|XML|EMBED|OBJECT';var C;if (B.length>0){C=new RegExp('<('+B+')(?!\w|:)','gi');A=A.replace(C,'','gi');A=A.replace(C,'<\/FCK:$1>');};B='META';if (FCKBrowserInfo.IsIE) B+='|HR';C=new RegExp('<(('+B+')(?=\\s|>|/)[\\s\\S]*?)/?>','gi');A=A.replace(C,'');return A;},SetData:function(A,B){this.EditingArea.Mode=FCK.EditMode;if (FCKBrowserInfo.IsIE&&FCK.EditorDocument){FCK.EditorDocument.detachEvent("onselectionchange",Doc_OnSelectionChange);};FCKTempBin.Reset();FCK.Selection.Release();if (FCK.EditMode==0){this._ForceResetIsDirty=(B===true);A=FCKConfig.ProtectedSource.Protect(A);A=FCK.DataProcessor.ConvertToHtml(A);A=A.replace(FCKRegexLib.InvalidSelfCloseTags,'$1>');A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);if (FCK.TempBaseTag.length>0&&!FCKRegexLib.HasBaseTag.test(A)) A=A.replace(FCKRegexLib.HeadOpener,'$&'+FCK.TempBaseTag);var C='';if (!FCKConfig.FullPage) C+=_FCK_GetEditorAreaStyleTags();if (FCKBrowserInfo.IsIE) C+=FCK._GetBehaviorsStyle();else if (FCKConfig.ShowBorders) C+=FCKTools.GetStyleHtml(FCK_ShowTableBordersCSS,true);C+=FCKTools.GetStyleHtml(FCK_InternalCSS,true);A=A.replace(FCKRegexLib.HeadCloser,C+'$&');this.EditingArea.OnLoad=_FCK_EditingArea_OnLoad;this.EditingArea.Start(A);}else{FCK.EditorWindow=null;FCK.EditorDocument=null;FCKDomTools.PaddingNode=null;this.EditingArea.OnLoad=null;this.EditingArea.Start(A);this.EditingArea.Textarea._FCKShowContextMenu=true;FCK.EnterKeyHandler=null;if (B) this.ResetIsDirty();FCK.KeystrokeHandler.AttachToElement(this.EditingArea.Textarea);this.EditingArea.Textarea.focus();FCK.Events.FireEvent('OnAfterSetHTML');};if (window.onresize) window.onresize();},RedirectNamedCommands:{},ExecuteNamedCommand:function(A,B,C,D){if (!D) FCKUndo.SaveUndoStep();if (!C&&FCK.RedirectNamedCommands[A]!=null) FCK.ExecuteRedirectedNamedCommand(A,B);else{FCK.Focus();FCK.EditorDocument.execCommand(A,false,B);FCK.Events.FireEvent('OnSelectionChange');};if (!D) FCKUndo.SaveUndoStep();},GetNamedCommandState:function(A){try{if (FCKBrowserInfo.IsSafari&&FCK.EditorWindow&&A.IEquals('Paste')) return 0;if (!FCK.EditorDocument.queryCommandEnabled(A)) return -1;else{return FCK.EditorDocument.queryCommandState(A)?1:0;}}catch (e){return 0;}},GetNamedCommandValue:function(A){var B='';var C=FCK.GetNamedCommandState(A);if (C==-1) return null;try{B=this.EditorDocument.queryCommandValue(A);}catch(e) {};return B?B:'';},Paste:function(A){if (FCK.Status!=2||!FCK.Events.FireEvent('OnPaste')) return false;return A||FCK._ExecPaste();},PasteFromWord:function(){FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteFromWord,'dialog/fck_paste.html',400,330,'Word');},Preview:function(){var A;if (FCKConfig.FullPage){if (FCK.TempBaseTag.length>0) A=FCK.TempBaseTag+FCK.GetXHTML();else A=FCK.GetXHTML();}else{A=FCKConfig.DocType+''+FCK.TempBaseTag+''+FCKLang.Preview+''+_FCK_GetEditorAreaStyleTags()+''+FCK.GetXHTML()+'';};var B=FCKConfig.ScreenWidth*0.8;var C=FCKConfig.ScreenHeight*0.7;var D=(FCKConfig.ScreenWidth-B)/2;var E='';if (FCK_IS_CUSTOM_DOMAIN&&FCKBrowserInfo.IsIE){window._FCKHtmlToLoad=A;E='javascript:void( (function(){document.open() ;document.domain="'+document.domain+'" ;document.write( window.opener._FCKHtmlToLoad );document.close() ;window.opener._FCKHtmlToLoad = null ;})() )';};var F=window.open(E,null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+B+',height='+C+',left='+D);if (!FCK_IS_CUSTOM_DOMAIN||!FCKBrowserInfo.IsIE){F.document.write(A);F.document.close();}},SwitchEditMode:function(A){var B=(FCK.EditMode==0);var C=FCK.IsDirty();var D;if (B){FCKCommands.GetCommand('ShowBlocks').SaveState();if (!A&&FCKBrowserInfo.IsIE) FCKUndo.SaveUndoStep();D=FCK.GetXHTML(FCKConfig.FormatSource);if (FCKBrowserInfo.IsIE) FCKTempBin.ToHtml();if (D==null) return false;}else D=this.EditingArea.Textarea.value;FCK.EditMode=B?1:0;FCK.SetData(D,!C);FCK.Focus();FCKTools.RunFunction(FCK.ToolbarSet.RefreshModeState,FCK.ToolbarSet);return true;},InsertElement:function(A){if (typeof A=='string') A=this.EditorDocument.createElement(A);var B=A.nodeName.toLowerCase();FCKSelection.Restore();var C=new FCKDomRange(this.EditorWindow);C.MoveToSelection();C.DeleteContents();if (FCKListsLib.BlockElements[B]!=null){if (C.StartBlock){if (C.CheckStartOfBlock()) C.MoveToPosition(C.StartBlock,3);else if (C.CheckEndOfBlock()) C.MoveToPosition(C.StartBlock,4);else C.SplitBlock();};C.InsertNode(A);var D=FCKDomTools.GetNextSourceElement(A,false,null,['hr','br','param','img','area','input'],true);if (!D&&FCKConfig.EnterMode!='br'){D=this.EditorDocument.body.appendChild(this.EditorDocument.createElement(FCKConfig.EnterMode));if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(D);};if (FCKListsLib.EmptyElements[B]==null) C.MoveToElementEditStart(A);else if (D) C.MoveToElementEditStart(D);else C.MoveToPosition(A,4);if (FCKBrowserInfo.IsGeckoLike){if (D) FCKDomTools.ScrollIntoView(D,false);FCKDomTools.ScrollIntoView(A,false);}}else{C.InsertNode(A);C.SetStart(A,4);C.SetEnd(A,4);};C.Select();C.Release();this.Focus();return A;},_InsertBlockElement:function(A){},_IsFunctionKey:function(A){if (A>=16&&A<=20) return true;if (A==27||(A>=33&&A<=40)) return true;if (A==45) return true;return false;},_KeyDownListener:function(A){if (!A) A=FCK.EditorWindow.event;if (FCK.EditorWindow){if (!FCK._IsFunctionKey(A.keyCode)&&!(A.ctrlKey||A.metaKey)&&!(A.keyCode==46)) FCK._KeyDownUndo();};return true;},_KeyDownUndo:function(){if (!FCKUndo.Typing){FCKUndo.SaveUndoStep();FCKUndo.Typing=true;FCK.Events.FireEvent("OnSelectionChange");};FCKUndo.TypesCount++;FCKUndo.Changed=1;if (FCKUndo.TypesCount>FCKUndo.MaxTypes){FCKUndo.TypesCount=0;FCKUndo.SaveUndoStep();}},_TabKeyHandler:function(A){if (!A) A=window.event;var B=A.keyCode;if (B==9&&FCK.EditMode!=0){if (FCKBrowserInfo.IsIE){var C=document.selection.createRange();if (C.parentElement()!=FCK.EditingArea.Textarea) return true;C.text='\t';C.select();}else{var a=[];var D=FCK.EditingArea.Textarea;var E=D.selectionStart;var F=D.selectionEnd;a.push(D.value.substr(0,E));a.push('\t');a.push(D.value.substr(F));D.value=a.join('');D.setSelectionRange(E+1,E+1);};if (A.preventDefault) return A.preventDefault();return A.returnValue=false;};return true;}};FCK.Events=new FCKEvents(FCK);FCK.GetHTML=FCK.GetXHTML=FCK.GetData;FCK.SetHTML=FCK.SetData;FCK.InsertElementAndGetIt=FCK.CreateElement=FCK.InsertElement;function _FCK_ProtectEvents_ReplaceTags(A){return A.replace(FCKRegexLib.EventAttributes,_FCK_ProtectEvents_ReplaceEvents);};function _FCK_ProtectEvents_ReplaceEvents(A,B){return ' '+B+'_fckprotectedatt="'+encodeURIComponent(A)+'"';};function _FCK_ProtectEvents_RestoreEvents(A,B){return decodeURIComponent(B);};function _FCK_MouseEventsListener(A){if (!A) A=window.event;if (A.type=='mousedown') FCK.MouseDownFlag=true;else if (A.type=='mouseup') FCK.MouseDownFlag=false;else if (A.type=='mousemove') FCK.Events.FireEvent('OnMouseMove',A);};function _FCK_PaddingNodeListener(){if (FCKConfig.EnterMode.IEquals('br')) return;FCKDomTools.EnforcePaddingNode(FCK.EditorDocument,FCKConfig.EnterMode);if (!FCKBrowserInfo.IsIE&&FCKDomTools.PaddingNode){var A=FCKSelection.GetSelection();if (A&&A.rangeCount==1){var B=A.getRangeAt(0);if (B.collapsed&&B.startContainer==FCK.EditorDocument.body&&B.startOffset==0){B.selectNodeContents(FCKDomTools.PaddingNode);B.collapse(true);A.removeAllRanges();A.addRange(B);}}}else if (FCKDomTools.PaddingNode){var C=FCKSelection.GetParentElement();var D=FCKDomTools.PaddingNode;if (C&&C.nodeName.IEquals('body')){if (FCK.EditorDocument.body.childNodes.length==1&&FCK.EditorDocument.body.firstChild==D){if (FCKSelection._GetSelectionDocument(FCK.EditorDocument.selection)!=FCK.EditorDocument) return;var B=FCK.EditorDocument.body.createTextRange();var F=false;if (!D.childNodes.firstChild){D.appendChild(FCKTools.GetElementDocument(D).createTextNode('\ufeff'));F=true;};B.moveToElementText(D);B.select();if (F) B.pasteHTML('');}}}};function _FCK_EditingArea_OnLoad(){FCK.EditorWindow=FCK.EditingArea.Window;FCK.EditorDocument=FCK.EditingArea.Document;if (FCKBrowserInfo.IsIE) FCKTempBin.ToElements();FCK.InitializeBehaviors();FCK.MouseDownFlag=false;FCKTools.AddEventListener(FCK.EditorDocument,'mousemove',_FCK_MouseEventsListener);FCKTools.AddEventListener(FCK.EditorDocument,'mousedown',_FCK_MouseEventsListener);FCKTools.AddEventListener(FCK.EditorDocument,'mouseup',_FCK_MouseEventsListener);if (FCKBrowserInfo.IsSafari){FCKTools.AddEventListener(FCK.EditorDocument,'paste',function(evt){var A=new FCKDomRange(FCK.EditorWindow);var B=FCK.EditorDocument.createTextNode('\ufeff');var C=FCK.EditorDocument.createElement('a');C.id='fck_paste_padding';C.innerHTML='';A.MoveToSelection();A.DeleteContents();A.InsertNode(B);A.Collapse();A.InsertNode(C);A.MoveToPosition(C,3);A.Select();setTimeout(function(){B.parentNode.removeChild(B);C=FCK.EditorDocument.getElementById('fck_paste_padding');C.parentNode.removeChild(C);},0);});};if (FCKBrowserInfo.IsSafari){var D=function(evt){if (!(evt.ctrlKey||evt.metaKey)) return;if (FCK.EditMode!=0) return;switch (evt.keyCode){case 89:FCKUndo.Redo();break;case 90:FCKUndo.Undo();break;}};FCKTools.AddEventListener(FCK.EditorDocument,'keyup',D);};FCK.EnterKeyHandler=new FCKEnterKey(FCK.EditorWindow,FCKConfig.EnterMode,FCKConfig.ShiftEnterMode,FCKConfig.TabSpaces);FCK.KeystrokeHandler.AttachToElement(FCK.EditorDocument);if (FCK._ForceResetIsDirty) FCK.ResetIsDirty();if (FCKBrowserInfo.IsIE&&FCK.HasFocus) FCK.EditorDocument.body.setActive();FCK.OnAfterSetHTML();FCKCommands.GetCommand('ShowBlocks').RestoreState();if (FCK.Status!=0) return;FCK.SetStatus(1);};function _FCK_GetEditorAreaStyleTags(){return FCKTools.GetStyleHtml(FCKConfig.EditorAreaCSS)+FCKTools.GetStyleHtml(FCKConfig.EditorAreaStyles);};function _FCK_KeystrokeHandler_OnKeystroke(A,B){if (FCK.Status!=2) return false;if (FCK.EditMode==0){switch (B){case 'Paste':return!FCK.Paste();case 'Cut':FCKUndo.SaveUndoStep();return false;}}else{if (B.Equals('Paste','Undo','Redo','SelectAll','Cut')) return false;};var C=FCK.Commands.GetCommand(B);if (C.GetState()==-1) return false;return (C.Execute.apply(C,FCKTools.ArgumentsToArray(arguments,2))!==false);};(function(){var A=window.parent.document;var B=A.getElementById(FCK.Name);var i=0;while (B||i==0){if (B&&B.tagName.toLowerCase().Equals('input','textarea')){FCK.LinkedField=B;break;};B=A.getElementsByName(FCK.Name)[i++];}})();var FCKTempBin={Elements:[],AddElement:function(A){var B=this.Elements.length;this.Elements[B]=A;return B;},RemoveElement:function(A){var e=this.Elements[A];this.Elements[A]=null;return e;},Reset:function(){var i=0;while (i '+this.Elements[i].outerHTML+'';this.Elements[i].isHtml=true;}},ToElements:function(){var A=FCK.EditorDocument.createElement('div');for (var i=0;i0) C+='TABLE { behavior: '+B+' ; }';C+='';FCK._BehaviorsStyle=C;};return FCK._BehaviorsStyle;};function Doc_OnMouseUp(){if (FCK.EditorWindow.event.srcElement.tagName=='HTML'){FCK.Focus();FCK.EditorWindow.event.cancelBubble=true;FCK.EditorWindow.event.returnValue=false;}};function Doc_OnPaste(){var A=FCK.EditorDocument.body;A.detachEvent('onpaste',Doc_OnPaste);var B=FCK.Paste(!FCKConfig.ForcePasteAsPlainText&&!FCKConfig.AutoDetectPasteFromWord);A.attachEvent('onpaste',Doc_OnPaste);return B;};function Doc_OnDblClick(){FCK.OnDoubleClick(FCK.EditorWindow.event.srcElement);FCK.EditorWindow.event.cancelBubble=true;};function Doc_OnSelectionChange(){if (!FCK.IsSelectionChangeLocked&&FCK.EditorDocument) FCK.Events.FireEvent("OnSelectionChange");};function Doc_OnDrop(){if (FCK.MouseDownFlag){FCK.MouseDownFlag=false;return;};if (FCKConfig.ForcePasteAsPlainText){var A=FCK.EditorWindow.event;if (FCK._CheckIsPastingEnabled()||FCKConfig.ShowDropDialog) FCK.PasteAsPlainText(A.dataTransfer.getData('Text'));A.returnValue=false;A.cancelBubble=true;}};FCK.InitializeBehaviors=function(A){this.EditorDocument.attachEvent('onmouseup',Doc_OnMouseUp);this.EditorDocument.body.attachEvent('onpaste',Doc_OnPaste);this.EditorDocument.body.attachEvent('ondrop',Doc_OnDrop);FCK.ContextMenu._InnerContextMenu.AttachToElement(FCK.EditorDocument.body);this.EditorDocument.attachEvent("onkeydown",FCK._KeyDownListener);this.EditorDocument.attachEvent("ondblclick",Doc_OnDblClick);this.EditorDocument.attachEvent("onbeforedeactivate",function(){ FCKSelection.Save();});this.EditorDocument.attachEvent("onselectionchange",Doc_OnSelectionChange);FCKTools.AddEventListener(FCK.EditorDocument,'mousedown',Doc_OnMouseDown);};FCK.InsertHtml=function(A){A=FCKConfig.ProtectedSource.Protect(A);A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);FCKSelection.Restore();FCK.EditorWindow.focus();FCKUndo.SaveUndoStep();var B=FCKSelection.GetSelection();if (B.type.toLowerCase()=='control') B.clear();A=''+A;B.createRange().pasteHTML(A);var C=FCK.EditorDocument.getElementById('__fakeFCKRemove__');if (C.parentNode.childNodes.length==1) C=C.parentNode;C.removeNode(true);FCKDocumentProcessor.Process(FCK.EditorDocument);this.Events.FireEvent("OnSelectionChange");};FCK.SetInnerHtml=function(A){var B=FCK.EditorDocument;B.body.innerHTML='
     
    '+A;B.getElementById('__fakeFCKRemove__').removeNode(true);};function FCK_PreloadImages(){var A=new FCKImagePreloader();A.AddImages(FCKConfig.PreloadImages);A.AddImages(FCKConfig.SkinPath+'fck_strip.gif');A.OnComplete=LoadToolbarSetup;A.Start();};function Document_OnContextMenu(){return (event.srcElement._FCKShowContextMenu==true);};document.oncontextmenu=Document_OnContextMenu;function FCK_Cleanup(){this.LinkedField=null;this.EditorWindow=null;this.EditorDocument=null;};FCK._ExecPaste=function(){if (FCK._PasteIsRunning) return true;if (FCKConfig.ForcePasteAsPlainText){FCK.PasteAsPlainText();return false;};var A=FCK._CheckIsPastingEnabled(true);if (A===false) FCKTools.RunFunction(FCKDialog.OpenDialog,FCKDialog,['FCKDialog_Paste',FCKLang.Paste,'dialog/fck_paste.html',400,330,'Security']);else{if (FCKConfig.AutoDetectPasteFromWord&&A.length>0){var B=/<\w[^>]*(( class="?MsoNormal"?)|(="mso-))/gi;if (B.test(A)){if (confirm(FCKLang.PasteWordConfirm)){FCK.PasteFromWord();return false;}}};FCK._PasteIsRunning=true;FCK.ExecuteNamedCommand('Paste');delete FCK._PasteIsRunning;};return false;};FCK.PasteAsPlainText=function(A){if (!FCK._CheckIsPastingEnabled()){FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteAsText,'dialog/fck_paste.html',400,330,'PlainText');return;};var B=null;if (!A) B=clipboardData.getData("Text");else B=A;if (B&&B.length>0){B=FCKTools.HTMLEncode(B);B=FCKTools.ProcessLineBreaks(window,FCKConfig,B);var C=B.search('

    ');var D=B.search('

    ');if ((C!=-1&&D!=-1&&C0){if (D){var F=this.EditorDocument.createElement('A');F.href=A;var G=E;G.parentNode.insertBefore(F,G);G.parentNode.removeChild(G);F.appendChild(G);return [F];};var H='javascript:void(0);/*'+(new Date().getTime())+'*/';FCK.ExecuteNamedCommand('CreateLink',H,false,!!B);var I=this.EditorDocument.links;for (i=0;i0&&!isNaN(E)) this.PageConfig[D]=parseFloat(E);else this.PageConfig[D]=E;}};function FCKConfig_LoadPageConfig(){var A=FCKConfig.PageConfig;for (var B in A) FCKConfig[B]=A[B];};function FCKConfig_PreProcess(){var A=FCKConfig;if (A.AllowQueryStringDebug){try{if ((/fckdebug=true/i).test(window.top.location.search)) A.Debug=true;}catch (e) { }};if (!A.PluginsPath.EndsWith('/')) A.PluginsPath+='/';var B=A.ToolbarComboPreviewCSS;if (!B||B.length==0) A.ToolbarComboPreviewCSS=A.EditorAreaCSS;A.RemoveAttributesArray=(A.RemoveAttributes||'').split(',');if (!FCKConfig.SkinEditorCSS||FCKConfig.SkinEditorCSS.length==0) FCKConfig.SkinEditorCSS=FCKConfig.SkinPath+'fck_editor.css';if (!FCKConfig.SkinDialogCSS||FCKConfig.SkinDialogCSS.length==0) FCKConfig.SkinDialogCSS=FCKConfig.SkinPath+'fck_dialog.css';};FCKConfig.ToolbarSets={};FCKConfig.Plugins={};FCKConfig.Plugins.Items=[];FCKConfig.Plugins.Add=function(A,B,C){FCKConfig.Plugins.Items.push([A,B,C]);};FCKConfig.ProtectedSource={};FCKConfig.ProtectedSource._CodeTag=(new Date()).valueOf();FCKConfig.ProtectedSource.RegexEntries=[//g,//gi,//gi];FCKConfig.ProtectedSource.Add=function(A){this.RegexEntries.push(A);};FCKConfig.ProtectedSource.Protect=function(A){var B=this._CodeTag;function _Replace(protectedSource){var C=FCKTempBin.AddElement(protectedSource);return '';};for (var i=0;i|>)","g");return A.replace(D,_Replace);};FCKConfig.GetBodyAttributes=function(){var A='';if (this.BodyId&&this.BodyId.length>0) A+=' id="'+this.BodyId+'"';if (this.BodyClass&&this.BodyClass.length>0) A+=' class="'+this.BodyClass+'"';return A;};FCKConfig.ApplyBodyAttributes=function(A){if (this.BodyId&&this.BodyId.length>0) A.id=FCKConfig.BodyId;if (this.BodyClass&&this.BodyClass.length>0) A.className+=' '+FCKConfig.BodyClass;}; +var FCKDebug={Output:function(){},OutputObject:function(){}}; +var FCKDomTools={MoveChildren:function(A,B,C){if (A==B) return;var D;if (C){while ((D=A.lastChild)) B.insertBefore(A.removeChild(D),B.firstChild);}else{while ((D=A.firstChild)) B.appendChild(A.removeChild(D));}},MoveNode:function(A,B,C){if (C) B.insertBefore(FCKDomTools.RemoveNode(A),B.firstChild);else B.appendChild(FCKDomTools.RemoveNode(A));},TrimNode:function(A){this.LTrimNode(A);this.RTrimNode(A);},LTrimNode:function(A){var B;while ((B=A.firstChild)){if (B.nodeType==3){var C=B.nodeValue.LTrim();var D=B.nodeValue.length;if (C.length==0){A.removeChild(B);continue;}else if (C.length0) break;if (A.lastChild) A=A.lastChild;else return this.GetPreviousSourceElement(A,B,C,D);};return null;},GetNextSourceElement:function(A,B,C,D,E){while((A=this.GetNextSourceNode(A,E))){if (A.nodeType==1){if (C&&A.nodeName.IEquals(C)) break;if (D&&A.nodeName.IEquals(D)) return this.GetNextSourceElement(A,B,C,D);return A;}else if (B&&A.nodeType==3&&A.nodeValue.RTrim().length>0) break;};return null;},GetNextSourceNode:function(A,B,C,D){if (!A) return null;var E;if (!B&&A.firstChild) E=A.firstChild;else{if (D&&A==D) return null;E=A.nextSibling;if (!E&&(!D||D!=A.parentNode)) return this.GetNextSourceNode(A.parentNode,true,C,D);};if (C&&E&&E.nodeType!=C) return this.GetNextSourceNode(E,false,C,D);return E;},GetPreviousSourceNode:function(A,B,C,D){if (!A) return null;var E;if (!B&&A.lastChild) E=A.lastChild;else{if (D&&A==D) return null;E=A.previousSibling;if (!E&&(!D||D!=A.parentNode)) return this.GetPreviousSourceNode(A.parentNode,true,C,D);};if (C&&E&&E.nodeType!=C) return this.GetPreviousSourceNode(E,false,C,D);return E;},InsertAfterNode:function(A,B){return A.parentNode.insertBefore(B,A.nextSibling);},GetParents:function(A){var B=[];while (A){B.unshift(A);A=A.parentNode;};return B;},GetCommonParents:function(A,B){var C=this.GetParents(A);var D=this.GetParents(B);var E=[];for (var i=0;i0) D[C.pop().toLowerCase()]=1;var E=this.GetCommonParents(A,B);var F=null;while ((F=E.pop())){if (D[F.nodeName.toLowerCase()]) return F;};return null;},GetIndexOf:function(A){var B=A.parentNode?A.parentNode.firstChild:null;var C=-1;while (B){C++;if (B==A) return C;B=B.nextSibling;};return-1;},PaddingNode:null,EnforcePaddingNode:function(A,B){try{if (!A||!A.body) return;}catch (e){return;};this.CheckAndRemovePaddingNode(A,B,true);try{if (A.body.lastChild&&(A.body.lastChild.nodeType!=1||A.body.lastChild.tagName.toLowerCase()==B.toLowerCase())) return;}catch (e){return;};var C=A.createElement(B);if (FCKBrowserInfo.IsGecko&&FCKListsLib.NonEmptyBlockElements[B]) FCKTools.AppendBogusBr(C);this.PaddingNode=C;if (A.body.childNodes.length==1&&A.body.firstChild.nodeType==1&&A.body.firstChild.tagName.toLowerCase()=='br'&&(A.body.firstChild.getAttribute('_moz_dirty')!=null||A.body.firstChild.getAttribute('type')=='_moz')) A.body.replaceChild(C,A.body.firstChild);else A.body.appendChild(C);},CheckAndRemovePaddingNode:function(A,B,C){var D=this.PaddingNode;if (!D) return;try{if (D.parentNode!=A.body||D.tagName.toLowerCase()!=B||(D.childNodes.length>1)||(D.firstChild&&D.firstChild.nodeValue!='\xa0'&&String(D.firstChild.tagName).toLowerCase()!='br')){this.PaddingNode=null;return;}}catch (e){this.PaddingNode=null;return;};if (!C){if (D.parentNode.childNodes.length>1) D.parentNode.removeChild(D);this.PaddingNode=null;}},HasAttribute:function(A,B){if (A.hasAttribute) return A.hasAttribute(B);else{var C=A.attributes[B];return (C!=undefined&&C.specified);}},HasAttributes:function(A){var B=A.attributes;for (var i=0;i0) return true;continue;}};if (B[i].specified) return true;};return false;},RemoveAttribute:function(A,B){if (FCKBrowserInfo.IsIE&&B.toLowerCase()=='class') B='className';return A.removeAttribute(B,0);},RemoveAttributes:function (A,B){for (var i=0;i0) return false;C=C.nextSibling;};return D?this.CheckIsEmptyElement(D,B):true;},SetElementStyles:function(A,B){var C=A.style;for (var D in B) C[D]=B[D];},SetOpacity:function(A,B){if (FCKBrowserInfo.IsIE){B=Math.round(B*100);A.style.filter=(B>100?'':'progid:DXImageTransform.Microsoft.Alpha(opacity='+B+')');}else A.style.opacity=B;},GetCurrentElementStyle:function(A,B){if (FCKBrowserInfo.IsIE) return A.currentStyle[B];else return A.ownerDocument.defaultView.getComputedStyle(A,'').getPropertyValue(B);},GetPositionedAncestor:function(A){var B=A;while (B!=FCKTools.GetElementDocument(B).documentElement){if (this.GetCurrentElementStyle(B,'position')!='static') return B;if (B==FCKTools.GetElementDocument(B).documentElement&¤tWindow!=w) B=currentWindow.frameElement;else B=B.parentNode;};return null;},ScrollIntoView:function(A,B){var C=FCKTools.GetElementWindow(A);var D=FCKTools.GetViewPaneSize(C).Height;var E=D*-1;if (B===false){E+=A.offsetHeight||0;E+=parseInt(this.GetCurrentElementStyle(A,'marginBottom')||0,10)||0;};var F=FCKTools.GetDocumentPosition(C,A);E+=F.y;var G=FCKTools.GetScrollPosition(C).Y;if (E>0&&(E>G||E'+styleDef+'';};var C=function(cssFileUrl,markTemp){if (cssFileUrl.length==0) return '';var B=markTemp?' _fcktemp="true"':'';return '';};return function(cssFileOrArrayOrDef,markTemp){if (!cssFileOrArrayOrDef) return '';if (typeof(cssFileOrArrayOrDef)=='string'){if (/[\\\/\.][^{}]*$/.test(cssFileOrArrayOrDef)){return this.GetStyleHtml(cssFileOrArrayOrDef.split(','),markTemp);}else return A(this._GetUrlFixedCss(cssFileOrArrayOrDef),markTemp);}else{var E='';for (var i=0;i/g,'>');return A;};FCKTools.HTMLDecode=function(A){if (!A) return '';A=A.replace(/>/g,'>');A=A.replace(/</g,'<');A=A.replace(/&/g,'&');return A;};FCKTools._ProcessLineBreaksForPMode=function(A,B,C,D,E){var F=0;var G="

    ";var H="

    ";var I="
    ";if (C){G="
  • ";H="
  • ";F=1;}while (D&&D!=A.FCK.EditorDocument.body){if (D.tagName.toLowerCase()=='p'){F=1;break;};D=D.parentNode;};for (var i=0;i0) return A[A.length-1];return null;};FCKTools.GetDocumentPosition=function(w,A){var x=0;var y=0;var B=A;var C=null;var D=FCKTools.GetElementWindow(B);while (B&&!(D==w&&(B==w.document.body||B==w.document.documentElement))){x+=B.offsetLeft-B.scrollLeft;y+=B.offsetTop-B.scrollTop;if (!FCKBrowserInfo.IsOpera){var E=C;while (E&&E!=B){x-=E.scrollLeft;y-=E.scrollTop;E=E.parentNode;}};C=B;if (B.offsetParent) B=B.offsetParent;else{if (D!=w){B=D.frameElement;C=null;if (B) D=B.contentWindow.parent;}else B=null;}};if (FCKDomTools.GetCurrentElementStyle(w.document.body,'position')!='static'||(FCKBrowserInfo.IsIE&&FCKDomTools.GetPositionedAncestor(A)==null)){x+=w.document.body.offsetLeft;y+=w.document.body.offsetTop;};return { "x":x,"y":y };};FCKTools.GetWindowPosition=function(w,A){var B=this.GetDocumentPosition(w,A);var C=FCKTools.GetScrollPosition(w);B.x-=C.X;B.y-=C.Y;return B;};FCKTools.ProtectFormStyles=function(A){if (!A||A.nodeType!=1||A.tagName.toLowerCase()!='form') return [];var B=[];var C=['style','className'];for (var i=0;i0){for (var i=B.length-1;i>=0;i--){var C=B[i][0];var D=B[i][1];if (D) A.insertBefore(C,D);else A.appendChild(C);}}};FCKTools.GetNextNode=function(A,B){if (A.firstChild) return A.firstChild;else if (A.nextSibling) return A.nextSibling;else{var C=A.parentNode;while (C){if (C==B) return null;if (C.nextSibling) return C.nextSibling;else C=C.parentNode;}};return null;};FCKTools.GetNextTextNode=function(A,B,C){node=this.GetNextNode(A,B);if (C&&node&&C(node)) return null;while (node&&node.nodeType!=3){node=this.GetNextNode(node,B);if (C&&node&&C(node)) return null;};return node;};FCKTools.Merge=function(){var A=arguments;var o=A[0];for (var i=1;i');document.domain = '"+FCK_RUNTIME_DOMAIN+"';document.close();}() ) ;";if (FCKBrowserInfo.IsIE){if (FCKBrowserInfo.IsIE7||!FCKBrowserInfo.IsIE6) return "";else return "javascript: '';";};return "javascript: void(0);";};FCKTools.ResetStyles=function(A){A.style.cssText='margin:0;padding:0;border:0;background-color:transparent;background-image:none;';}; +FCKTools.CancelEvent=function(e){return false;};FCKTools._AppendStyleSheet=function(A,B){return A.createStyleSheet(B).owningElement;};FCKTools.AppendStyleString=function(A,B){if (!B) return null;var s=A.createStyleSheet("");s.cssText=B;return s;};FCKTools.ClearElementAttributes=function(A){A.clearAttributes();};FCKTools.GetAllChildrenIds=function(A){var B=[];for (var i=0;i0) B[B.length]=C;};return B;};FCKTools.RemoveOuterTags=function(e){e.insertAdjacentHTML('beforeBegin',e.innerHTML);e.parentNode.removeChild(e);};FCKTools.CreateXmlObject=function(A){var B;switch (A){case 'XmlHttp':if (document.location.protocol!='file:') try { return new XMLHttpRequest();} catch (e) {};B=['MSXML2.XmlHttp','Microsoft.XmlHttp'];break;case 'DOMDocument':B=['MSXML2.DOMDocument','Microsoft.XmlDom'];break;};for (var i=0;i<2;i++){try { return new ActiveXObject(B[i]);}catch (e){}};if (FCKLang.NoActiveX){alert(FCKLang.NoActiveX);FCKLang.NoActiveX=null;};return null;};FCKTools.DisableSelection=function(A){A.unselectable='on';var e,i=0;while ((e=A.all[i++])){switch (e.tagName){case 'IFRAME':case 'TEXTAREA':case 'INPUT':case 'SELECT':break;default:e.unselectable='on';}}};FCKTools.GetScrollPosition=function(A){var B=A.document;var C={ X:B.documentElement.scrollLeft,Y:B.documentElement.scrollTop };if (C.X>0||C.Y>0) return C;return { X:B.body.scrollLeft,Y:B.body.scrollTop };};FCKTools.AddEventListener=function(A,B,C){A.attachEvent('on'+B,C);};FCKTools.RemoveEventListener=function(A,B,C){A.detachEvent('on'+B,C);};FCKTools.AddEventListenerEx=function(A,B,C,D){var o={};o.Source=A;o.Params=D||[];o.Listener=function(ev){return C.apply(o.Source,[ev].concat(o.Params));};if (FCK.IECleanup) FCK.IECleanup.AddItem(null,function() { o.Source=null;o.Params=null;});A.attachEvent('on'+B,o.Listener);A=null;D=null;};FCKTools.GetViewPaneSize=function(A){var B;var C=A.document.documentElement;if (C&&C.clientWidth) B=C;else B=A.document.body;if (B) return { Width:B.clientWidth,Height:B.clientHeight };else return { Width:0,Height:0 };};FCKTools.SaveStyles=function(A){var B=FCKTools.ProtectFormStyles(A);var C={};if (A.className.length>0){C.Class=A.className;A.className='';};var D=A.style.cssText;if (D.length>0){C.Inline=D;A.style.cssText='';};FCKTools.RestoreFormStyles(A,B);return C;};FCKTools.RestoreStyles=function(A,B){var C=FCKTools.ProtectFormStyles(A);A.className=B.Class||'';A.style.cssText=B.Inline||'';FCKTools.RestoreFormStyles(A,C);};FCKTools.RegisterDollarFunction=function(A){A.$=A.document.getElementById;};FCKTools.AppendElement=function(A,B){return A.appendChild(this.GetElementDocument(A).createElement(B));};FCKTools.ToLowerCase=function(A){return A.toLowerCase();}; +var FCKeditorAPI;function InitializeAPI(){var A=window.parent;if (!(FCKeditorAPI=A.FCKeditorAPI)){var B='window.FCKeditorAPI = {Version : "2.6.5",VersionBuild : "23959",Instances : window.FCKeditorAPI && window.FCKeditorAPI.Instances || {},GetInstance : function( name ){return this.Instances[ name ];},_FormSubmit : function(){for ( var name in FCKeditorAPI.Instances ){var oEditor = FCKeditorAPI.Instances[ name ] ;if ( oEditor.GetParentForm && oEditor.GetParentForm() == this )oEditor.UpdateLinkedField() ;}this._FCKOriginalSubmit() ;},_FunctionQueue : window.FCKeditorAPI && window.FCKeditorAPI._FunctionQueue || {Functions : new Array(),IsRunning : false,Add : function( f ){this.Functions.push( f );if ( !this.IsRunning )this.StartNext();},StartNext : function(){var aQueue = this.Functions ;if ( aQueue.length > 0 ){this.IsRunning = true;aQueue[0].call();}else this.IsRunning = false;},Remove : function( f ){var aQueue = this.Functions;var i = 0, fFunc;while( (fFunc = aQueue[ i ]) ){if ( fFunc == f )aQueue.splice( i,1 );i++ ;}this.StartNext();}}}';if (A.execScript) A.execScript(B,'JavaScript');else{if (FCKBrowserInfo.IsGecko10){eval.call(A,B);}else if(FCKBrowserInfo.IsAIR){FCKAdobeAIR.FCKeditorAPI_Evaluate(A,B);}else if (FCKBrowserInfo.IsSafari){var C=A.document;var D=C.createElement('script');D.appendChild(C.createTextNode(B));C.documentElement.appendChild(D);}else A.eval(B);};FCKeditorAPI=A.FCKeditorAPI;FCKeditorAPI.__Instances=FCKeditorAPI.Instances;};FCKeditorAPI.Instances[FCK.Name]=FCK;};function _AttachFormSubmitToAPI(){var A=FCK.GetParentForm();if (A){FCKTools.AddEventListener(A,'submit',FCK.UpdateLinkedField);if (!A._FCKOriginalSubmit&&(typeof(A.submit)=='function'||(!A.submit.tagName&&!A.submit.length))){A._FCKOriginalSubmit=A.submit;A.submit=FCKeditorAPI._FormSubmit;}}};function FCKeditorAPI_Cleanup(){if (window.FCKConfig&&FCKConfig.MsWebBrowserControlCompat&&!window.FCKUnloadFlag) return;delete FCKeditorAPI.Instances[FCK.Name];};function FCKeditorAPI_ConfirmCleanup(){if (window.FCKConfig&&FCKConfig.MsWebBrowserControlCompat) window.FCKUnloadFlag=true;};FCKTools.AddEventListener(window,'unload',FCKeditorAPI_Cleanup);FCKTools.AddEventListener(window,'beforeunload',FCKeditorAPI_ConfirmCleanup); +var FCKImagePreloader=function(){this._Images=[];};FCKImagePreloader.prototype={AddImages:function(A){if (typeof(A)=='string') A=A.split(';');this._Images=this._Images.concat(A);},Start:function(){var A=this._Images;this._PreloadCount=A.length;for (var i=0;i]*\>)/i,AfterBody:/(\<\/body\>[\s\S]*$)/i,ToReplace:/___fcktoreplace:([\w]+)/ig,MetaHttpEquiv:/http-equiv\s*=\s*["']?([^"' ]+)/i,HasBaseTag:/]/i,HtmlOpener:/]*>/i,HeadOpener:/]*>/i,HeadCloser:/<\/head\s*>/i,FCK_Class:/\s*FCK__[^ ]*(?=\s+|$)/,ElementName:/(^[a-z_:][\w.\-:]*\w$)|(^[a-z_]$)/,ForceSimpleAmpersand:/___FCKAmp___/g,SpaceNoClose:/\/>/g,EmptyParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>\s*(<\/\1>)?$/,EmptyOutParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>(?:\s*| | )(<\/\1>)?$/,TagBody:/>]+))/gi,ProtectUrlsA:/]+))/gi,ProtectUrlsArea:/]+))/gi,Html4DocType:/HTML 4\.0 Transitional/i,DocTypeTag:/]*>/i,HtmlDocType:/DTD HTML/,TagsWithEvent:/<[^\>]+ on\w+[\s\r\n]*=[\s\r\n]*?('|")[\s\S]+?\>/g,EventAttributes:/\s(on\w+)[\s\r\n]*=[\s\r\n]*?('|")([\s\S]*?)\2/g,ProtectedEvents:/\s\w+_fckprotectedatt="([^"]+)"/g,StyleProperties:/\S+\s*:/g,InvalidSelfCloseTags:/(<(?!base|meta|link|hr|br|param|img|area|input)([a-zA-Z0-9:]+)[^>]*)\/>/gi,StyleVariableAttName:/#\(\s*("|')(.+?)\1[^\)]*\s*\)/g,RegExp:/^\/(.*)\/([gim]*)$/,HtmlTag:/<[^\s<>](?:"[^"]*"|'[^']*'|[^<])*>/}; +var FCKListsLib={BlockElements:{ address:1,blockquote:1,center:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,marquee:1,noscript:1,ol:1,p:1,pre:1,script:1,table:1,ul:1 },NonEmptyBlockElements:{ p:1,div:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,address:1,pre:1,ol:1,ul:1,li:1,td:1,th:1 },InlineChildReqElements:{ abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 },InlineNonEmptyElements:{ a:1,abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 },EmptyElements:{ base:1,col:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 },PathBlockElements:{ address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,li:1,dt:1,de:1 },PathBlockLimitElements:{ body:1,div:1,td:1,th:1,caption:1,form:1 },StyleBlockElements:{ address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1 },StyleObjectElements:{ img:1,hr:1,li:1,table:1,tr:1,td:1,embed:1,object:1,ol:1,ul:1 },NonEditableElements:{ button:1,option:1,script:1,iframe:1,textarea:1,object:1,embed:1,map:1,applet:1 },BlockBoundaries:{ p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,address:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1,table:1,thead:1,tbody:1,tfoot:1,tr:1,th:1,td:1,caption:1,col:1,colgroup:1,blockquote:1,body:1 },ListBoundaries:{ p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,address:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1,table:1,thead:1,tbody:1,tfoot:1,tr:1,th:1,td:1,caption:1,col:1,colgroup:1,blockquote:1,body:1,br:1 }}; +var FCKLanguageManager=FCK.Language={AvailableLanguages:{af:'Afrikaans',ar:'Arabic',bg:'Bulgarian',bn:'Bengali/Bangla',bs:'Bosnian',ca:'Catalan',cs:'Czech',da:'Danish',de:'German',el:'Greek',en:'English','en-au':'English (Australia)','en-ca':'English (Canadian)','en-uk':'English (United Kingdom)',eo:'Esperanto',es:'Spanish',et:'Estonian',eu:'Basque',fa:'Persian',fi:'Finnish',fo:'Faroese',fr:'French','fr-ca':'French (Canada)',gl:'Galician',gu:'Gujarati',he:'Hebrew',hi:'Hindi',hr:'Croatian',hu:'Hungarian',is:'Icelandic',it:'Italian',ja:'Japanese',km:'Khmer',ko:'Korean',lt:'Lithuanian',lv:'Latvian',mn:'Mongolian',ms:'Malay',nb:'Norwegian Bokmal',nl:'Dutch',no:'Norwegian',pl:'Polish',pt:'Portuguese (Portugal)','pt-br':'Portuguese (Brazil)',ro:'Romanian',ru:'Russian',sk:'Slovak',sl:'Slovenian',sr:'Serbian (Cyrillic)','sr-latn':'Serbian (Latin)',sv:'Swedish',th:'Thai',tr:'Turkish',uk:'Ukrainian',vi:'Vietnamese',zh:'Chinese Traditional','zh-cn':'Chinese Simplified'},GetActiveLanguage:function(){if (FCKConfig.AutoDetectLanguage){var A;if (navigator.userLanguage) A=navigator.userLanguage.toLowerCase();else if (navigator.language) A=navigator.language.toLowerCase();else{return FCKConfig.DefaultLanguage;};if (A.length>=5){A=A.substr(0,5);if (this.AvailableLanguages[A]) return A;};if (A.length>=2){A=A.substr(0,2);if (this.AvailableLanguages[A]) return A;}};return this.DefaultLanguage;},TranslateElements:function(A,B,C,D){var e=A.getElementsByTagName(B);var E,s;for (var i=0;i':'gt','ˆ':'circ','Ëœ':'tilde',' ':'ensp',' ':'emsp',' ':'thinsp','‌':'zwnj','â€':'zwj','‎':'lrm','â€':'rlm','–':'ndash','—':'mdash','‘':'lsquo','’':'rsquo','‚':'sbquo','“':'ldquo','â€':'rdquo','„':'bdquo','†':'dagger','‡':'Dagger','‰':'permil','‹':'lsaquo','›':'rsaquo','€':'euro'};for (e in FCKXHtmlEntities.Entities) A+=e;if (FCKConfig.IncludeLatinEntities){B={'À':'Agrave','Ã':'Aacute','Â':'Acirc','Ã':'Atilde','Ä':'Auml','Ã…':'Aring','Æ':'AElig','Ç':'Ccedil','È':'Egrave','É':'Eacute','Ê':'Ecirc','Ë':'Euml','ÃŒ':'Igrave','Ã':'Iacute','ÃŽ':'Icirc','Ã':'Iuml','Ã':'ETH','Ñ':'Ntilde','Ã’':'Ograve','Ó':'Oacute','Ô':'Ocirc','Õ':'Otilde','Ö':'Ouml','Ø':'Oslash','Ù':'Ugrave','Ú':'Uacute','Û':'Ucirc','Ãœ':'Uuml','Ã':'Yacute','Þ':'THORN','ß':'szlig','à':'agrave','á':'aacute','â':'acirc','ã':'atilde','ä':'auml','Ã¥':'aring','æ':'aelig','ç':'ccedil','è':'egrave','é':'eacute','ê':'ecirc','ë':'euml','ì':'igrave','í':'iacute','î':'icirc','ï':'iuml','ð':'eth','ñ':'ntilde','ò':'ograve','ó':'oacute','ô':'ocirc','õ':'otilde','ö':'ouml','ø':'oslash','ù':'ugrave','ú':'uacute','û':'ucirc','ü':'uuml','ý':'yacute','þ':'thorn','ÿ':'yuml','Å’':'OElig','Å“':'oelig','Å ':'Scaron','Å¡':'scaron','Ÿ':'Yuml'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;};if (FCKConfig.IncludeGreekEntities){B={'Α':'Alpha','Î’':'Beta','Γ':'Gamma','Δ':'Delta','Ε':'Epsilon','Ζ':'Zeta','Η':'Eta','Θ':'Theta','Ι':'Iota','Κ':'Kappa','Λ':'Lambda','Îœ':'Mu','Î':'Nu','Ξ':'Xi','Ο':'Omicron','Π':'Pi','Ρ':'Rho','Σ':'Sigma','Τ':'Tau','Î¥':'Upsilon','Φ':'Phi','Χ':'Chi','Ψ':'Psi','Ω':'Omega','α':'alpha','β':'beta','γ':'gamma','δ':'delta','ε':'epsilon','ζ':'zeta','η':'eta','θ':'theta','ι':'iota','κ':'kappa','λ':'lambda','μ':'mu','ν':'nu','ξ':'xi','ο':'omicron','Ï€':'pi','Ï':'rho','Ï‚':'sigmaf','σ':'sigma','Ï„':'tau','Ï…':'upsilon','φ':'phi','χ':'chi','ψ':'psi','ω':'omega','\u03d1':'thetasym','\u03d2':'upsih','\u03d6':'piv'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;}}else{FCKXHtmlEntities.Entities={'>':'gt'};A='>';A+=' ';};var C='['+A+']';if (FCKConfig.ProcessNumericEntities) C='[^ -~]|'+C;var D=FCKConfig.AdditionalNumericEntities;if (D&&D.length>0) C+='|'+FCKConfig.AdditionalNumericEntities;FCKXHtmlEntities.EntitiesRegex=new RegExp(C,'g');}; +var FCKXHtml={};FCKXHtml.CurrentJobNum=0;FCKXHtml.GetXHTML=function(A,B,C){FCKDomTools.CheckAndRemovePaddingNode(FCKTools.GetElementDocument(A),FCKConfig.EnterMode);FCKXHtmlEntities.Initialize();this._NbspEntity=(FCKConfig.ProcessHTMLEntities?'nbsp':'#160');var D=FCK.IsDirty();FCKXHtml.SpecialBlocks=[];this.XML=FCKTools.CreateXmlObject('DOMDocument');this.MainNode=this.XML.appendChild(this.XML.createElement('xhtml'));FCKXHtml.CurrentJobNum++;if (B) this._AppendNode(this.MainNode,A);else this._AppendChildNodes(this.MainNode,A,false);if (FCKBrowserInfo.IsIE) FCKXHtml._RemoveXHtmlJobProperties(A);var E=this._GetMainXmlString();this.XML=null;if (FCKBrowserInfo.IsSafari) E=E.replace(/^/,'');E=E.substr(7,E.length-15).Trim();if (FCKConfig.DocType.length>0&&FCKRegexLib.HtmlDocType.test(FCKConfig.DocType)) E=E.replace(FCKRegexLib.SpaceNoClose,'>');else E=E.replace(FCKRegexLib.SpaceNoClose,' />');if (FCKConfig.ForceSimpleAmpersand) E=E.replace(FCKRegexLib.ForceSimpleAmpersand,'&');if (C) E=FCKCodeFormatter.Format(E);for (var i=0;i0;if (C) A.appendChild(this.XML.createTextNode(B.replace(FCKXHtmlEntities.EntitiesRegex,FCKXHtml_GetEntity)));return C;};function FCKXHtml_GetEntity(A){var B=FCKXHtmlEntities.Entities[A]||('#'+A.charCodeAt(0));return '#?-:'+B+';';};FCKXHtml.TagProcessors={a:function(A,B){if (B.innerHTML.Trim().length==0&&!B.name) return false;var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'href',C);if (FCKBrowserInfo.IsIE){if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);};A=FCKXHtml._AppendChildNodes(A,B,false);return A;},area:function(A,B){var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'href',C);if (FCKBrowserInfo.IsIE){if (!A.attributes.getNamedItem('coords')){var D=B.getAttribute('coords',2);if (D&&D!='0,0,0') FCKXHtml._AppendAttribute(A,'coords',D);};if (!A.attributes.getNamedItem('shape')){var E=B.getAttribute('shape',2);if (E&&E.length>0) FCKXHtml._AppendAttribute(A,'shape',E.toLowerCase());}};return A;},body:function(A,B){A=FCKXHtml._AppendChildNodes(A,B,false);A.removeAttribute('spellcheck');return A;},iframe:function(A,B){var C=B.innerHTML;if (FCKBrowserInfo.IsGecko) C=FCKTools.HTMLDecode(C);C=C.replace(/\s_fcksavedurl="[^"]*"/g,'');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(C)));return A;},img:function(A,B){if (!A.attributes.getNamedItem('alt')) FCKXHtml._AppendAttribute(A,'alt','');var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'src',C);if (B.style.width) A.removeAttribute('width');if (B.style.height) A.removeAttribute('height');return A;},li:function(A,B,C){if (C.nodeName.IEquals(['ul','ol'])) return FCKXHtml._AppendChildNodes(A,B,true);var D=FCKXHtml.XML.createElement('ul');B._fckxhtmljob=null;do{FCKXHtml._AppendNode(D,B);do{B=FCKDomTools.GetNextSibling(B);} while (B&&B.nodeType==3&&B.nodeValue.Trim().length==0)} while (B&&B.nodeName.toLowerCase()=='li') return D;},ol:function(A,B,C){if (B.innerHTML.Trim().length==0) return false;var D=C.lastChild;if (D&&D.nodeType==3) D=D.previousSibling;if (D&&D.nodeName.toUpperCase()=='LI'){B._fckxhtmljob=null;FCKXHtml._AppendNode(D,B);return false;};A=FCKXHtml._AppendChildNodes(A,B);return A;},pre:function (A,B){var C=B.firstChild;if (C&&C.nodeType==3) A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem('\r\n')));FCKXHtml._AppendChildNodes(A,B,true);return A;},script:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/javascript');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(B.text)));return A;},span:function(A,B){if (B.innerHTML.length==0) return false;A=FCKXHtml._AppendChildNodes(A,B,false);return A;},style:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/css');var C=B.innerHTML;if (FCKBrowserInfo.IsIE) C=C.replace(/^(\r\n|\n|\r)/,'');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(C)));return A;},title:function(A,B){A.appendChild(FCKXHtml.XML.createTextNode(FCK.EditorDocument.title));return A;}};FCKXHtml.TagProcessors.ul=FCKXHtml.TagProcessors.ol; +FCKXHtml._GetMainXmlString=function(){return this.MainNode.xml;};FCKXHtml._AppendAttributes=function(A,B,C,D){var E=B.attributes,bHasStyle;for (var n=0;n0){var I=FCKTools.ProtectFormStyles(B);var J=B.style.cssText.replace(FCKRegexLib.StyleProperties,FCKTools.ToLowerCase);FCKTools.RestoreFormStyles(B,I);this._AppendAttribute(C,'style',J);}};FCKXHtml._RemoveXHtmlJobProperties=function (A){if (!A||!A.nodeType||A.nodeType!=1) return;if (typeof A._fckxhtmljob!=='undefined') A.removeAttribute('_fckxhtmljob');if (A.hasChildNodes()){var B=A.childNodes;for (var i=B.length-1;i>=0;i--) FCKXHtml._RemoveXHtmlJobProperties(B.item(i));}};FCKXHtml.TagProcessors['div']=function(A,B){if (B.align.length>0) FCKXHtml._AppendAttribute(A,'align',B.align);A=FCKXHtml._AppendChildNodes(A,B,true);return A;};FCKXHtml.TagProcessors['font']=function(A,B){if (A.attributes.length==0) A=FCKXHtml.XML.createDocumentFragment();A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['form']=function(A,B){if (B.acceptCharset&&B.acceptCharset.length>0&&B.acceptCharset!='UNKNOWN') FCKXHtml._AppendAttribute(A,'accept-charset',B.acceptCharset);var C=B.attributes['name'];if (C&&C.value.length>0) FCKXHtml._AppendAttribute(A,'name',C.value);A=FCKXHtml._AppendChildNodes(A,B,true);return A;};FCKXHtml.TagProcessors['input']=function(A,B){if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);if (B.value&&!A.attributes.getNamedItem('value')) FCKXHtml._AppendAttribute(A,'value',B.value);if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text');return A;};FCKXHtml.TagProcessors['label']=function(A,B){if (B.htmlFor.length>0) FCKXHtml._AppendAttribute(A,'for',B.htmlFor);A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['map']=function(A,B){if (!A.attributes.getNamedItem('name')){var C=B.name;if (C) FCKXHtml._AppendAttribute(A,'name',C);};A=FCKXHtml._AppendChildNodes(A,B,true);return A;};FCKXHtml.TagProcessors['meta']=function(A,B){var C=A.attributes.getNamedItem('http-equiv');if (C==null||C.value.length==0){var D=B.outerHTML.match(FCKRegexLib.MetaHttpEquiv);if (D){D=D[1];FCKXHtml._AppendAttribute(A,'http-equiv',D);}};return A;};FCKXHtml.TagProcessors['option']=function(A,B){if (B.selected&&!A.attributes.getNamedItem('selected')) FCKXHtml._AppendAttribute(A,'selected','selected');A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['textarea']=FCKXHtml.TagProcessors['select']=function(A,B){if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);A=FCKXHtml._AppendChildNodes(A,B);return A;}; +var FCKCodeFormatter={};FCKCodeFormatter.Init=function(){var A=this.Regex={};A.BlocksOpener=/\<(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DL|DT|DD|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.BlocksCloser=/\<\/(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DL|DT|DD|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.NewLineTags=/\<(BR|HR)[^\>]*\>/gi;A.MainTags=/\<\/?(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR)[^\>]*\>/gi;A.LineSplitter=/\s*\n+\s*/g;A.IncreaseIndent=/^\<(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL|DL)[ \/\>]/i;A.DecreaseIndent=/^\<\/(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL|DL)[ \>]/i;A.FormatIndentatorRemove=new RegExp('^'+FCKConfig.FormatIndentator);A.ProtectedTags=/(]*>)([\s\S]*?)(<\/PRE>)/gi;};FCKCodeFormatter._ProtectData=function(A,B,C,D){return B+'___FCKpd___'+(FCKCodeFormatter.ProtectedData.push(C)-1)+D;};FCKCodeFormatter.Format=function(A){if (!this.Regex) this.Init();FCKCodeFormatter.ProtectedData=[];var B=A.replace(this.Regex.ProtectedTags,FCKCodeFormatter._ProtectData);B=B.replace(this.Regex.BlocksOpener,'\n$&');B=B.replace(this.Regex.BlocksCloser,'$&\n');B=B.replace(this.Regex.NewLineTags,'$&\n');B=B.replace(this.Regex.MainTags,'\n$&\n');var C='';var D=B.split(this.Regex.LineSplitter);B='';for (var i=0;iB[i]) return 1;};if (A.lengthB.length) return 1;return 0;};FCKUndo._CheckIsBookmarksEqual=function(A,B){if (!(A&&B)) return false;if (FCKBrowserInfo.IsIE){var C=A[1].search(A[0].StartId);var D=B[1].search(B[0].StartId);var E=A[1].search(A[0].EndId);var F=B[1].search(B[0].EndId);return C==D&&E==F;}else{return this._CompareCursors(A.Start,B.Start)==0&&this._CompareCursors(A.End,B.End)==0;}};FCKUndo.SaveUndoStep=function(){if (FCK.EditMode!=0||this.SaveLocked) return;if (this.SavedData.length) this.Changed=true;var A=FCK.EditorDocument.body.innerHTML;var B=this._GetBookmark();this.SavedData=this.SavedData.slice(0,this.CurrentIndex+1);if (this.CurrentIndex>0&&A==this.SavedData[this.CurrentIndex][0]&&this._CheckIsBookmarksEqual(B,this.SavedData[this.CurrentIndex][1])) return;else if (this.CurrentIndex==0&&this.SavedData.length&&A==this.SavedData[0][0]){this.SavedData[0][1]=B;return;};if (this.CurrentIndex+1>=FCKConfig.MaxUndoLevels) this.SavedData.shift();else this.CurrentIndex++;this.SavedData[this.CurrentIndex]=[A,B];FCK.Events.FireEvent("OnSelectionChange");};FCKUndo.CheckUndoState=function(){return (this.Changed||this.CurrentIndex>0);};FCKUndo.CheckRedoState=function(){return (this.CurrentIndex<(this.SavedData.length-1));};FCKUndo.Undo=function(){if (this.CheckUndoState()){if (this.CurrentIndex==(this.SavedData.length-1)){this.SaveUndoStep();};this._ApplyUndoLevel(--this.CurrentIndex);FCK.Events.FireEvent("OnSelectionChange");}};FCKUndo.Redo=function(){if (this.CheckRedoState()){this._ApplyUndoLevel(++this.CurrentIndex);FCK.Events.FireEvent("OnSelectionChange");}};FCKUndo._ApplyUndoLevel=function(A){var B=this.SavedData[A];if (!B) return;if (FCKBrowserInfo.IsIE){if (B[1]&&B[1][1]) FCK.SetInnerHtml(B[1][1]);else FCK.SetInnerHtml(B[0]);}else FCK.EditorDocument.body.innerHTML=B[0];this._SelectBookmark(B[1]);this.TypesCount=0;this.Changed=false;this.Typing=false;}; +var FCKEditingArea=function(A){this.TargetElement=A;this.Mode=0;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKEditingArea_Cleanup);};FCKEditingArea.prototype.Start=function(A,B){var C=this.TargetElement;var D=FCKTools.GetElementDocument(C);while(C.firstChild) C.removeChild(C.firstChild);if (this.Mode==0){if (FCK_IS_CUSTOM_DOMAIN) A=''+A;if (FCKBrowserInfo.IsIE) A=A.replace(/(]*?)\s*\/?>(?!\s*<\/base>)/gi,'$1>');else if (!B){var E=A.match(FCKRegexLib.BeforeBody);var F=A.match(FCKRegexLib.AfterBody);if (E&&F){var G=A.substr(E[1].length,A.length-E[1].length-F[1].length);A=E[1]+' '+F[1];if (FCKBrowserInfo.IsGecko&&(G.length==0||FCKRegexLib.EmptyParagraph.test(G))) G='
    ';this._BodyHTML=G;}else this._BodyHTML=A;};var H=this.IFrame=D.createElement('iframe');var I='';H.frameBorder=0;H.style.width=H.style.height='100%';if (FCK_IS_CUSTOM_DOMAIN&&FCKBrowserInfo.IsIE){window._FCKHtmlToLoad=A.replace(//i,''+I);H.src='javascript:void( (function(){document.open() ;document.domain="'+document.domain+'" ;document.write( window.parent._FCKHtmlToLoad );document.close() ;window.parent._FCKHtmlToLoad = null ;})() )';}else if (!FCKBrowserInfo.IsGecko){H.src='javascript:void(0)';};C.appendChild(H);this.Window=H.contentWindow;if (!FCK_IS_CUSTOM_DOMAIN||!FCKBrowserInfo.IsIE){var J=this.Window.document;J.open();J.write(A.replace(//i,''+I));J.close();};if (FCKBrowserInfo.IsAIR) FCKAdobeAIR.EditingArea_Start(J,A);if (FCKBrowserInfo.IsGecko10&&!B){this.Start(A,true);return;};if (H.readyState&&H.readyState!='completed'){var K=this;setTimeout(function(){try{K.Window.document.documentElement.doScroll("left");}catch(e){setTimeout(arguments.callee,0);return;};K.Window._FCKEditingArea=K;FCKEditingArea_CompleteStart.call(K.Window);},0);}else{this.Window._FCKEditingArea=this;if (FCKBrowserInfo.IsGecko10) this.Window.setTimeout(FCKEditingArea_CompleteStart,500);else FCKEditingArea_CompleteStart.call(this.Window);}}else{var L=this.Textarea=D.createElement('textarea');L.className='SourceField';L.dir='ltr';FCKDomTools.SetElementStyles(L,{width:'100%',height:'100%',border:'none',resize:'none',outline:'none'});C.appendChild(L);L.value=A;FCKTools.RunFunction(this.OnLoad);}};function FCKEditingArea_CompleteStart(){if (!this.document.body){this.setTimeout(FCKEditingArea_CompleteStart,50);return;};var A=this._FCKEditingArea;A.Document=A.Window.document;A.MakeEditable();FCKTools.RunFunction(A.OnLoad);};FCKEditingArea.prototype.MakeEditable=function(){var A=this.Document;if (FCKBrowserInfo.IsIE){A.body.disabled=true;A.body.contentEditable=true;A.body.removeAttribute("disabled");}else{try{A.body.spellcheck=(this.FFSpellChecker!==false);if (this._BodyHTML){A.body.innerHTML=this._BodyHTML;A.body.offsetLeft;this._BodyHTML=null;};A.designMode='on';A.execCommand('enableObjectResizing',false,!FCKConfig.DisableObjectResizing);A.execCommand('enableInlineTableEditing',false,!FCKConfig.DisableFFTableHandles);}catch (e){FCKTools.AddEventListener(this.Window.frameElement,'DOMAttrModified',FCKEditingArea_Document_AttributeNodeModified);}}};function FCKEditingArea_Document_AttributeNodeModified(A){var B=A.currentTarget.contentWindow._FCKEditingArea;if (B._timer) window.clearTimeout(B._timer);B._timer=FCKTools.SetTimeout(FCKEditingArea_MakeEditableByMutation,1000,B);};function FCKEditingArea_MakeEditableByMutation(){delete this._timer;FCKTools.RemoveEventListener(this.Window.frameElement,'DOMAttrModified',FCKEditingArea_Document_AttributeNodeModified);this.MakeEditable();};FCKEditingArea.prototype.Focus=function(){try{if (this.Mode==0){if (FCKBrowserInfo.IsIE) this._FocusIE();else this.Window.focus();}else{var A=FCKTools.GetElementDocument(this.Textarea);if ((!A.hasFocus||A.hasFocus())&&A.activeElement==this.Textarea) return;this.Textarea.focus();}}catch(e) {}};FCKEditingArea.prototype._FocusIE=function(){this.Document.body.setActive();this.Window.focus();var A=this.Document.selection.createRange();var B=A.parentElement();var C=B.nodeName.toLowerCase();if (B.childNodes.length>0||!(FCKListsLib.BlockElements[C]||FCKListsLib.NonEmptyBlockElements[C])){return;};A=new FCKDomRange(this.Window);A.MoveToElementEditStart(B);A.Select();};function FCKEditingArea_Cleanup(){if (this.Document){this.Document.selection.empty();this.Document.body.innerHTML="";};this.TargetElement=null;this.IFrame=null;this.Document=null;this.Textarea=null;if (this.Window){this.Window._FCKEditingArea=null;this.Window=null;}}; +var FCKKeystrokeHandler=function(A){this.Keystrokes={};this.CancelCtrlDefaults=(A!==false);};FCKKeystrokeHandler.prototype.AttachToElement=function(A){FCKTools.AddEventListenerEx(A,'keydown',_FCKKeystrokeHandler_OnKeyDown,this);if (FCKBrowserInfo.IsGecko10||FCKBrowserInfo.IsOpera||(FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsMac)) FCKTools.AddEventListenerEx(A,'keypress',_FCKKeystrokeHandler_OnKeyPress,this);};FCKKeystrokeHandler.prototype.SetKeystrokes=function(){for (var i=0;i40))){B._CancelIt=true;if (A.preventDefault) return A.preventDefault();A.returnValue=false;A.cancelBubble=true;return false;};return true;};function _FCKKeystrokeHandler_OnKeyPress(A,B){if (B._CancelIt){if (A.preventDefault) return A.preventDefault();return false;};return true;}; +FCK.DTD=(function(){var X=FCKTools.Merge;var A,L,J,M,N,O,D,H,P,K,Q,F,G,C,B,E,I;A={isindex:1,fieldset:1};B={input:1,button:1,select:1,textarea:1,label:1};C=X({a:1},B);D=X({iframe:1},C);E={hr:1,ul:1,menu:1,div:1,blockquote:1,noscript:1,table:1,center:1,address:1,dir:1,pre:1,h5:1,dl:1,h4:1,noframes:1,h6:1,ol:1,h1:1,h3:1,h2:1};F={ins:1,del:1,script:1};G=X({b:1,acronym:1,bdo:1,'var':1,'#':1,abbr:1,code:1,br:1,i:1,cite:1,kbd:1,u:1,strike:1,s:1,tt:1,strong:1,q:1,samp:1,em:1,dfn:1,span:1},F);H=X({sub:1,img:1,object:1,sup:1,basefont:1,map:1,applet:1,font:1,big:1,small:1},G);I=X({p:1},H);J=X({iframe:1},H,B);K={img:1,noscript:1,br:1,kbd:1,center:1,button:1,basefont:1,h5:1,h4:1,samp:1,h6:1,ol:1,h1:1,h3:1,h2:1,form:1,font:1,'#':1,select:1,menu:1,ins:1,abbr:1,label:1,code:1,table:1,script:1,cite:1,input:1,iframe:1,strong:1,textarea:1,noframes:1,big:1,small:1,span:1,hr:1,sub:1,bdo:1,'var':1,div:1,object:1,sup:1,strike:1,dir:1,map:1,dl:1,applet:1,del:1,isindex:1,fieldset:1,ul:1,b:1,acronym:1,a:1,blockquote:1,i:1,u:1,s:1,tt:1,address:1,q:1,pre:1,p:1,em:1,dfn:1};L=X({a:1},J);M={tr:1};N={'#':1};O=X({param:1},K);P=X({form:1},A,D,E,I);Q={li:1};return {col:{},tr:{td:1,th:1},img:{},colgroup:{col:1},noscript:P,td:P,br:{},th:P,center:P,kbd:L,button:X(I,E),basefont:{},h5:L,h4:L,samp:L,h6:L,ol:Q,h1:L,h3:L,option:N,h2:L,form:X(A,D,E,I),select:{optgroup:1,option:1},font:J,ins:P,menu:Q,abbr:L,label:L,table:{thead:1,col:1,tbody:1,tr:1,colgroup:1,caption:1,tfoot:1},code:L,script:N,tfoot:M,cite:L,li:P,input:{},iframe:P,strong:J,textarea:N,noframes:P,big:J,small:J,span:J,hr:{},dt:L,sub:J,optgroup:{option:1},param:{},bdo:L,'var':J,div:P,object:O,sup:J,dd:P,strike:J,area:{},dir:Q,map:X({area:1,form:1,p:1},A,F,E),applet:O,dl:{dt:1,dd:1},del:P,isindex:{},fieldset:X({legend:1},K),thead:M,ul:Q,acronym:L,b:J,a:J,blockquote:P,caption:L,i:J,u:J,tbody:M,s:L,address:X(D,I),tt:J,legend:L,q:L,pre:X(G,C),p:L,em:J,dfn:L};})(); +var FCKStyle=function(A){this.Element=(A.Element||'span').toLowerCase();this._StyleDesc=A;};FCKStyle.prototype={GetType:function(){var A=this.GetType_$;if (A!=undefined) return A;var B=this.Element;if (B=='#'||FCKListsLib.StyleBlockElements[B]) A=0;else if (FCKListsLib.StyleObjectElements[B]) A=2;else A=1;return (this.GetType_$=A);},ApplyToSelection:function(A){var B=new FCKDomRange(A);B.MoveToSelection();this.ApplyToRange(B,true);},ApplyToRange:function(A,B,C){switch (this.GetType()){case 0:this.ApplyToRange=this._ApplyBlockStyle;break;case 1:this.ApplyToRange=this._ApplyInlineStyle;break;default:return;};this.ApplyToRange(A,B,C);},ApplyToObject:function(A){if (!A) return;this.BuildElement(null,A);},RemoveFromSelection:function(A){var B=new FCKDomRange(A);B.MoveToSelection();this.RemoveFromRange(B,true);},RemoveFromRange:function(A,B,C){var D;var E=this._GetAttribsForComparison();var F=this._GetOverridesForComparison();if (A.CheckIsCollapsed()){var D=A.CreateBookmark(true);var H=A.GetBookmarkNode(D,true);var I=new FCKElementPath(H.parentNode);var J=[];var K=!FCKDomTools.GetNextSibling(H);var L=K||!FCKDomTools.GetPreviousSibling(H);var M;var N=-1;for (var i=0;i=0;i--){var E=D[i];for (var F in B){if (FCKDomTools.HasAttribute(E,F)){switch (F){case 'style':this._RemoveStylesFromElement(E);break;case 'class':if (FCKDomTools.GetAttributeValue(E,F)!=this.GetFinalAttributeValue(F)) continue;default:FCKDomTools.RemoveAttribute(E,F);}}};this._RemoveOverrides(E,C[this.Element]);this._RemoveNoAttribElement(E);};for (var G in C){if (G!=this.Element){D=A.getElementsByTagName(G);for (var i=D.length-1;i>=0;i--){var E=D[i];this._RemoveOverrides(E,C[G]);this._RemoveNoAttribElement(E);}}}},_RemoveStylesFromElement:function(A){var B=A.style.cssText;var C=this.GetFinalStyleValue();if (B.length>0&&C.length==0) return;C='(^|;)\\s*('+C.replace(/\s*([^ ]+):.*?(;|$)/g,'$1|').replace(/\|$/,'')+'):[^;]+';var D=new RegExp(C,'gi');B=B.replace(D,'').Trim();if (B.length==0||B==';') FCKDomTools.RemoveAttribute(A,'style');else A.style.cssText=B.replace(D,'');},_RemoveOverrides:function(A,B){var C=B&&B.Attributes;if (C){for (var i=0;i0) C.style.cssText=this.GetFinalStyleValue();return C;},_CompareAttributeValues:function(A,B,C){if (A=='style'&&B&&C){B=B.replace(/;$/,'').toLowerCase();C=C.replace(/;$/,'').toLowerCase();};return (B==C||((B===null||B==='')&&(C===null||C==='')))},GetFinalAttributeValue:function(A){var B=this._StyleDesc.Attributes;var B=B?B[A]:null;if (!B&&A=='style') return this.GetFinalStyleValue();if (B&&this._Variables) B=B.Replace(FCKRegexLib.StyleVariableAttName,this._GetVariableReplace,this);return B;},GetFinalStyleValue:function(){var A=this._GetStyleText();if (A.length>0&&this._Variables){A=A.Replace(FCKRegexLib.StyleVariableAttName,this._GetVariableReplace,this);A=FCKTools.NormalizeCssText(A);};return A;},_GetVariableReplace:function(){return this._Variables[arguments[2]]||arguments[0];},SetVariable:function(A,B){var C=this._Variables;if (!C) C=this._Variables={};this._Variables[A]=B;},_FromPre:function(A,B,C){var D=B.innerHTML;D=D.replace(/(\r\n|\r)/g,'\n');D=D.replace(/^[ \t]*\n/,'');D=D.replace(/\n$/,'');D=D.replace(/^[ \t]+|[ \t]+$/g,function(match,offset,s){if (match.length==1) return ' ';else if (offset==0) return new Array(match.length).join(' ')+' ';else return ' '+new Array(match.length).join(' ');});var E=new FCKHtmlIterator(D);var F=[];E.Each(function(isTag,value){if (!isTag){value=value.replace(/\n/g,'
    ');value=value.replace(/[ \t]{2,}/g,function (match){return new Array(match.length).join(' ')+' ';});};F.push(value);});C.innerHTML=F.join('');return C;},_ToPre:function(A,B,C){var D=B.innerHTML.Trim();D=D.replace(/[ \t\r\n]*(]*>)[ \t\r\n]*/gi,'
    ');var E=new FCKHtmlIterator(D);var F=[];E.Each(function(isTag,value){if (!isTag) value=value.replace(/([ \t\n\r]+| )/g,' ');else if (isTag&&value=='
    ') value='\n';F.push(value);});if (FCKBrowserInfo.IsIE){var G=A.createElement('div');G.appendChild(C);C.outerHTML='
    \n'+F.join('')+'
    ';C=G.removeChild(G.firstChild);}else C.innerHTML=F.join('');return C;},_CheckAndMergePre:function(A,B){if (A!=FCKDomTools.GetPreviousSourceElement(B,true)) return;var C=A.innerHTML.replace(/\n$/,'')+'\n\n'+B.innerHTML.replace(/^\n/,'');if (FCKBrowserInfo.IsIE) B.outerHTML='
    '+C+'
    ';else B.innerHTML=C;FCKDomTools.RemoveNode(A);},_CheckAndSplitPre:function(A){var B;var C=A.firstChild;C=C&&C.nextSibling;while (C){var D=C.nextSibling;if (D&&D.nextSibling&&C.nodeName.IEquals('br')&&D.nodeName.IEquals('br')){FCKDomTools.RemoveNode(C);C=D.nextSibling;FCKDomTools.RemoveNode(D);B=FCKDomTools.InsertAfterNode(B||A,FCKDomTools.CloneElement(A));continue;};if (B){C=C.previousSibling;FCKDomTools.MoveNode(C.nextSibling,B);};C=C.nextSibling;}},_ApplyBlockStyle:function(A,B,C){var D;if (B) D=A.CreateBookmark();var E=new FCKDomRangeIterator(A);E.EnforceRealBlocks=true;var F;var G=A.Window.document;var H;while((F=E.GetNextParagraph())){var I=this.BuildElement(G);var J=I.nodeName.IEquals('pre');var K=F.nodeName.IEquals('pre');var L=J&&!K;var M=!J&&K;if (L) I=this._ToPre(G,F,I);else if (M) I=this._FromPre(G,F,I);else FCKDomTools.MoveChildren(F,I);F.parentNode.insertBefore(I,F);FCKDomTools.RemoveNode(F);if (J){if (H) this._CheckAndMergePre(H,I);H=I;}else if (M) this._CheckAndSplitPre(I);};if (B) A.SelectBookmark(D);if (C) A.MoveToBookmark(D);},_ApplyInlineStyle:function(A,B,C){var D=A.Window.document;if (A.CheckIsCollapsed()){var E=this.BuildElement(D);A.InsertNode(E);A.MoveToPosition(E,2);A.Select();return;};var F=this.Element;var G=FCK.DTD[F]||FCK.DTD.span;var H=this._GetAttribsForComparison();var I;A.Expand('inline_elements');var J=A.CreateBookmark(true);var K=A.GetBookmarkNode(J,true);var L=A.GetBookmarkNode(J,false);A.Release(true);var M=FCKDomTools.GetNextSourceNode(K,true);while (M){var N=false;var O=M.nodeType;var P=O==1?M.nodeName.toLowerCase():null;if (!P||G[P]){if ((FCK.DTD[M.parentNode.nodeName.toLowerCase()]||FCK.DTD.span)[F]||!FCK.DTD[F]){if (!A.CheckHasRange()) A.SetStart(M,3);if (O!=1||M.childNodes.length==0){var Q=M;var R=Q.parentNode;while (Q==R.lastChild&&G[R.nodeName.toLowerCase()]){Q=R;};A.SetEnd(Q,4);if (Q==Q.parentNode.lastChild&&!G[Q.parentNode.nodeName.toLowerCase()]) N=true;}else{A.SetEnd(M,3);}}else N=true;}else N=true;M=FCKDomTools.GetNextSourceNode(M);if (M==L){M=null;N=true;};if (N&&A.CheckHasRange()&&!A.CheckIsCollapsed()){I=this.BuildElement(D);A.ExtractContents().AppendTo(I);if (I.innerHTML.RTrim().length>0){A.InsertNode(I);this.RemoveFromElement(I);this._MergeSiblings(I,this._GetAttribsForComparison());if (!FCKBrowserInfo.IsIE) I.normalize();};A.Release(true);}};this._FixBookmarkStart(K);if (B) A.SelectBookmark(J);if (C) A.MoveToBookmark(J);},_FixBookmarkStart:function(A){var B;while ((B=A.nextSibling)){if (B.nodeType==1&&FCKListsLib.InlineNonEmptyElements[B.nodeName.toLowerCase()]){if (!B.firstChild) FCKDomTools.RemoveNode(B);else FCKDomTools.MoveNode(A,B,true);continue;};if (B.nodeType==3&&B.length==0){FCKDomTools.RemoveNode(B);continue;};break;}},_MergeSiblings:function(A,B){if (!A||A.nodeType!=1||!FCKListsLib.InlineNonEmptyElements[A.nodeName.toLowerCase()]) return;this._MergeNextSibling(A,B);this._MergePreviousSibling(A,B);},_MergeNextSibling:function(A,B){var C=A.nextSibling;var D=(C&&C.nodeType==1&&C.getAttribute('_fck_bookmark'));if (D) C=C.nextSibling;if (C&&C.nodeType==1&&C.nodeName==A.nodeName){if (!B) B=this._CreateElementAttribsForComparison(A);if (this._CheckAttributesMatch(C,B)){var E=A.lastChild;if (D) FCKDomTools.MoveNode(A.nextSibling,A);FCKDomTools.MoveChildren(C,A);FCKDomTools.RemoveNode(C);if (E) this._MergeNextSibling(E);}}},_MergePreviousSibling:function(A,B){var C=A.previousSibling;var D=(C&&C.nodeType==1&&C.getAttribute('_fck_bookmark'));if (D) C=C.previousSibling;if (C&&C.nodeType==1&&C.nodeName==A.nodeName){if (!B) B=this._CreateElementAttribsForComparison(A);if (this._CheckAttributesMatch(C,B)){var E=A.firstChild;if (D) FCKDomTools.MoveNode(A.previousSibling,A,true);FCKDomTools.MoveChildren(C,A,true);FCKDomTools.RemoveNode(C);if (E) this._MergePreviousSibling(E);}}},_GetStyleText:function(){var A=this._StyleDesc.Styles;var B=(this._StyleDesc.Attributes?this._StyleDesc.Attributes['style']||'':'');if (B.length>0) B+=';';for (var C in A) B+=C+':'+A[C]+';';if (B.length>0&&!(/#\(/.test(B))){B=FCKTools.NormalizeCssText(B);};return (this._GetStyleText=function() { return B;})();},_GetAttribsForComparison:function(){var A=this._GetAttribsForComparison_$;if (A) return A;A={};var B=this._StyleDesc.Attributes;if (B){for (var C in B){A[C.toLowerCase()]=B[C].toLowerCase();}};if (this._GetStyleText().length>0){A['style']=this._GetStyleText().toLowerCase();};FCKTools.AppendLengthProperty(A,'_length');return (this._GetAttribsForComparison_$=A);},_GetOverridesForComparison:function(){var A=this._GetOverridesForComparison_$;if (A) return A;A={};var B=this._StyleDesc.Overrides;if (B){if (!FCKTools.IsArray(B)) B=[B];for (var i=0;i0) return true;};B=B.nextSibling;};return false;}}; +var FCKElementPath=function(A){var B=null;var C=null;var D=[];var e=A;while (e){if (e.nodeType==1){if (!this.LastElement) this.LastElement=e;var E=e.nodeName.toLowerCase();if (FCKBrowserInfo.IsIE&&e.scopeName!='HTML') E=e.scopeName.toLowerCase()+':'+E;if (!C){if (!B&&FCKListsLib.PathBlockElements[E]!=null) B=e;if (FCKListsLib.PathBlockLimitElements[E]!=null){if (!B&&E=='div'&&!FCKElementPath._CheckHasBlock(e)) B=e;else C=e;}};D.push(e);if (E=='body') break;};e=e.parentNode;};this.Block=B;this.BlockLimit=C;this.Elements=D;};FCKElementPath._CheckHasBlock=function(A){var B=A.childNodes;for (var i=0,count=B.length;i0){if (D.nodeType==3){var G=D.nodeValue.substr(0,E).Trim();if (G.length!=0) return A.IsStartOfBlock=false;}else F=D.childNodes[E-1];};if (!F) F=FCKDomTools.GetPreviousSourceNode(D,true,null,C);while (F){switch (F.nodeType){case 1:if (!FCKListsLib.InlineChildReqElements[F.nodeName.toLowerCase()]) return A.IsStartOfBlock=false;break;case 3:if (F.nodeValue.Trim().length>0) return A.IsStartOfBlock=false;};F=FCKDomTools.GetPreviousSourceNode(F,false,null,C);};return A.IsStartOfBlock=true;},CheckEndOfBlock:function(A){var B=this._Cache.IsEndOfBlock;if (B!=undefined) return B;var C=this.EndBlock||this.EndBlockLimit;var D=this._Range.endContainer;var E=this._Range.endOffset;var F;if (D.nodeType==3){var G=D.nodeValue;if (E0) return this._Cache.IsEndOfBlock=false;};F=FCKDomTools.GetNextSourceNode(F,false,null,C);};if (A) this.Select();return this._Cache.IsEndOfBlock=true;},CreateBookmark:function(A){var B={StartId:(new Date()).valueOf()+Math.floor(Math.random()*1000)+'S',EndId:(new Date()).valueOf()+Math.floor(Math.random()*1000)+'E'};var C=this.Window.document;var D;var E;var F;if (!this.CheckIsCollapsed()){E=C.createElement('span');E.style.display='none';E.id=B.EndId;E.setAttribute('_fck_bookmark',true);E.innerHTML=' ';F=this.Clone();F.Collapse(false);F.InsertNode(E);};D=C.createElement('span');D.style.display='none';D.id=B.StartId;D.setAttribute('_fck_bookmark',true);D.innerHTML=' ';F=this.Clone();F.Collapse(true);F.InsertNode(D);if (A){B.StartNode=D;B.EndNode=E;};if (E){this.SetStart(D,4);this.SetEnd(E,3);}else this.MoveToPosition(D,4);return B;},GetBookmarkNode:function(A,B){var C=this.Window.document;if (B) return A.StartNode||C.getElementById(A.StartId);else return A.EndNode||C.getElementById(A.EndId);},MoveToBookmark:function(A,B){var C=this.GetBookmarkNode(A,true);var D=this.GetBookmarkNode(A,false);this.SetStart(C,3);if (!B) FCKDomTools.RemoveNode(C);if (D){this.SetEnd(D,3);if (!B) FCKDomTools.RemoveNode(D);}else this.Collapse(true);this._UpdateElementInfo();},CreateBookmark2:function(){if (!this._Range) return { "Start":0,"End":0 };var A={"Start":[this._Range.startOffset],"End":[this._Range.endOffset]};var B=this._Range.startContainer.previousSibling;var C=this._Range.endContainer.previousSibling;var D=this._Range.startContainer;var E=this._Range.endContainer;while (B&&B.nodeType==3&&D.nodeType==3){A.Start[0]+=B.length;D=B;B=B.previousSibling;}while (C&&C.nodeType==3&&E.nodeType==3){A.End[0]+=C.length;E=C;C=C.previousSibling;};if (D.nodeType==1&&D.childNodes[A.Start[0]]&&D.childNodes[A.Start[0]].nodeType==3){var F=D.childNodes[A.Start[0]];var G=0;while (F.previousSibling&&F.previousSibling.nodeType==3){F=F.previousSibling;G+=F.length;};D=F;A.Start[0]=G;};if (E.nodeType==1&&E.childNodes[A.End[0]]&&E.childNodes[A.End[0]].nodeType==3){var F=E.childNodes[A.End[0]];var G=0;while (F.previousSibling&&F.previousSibling.nodeType==3){F=F.previousSibling;G+=F.length;};E=F;A.End[0]=G;};A.Start=FCKDomTools.GetNodeAddress(D,true).concat(A.Start);A.End=FCKDomTools.GetNodeAddress(E,true).concat(A.End);return A;},MoveToBookmark2:function(A){var B=FCKDomTools.GetNodeFromAddress(this.Window.document,A.Start.slice(0,-1),true);var C=FCKDomTools.GetNodeFromAddress(this.Window.document,A.End.slice(0,-1),true);this.Release(true);this._Range=new FCKW3CRange(this.Window.document);var D=A.Start[A.Start.length-1];var E=A.End[A.End.length-1];while (B.nodeType==3&&D>B.length){if (!B.nextSibling||B.nextSibling.nodeType!=3) break;D-=B.length;B=B.nextSibling;}while (C.nodeType==3&&E>C.length){if (!C.nextSibling||C.nextSibling.nodeType!=3) break;E-=C.length;C=C.nextSibling;};this._Range.setStart(B,D);this._Range.setEnd(C,E);this._UpdateElementInfo();},MoveToPosition:function(A,B){this.SetStart(A,B);this.Collapse(true);},SetStart:function(A,B,C){var D=this._Range;if (!D) D=this._Range=this.CreateRange();switch(B){case 1:D.setStart(A,0);break;case 2:D.setStart(A,A.childNodes.length);break;case 3:D.setStartBefore(A);break;case 4:D.setStartAfter(A);};if (!C) this._UpdateElementInfo();},SetEnd:function(A,B,C){var D=this._Range;if (!D) D=this._Range=this.CreateRange();switch(B){case 1:D.setEnd(A,0);break;case 2:D.setEnd(A,A.childNodes.length);break;case 3:D.setEndBefore(A);break;case 4:D.setEndAfter(A);};if (!C) this._UpdateElementInfo();},Expand:function(A){var B,oSibling;switch (A){case 'inline_elements':if (this._Range.startOffset==0){B=this._Range.startContainer;if (B.nodeType!=1) B=B.previousSibling?null:B.parentNode;if (B){while (FCKListsLib.InlineNonEmptyElements[B.nodeName.toLowerCase()]){this._Range.setStartBefore(B);if (B!=B.parentNode.firstChild) break;B=B.parentNode;}}};B=this._Range.endContainer;var C=this._Range.endOffset;if ((B.nodeType==3&&C>=B.nodeValue.length)||(B.nodeType==1&&C>=B.childNodes.length)||(B.nodeType!=1&&B.nodeType!=3)){if (B.nodeType!=1) B=B.nextSibling?null:B.parentNode;if (B){while (FCKListsLib.InlineNonEmptyElements[B.nodeName.toLowerCase()]){this._Range.setEndAfter(B);if (B!=B.parentNode.lastChild) break;B=B.parentNode;}}};break;case 'block_contents':case 'list_contents':var D=FCKListsLib.BlockBoundaries;if (A=='list_contents'||FCKConfig.EnterMode=='br') D=FCKListsLib.ListBoundaries;if (this.StartBlock&&FCKConfig.EnterMode!='br'&&A=='block_contents') this.SetStart(this.StartBlock,1);else{B=this._Range.startContainer;if (B.nodeType==1){var E=B.childNodes[this._Range.startOffset];if (E) B=FCKDomTools.GetPreviousSourceNode(E,true);else B=B.lastChild||B;}while (B&&(B.nodeType!=1||(B!=this.StartBlockLimit&&!D[B.nodeName.toLowerCase()]))){this._Range.setStartBefore(B);B=B.previousSibling||B.parentNode;}};if (this.EndBlock&&FCKConfig.EnterMode!='br'&&A=='block_contents'&&this.EndBlock.nodeName.toLowerCase()!='li') this.SetEnd(this.EndBlock,2);else{B=this._Range.endContainer;if (B.nodeType==1) B=B.childNodes[this._Range.endOffset]||B.lastChild;while (B&&(B.nodeType!=1||(B!=this.StartBlockLimit&&!D[B.nodeName.toLowerCase()]))){this._Range.setEndAfter(B);B=B.nextSibling||B.parentNode;};if (B&&B.nodeName.toLowerCase()=='br') this._Range.setEndAfter(B);};this._UpdateElementInfo();}},SplitBlock:function(A){var B=A||FCKConfig.EnterMode;if (!this._Range) this.MoveToSelection();if (this.StartBlockLimit==this.EndBlockLimit){var C=this.StartBlock;var D=this.EndBlock;var E=null;if (B!='br'){if (!C){C=this.FixBlock(true,B);D=this.EndBlock;};if (!D) D=this.FixBlock(false,B);};var F=(C!=null&&this.CheckStartOfBlock());var G=(D!=null&&this.CheckEndOfBlock());if (!this.CheckIsEmpty()) this.DeleteContents();if (C&&D&&C==D){if (G){E=new FCKElementPath(this.StartContainer);this.MoveToPosition(D,4);D=null;}else if (F){E=new FCKElementPath(this.StartContainer);this.MoveToPosition(C,3);C=null;}else{this.SetEnd(C,2);var H=this.ExtractContents();D=C.cloneNode(false);D.removeAttribute('id',false);H.AppendTo(D);FCKDomTools.InsertAfterNode(C,D);this.MoveToPosition(C,4);if (FCKBrowserInfo.IsGecko&&!C.nodeName.IEquals(['ul','ol'])) FCKTools.AppendBogusBr(C);}};return {PreviousBlock:C,NextBlock:D,WasStartOfBlock:F,WasEndOfBlock:G,ElementPath:E};};return null;},FixBlock:function(A,B){var C=this.CreateBookmark();this.Collapse(A);this.Expand('block_contents');var D=this.Window.document.createElement(B);this.ExtractContents().AppendTo(D);FCKDomTools.TrimNode(D);if (FCKDomTools.CheckIsEmptyElement(D,function(element) { return element.getAttribute('_fck_bookmark')!='true';})&&FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(D);this.InsertNode(D);this.MoveToBookmark(C);return D;},Release:function(A){if (!A) this.Window=null;this.StartNode=null;this.StartContainer=null;this.StartBlock=null;this.StartBlockLimit=null;this.EndNode=null;this.EndContainer=null;this.EndBlock=null;this.EndBlockLimit=null;this._Range=null;this._Cache=null;},CheckHasRange:function(){return!!this._Range;},GetTouchedStartNode:function(){var A=this._Range;var B=A.startContainer;if (A.collapsed||B.nodeType!=1) return B;return B.childNodes[A.startOffset]||B;},GetTouchedEndNode:function(){var A=this._Range;var B=A.endContainer;if (A.collapsed||B.nodeType!=1) return B;return B.childNodes[A.endOffset-1]||B;}}; +FCKDomRange.prototype.MoveToSelection=function(){this.Release(true);this._Range=new FCKW3CRange(this.Window.document);var A=this.Window.document.selection;if (A.type!='Control'){var B=this._GetSelectionMarkerTag(true);var C=this._GetSelectionMarkerTag(false);if (!B&&!C){this._Range.setStart(this.Window.document.body,0);this._UpdateElementInfo();return;};this._Range.setStart(B.parentNode,FCKDomTools.GetIndexOf(B));B.parentNode.removeChild(B);this._Range.setEnd(C.parentNode,FCKDomTools.GetIndexOf(C));C.parentNode.removeChild(C);this._UpdateElementInfo();}else{var D=A.createRange().item(0);if (D){this._Range.setStartBefore(D);this._Range.setEndAfter(D);this._UpdateElementInfo();}}};FCKDomRange.prototype.Select=function(A){if (this._Range) this.SelectBookmark(this.CreateBookmark(true),A);};FCKDomRange.prototype.SelectBookmark=function(A,B){var C=this.CheckIsCollapsed();var D;var E;var F=this.GetBookmarkNode(A,true);if (!F) return;var G;if (!C) G=this.GetBookmarkNode(A,false);var H=this.Window.document.body.createTextRange();H.moveToElementText(F);H.moveStart('character',1);if (G){var I=this.Window.document.body.createTextRange();I.moveToElementText(G);H.setEndPoint('EndToEnd',I);H.moveEnd('character',-1);}else{D=B||!F.previousSibling||F.previousSibling.nodeName.toLowerCase()=='br';E=this.Window.document.createElement('span');E.innerHTML='';F.parentNode.insertBefore(E,F);if (D){F.parentNode.insertBefore(this.Window.document.createTextNode('\ufeff'),F);}};if (!this._Range) this._Range=this.CreateRange();this._Range.setStartBefore(F);F.parentNode.removeChild(F);if (C){if (D){H.moveStart('character',-1);H.select();this.Window.document.selection.clear();}else H.select();FCKDomTools.RemoveNode(E);}else{this._Range.setEndBefore(G);G.parentNode.removeChild(G);H.select();}};FCKDomRange.prototype._GetSelectionMarkerTag=function(A){var B=this.Window.document;var C=B.selection;var D;try{D=C.createRange();}catch (e){return null;};if (D.parentElement().document!=B) return null;D.collapse(A===true);var E='fck_dom_range_temp_'+(new Date()).valueOf()+'_'+Math.floor(Math.random()*1000);D.pasteHTML('');return B.getElementById(E);}; +var FCKDomRangeIterator=function(A){this.Range=A;this.ForceBrBreak=false;this.EnforceRealBlocks=false;};FCKDomRangeIterator.CreateFromSelection=function(A){var B=new FCKDomRange(A);B.MoveToSelection();return new FCKDomRangeIterator(B);};FCKDomRangeIterator.prototype={GetNextParagraph:function(){var A;var B;var C;var D;var E;var F=this.ForceBrBreak?FCKListsLib.ListBoundaries:FCKListsLib.BlockBoundaries;if (!this._LastNode){var B=this.Range.Clone();B.Expand(this.ForceBrBreak?'list_contents':'block_contents');this._NextNode=B.GetTouchedStartNode();this._LastNode=B.GetTouchedEndNode();B=null;};var H=this._NextNode;var I=this._LastNode;this._NextNode=null;while (H){var J=false;var K=(H.nodeType!=1);var L=false;if (!K){var M=H.nodeName.toLowerCase();if (F[M]&&(!FCKBrowserInfo.IsIE||H.scopeName=='HTML')){if (M=='br') K=true;else if (!B&&H.childNodes.length==0&&M!='hr'){A=H;C=H==I;break;};if (B){B.SetEnd(H,3,true);if (M!='br') this._NextNode=FCKDomTools.GetNextSourceNode(H,true,null,I)||H;};J=true;}else{if (H.firstChild){if (!B){B=new FCKDomRange(this.Range.Window);B.SetStart(H,3,true);};H=H.firstChild;continue;};K=true;}}else if (H.nodeType==3){if (/^[\r\n\t ]+$/.test(H.nodeValue)) K=false;};if (K&&!B){B=new FCKDomRange(this.Range.Window);B.SetStart(H,3,true);};C=((!J||K)&&H==I);if (B&&!J){while (!H.nextSibling&&!C){var N=H.parentNode;if (F[N.nodeName.toLowerCase()]){J=true;C=C||(N==I);break;};H=N;K=true;C=(H==I);L=true;}};if (K) B.SetEnd(H,4,true);if ((J||C)&&B){B._UpdateElementInfo();if (B.StartNode==B.EndNode&&B.StartNode.parentNode==B.StartBlockLimit&&B.StartNode.getAttribute&&B.StartNode.getAttribute('_fck_bookmark')) B=null;else break;};if (C) break;H=FCKDomTools.GetNextSourceNode(H,L,null,I);};if (!A){if (!B){this._NextNode=null;return null;};A=B.StartBlock;if (!A&&!this.EnforceRealBlocks&&B.StartBlockLimit.nodeName.IEquals('DIV','TH','TD')&&B.CheckStartOfBlock()&&B.CheckEndOfBlock()){A=B.StartBlockLimit;}else if (!A||(this.EnforceRealBlocks&&A.nodeName.toLowerCase()=='li')){A=this.Range.Window.document.createElement(FCKConfig.EnterMode=='p'?'p':'div');B.ExtractContents().AppendTo(A);FCKDomTools.TrimNode(A);B.InsertNode(A);D=true;E=true;}else if (A.nodeName.toLowerCase()!='li'){if (!B.CheckStartOfBlock()||!B.CheckEndOfBlock()){A=A.cloneNode(false);B.ExtractContents().AppendTo(A);FCKDomTools.TrimNode(A);var O=B.SplitBlock();D=!O.WasStartOfBlock;E=!O.WasEndOfBlock;B.InsertNode(A);}}else if (!C){this._NextNode=A==I?null:FCKDomTools.GetNextSourceNode(B.EndNode,true,null,I);return A;}};if (D){var P=A.previousSibling;if (P&&P.nodeType==1){if (P.nodeName.toLowerCase()=='br') P.parentNode.removeChild(P);else if (P.lastChild&&P.lastChild.nodeName.IEquals('br')) P.removeChild(P.lastChild);}};if (E){var Q=A.lastChild;if (Q&&Q.nodeType==1&&Q.nodeName.toLowerCase()=='br') A.removeChild(Q);};if (!this._NextNode) this._NextNode=(C||A==I)?null:FCKDomTools.GetNextSourceNode(A,true,null,I);return A;}}; +var FCKDocumentFragment=function(A){this._Document=A;this.RootNode=A.createElement('div');};FCKDocumentFragment.prototype={AppendTo:function(A){FCKDomTools.MoveChildren(this.RootNode,A);},AppendHtml:function(A){var B=this._Document.createElement('div');B.innerHTML=A;FCKDomTools.MoveChildren(B,this.RootNode);},InsertAfterNode:function(A){var B=this.RootNode;var C;while((C=B.lastChild)) FCKDomTools.InsertAfterNode(A,B.removeChild(C));}}; +var FCKW3CRange=function(A){this._Document=A;this.startContainer=null;this.startOffset=null;this.endContainer=null;this.endOffset=null;this.collapsed=true;};FCKW3CRange.CreateRange=function(A){return new FCKW3CRange(A);};FCKW3CRange.CreateFromRange=function(A,B){var C=FCKW3CRange.CreateRange(A);C.setStart(B.startContainer,B.startOffset);C.setEnd(B.endContainer,B.endOffset);return C;};FCKW3CRange.prototype={_UpdateCollapsed:function(){this.collapsed=(this.startContainer==this.endContainer&&this.startOffset==this.endOffset);},setStart:function(A,B){this.startContainer=A;this.startOffset=B;if (!this.endContainer){this.endContainer=A;this.endOffset=B;};this._UpdateCollapsed();},setEnd:function(A,B){this.endContainer=A;this.endOffset=B;if (!this.startContainer){this.startContainer=A;this.startOffset=B;};this._UpdateCollapsed();},setStartAfter:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setStartBefore:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A));},setEndAfter:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setEndBefore:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A));},collapse:function(A){if (A){this.endContainer=this.startContainer;this.endOffset=this.startOffset;}else{this.startContainer=this.endContainer;this.startOffset=this.endOffset;};this.collapsed=true;},selectNodeContents:function(A){this.setStart(A,0);this.setEnd(A,A.nodeType==3?A.data.length:A.childNodes.length);},insertNode:function(A){var B=this.startContainer;var C=this.startOffset;if (B.nodeType==3){B.splitText(C);if (B==this.endContainer) this.setEnd(B.nextSibling,this.endOffset-this.startOffset);FCKDomTools.InsertAfterNode(B,A);return;}else{B.insertBefore(A,B.childNodes[C]||null);if (B==this.endContainer){this.endOffset++;this.collapsed=false;}}},deleteContents:function(){if (this.collapsed) return;this._ExecContentsAction(0);},extractContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(1,A);return A;},cloneContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(2,A);return A;},_ExecContentsAction:function(A,B){var C=this.startContainer;var D=this.endContainer;var E=this.startOffset;var F=this.endOffset;var G=false;var H=false;if (D.nodeType==3) D=D.splitText(F);else{if (D.childNodes.length>0){if (F>D.childNodes.length-1){D=FCKDomTools.InsertAfterNode(D.lastChild,this._Document.createTextNode(''));H=true;}else D=D.childNodes[F];}};if (C.nodeType==3){C.splitText(E);if (C==D) D=C.nextSibling;}else{if (E==0){C=C.insertBefore(this._Document.createTextNode(''),C.firstChild);G=true;}else if (E>C.childNodes.length-1){C=C.appendChild(this._Document.createTextNode(''));G=true;}else C=C.childNodes[E].previousSibling;};var I=FCKDomTools.GetParents(C);var J=FCKDomTools.GetParents(D);var i,topStart,topEnd;for (i=0;i0&&levelStartNode!=D) levelClone=K.appendChild(levelStartNode.cloneNode(levelStartNode==D));if (!I[k]||levelStartNode.parentNode!=I[k].parentNode){currentNode=levelStartNode.previousSibling;while(currentNode){if (currentNode==I[k]||currentNode==C) break;currentSibling=currentNode.previousSibling;if (A==2) K.insertBefore(currentNode.cloneNode(true),K.firstChild);else{currentNode.parentNode.removeChild(currentNode);if (A==1) K.insertBefore(currentNode,K.firstChild);};currentNode=currentSibling;}};if (K) K=levelClone;};if (A==2){var L=this.startContainer;if (L.nodeType==3){L.data+=L.nextSibling.data;L.parentNode.removeChild(L.nextSibling);};var M=this.endContainer;if (M.nodeType==3&&M.nextSibling){M.data+=M.nextSibling.data;M.parentNode.removeChild(M.nextSibling);}}else{if (topStart&&topEnd&&(C.parentNode!=topStart.parentNode||D.parentNode!=topEnd.parentNode)){var N=FCKDomTools.GetIndexOf(topEnd);if (G&&topEnd.parentNode==C.parentNode) N--;this.setStart(topEnd.parentNode,N);};this.collapse(true);};if(G) C.parentNode.removeChild(C);if(H&&D.parentNode) D.parentNode.removeChild(D);},cloneRange:function(){return FCKW3CRange.CreateFromRange(this._Document,this);}}; +var FCKEnterKey=function(A,B,C,D){this.Window=A;this.EnterMode=B||'p';this.ShiftEnterMode=C||'br';var E=new FCKKeystrokeHandler(false);E._EnterKey=this;E.OnKeystroke=FCKEnterKey_OnKeystroke;E.SetKeystrokes([[13,'Enter'],[SHIFT+13,'ShiftEnter'],[8,'Backspace'],[CTRL+8,'CtrlBackspace'],[46,'Delete']]);this.TabText='';if (D>0||FCKBrowserInfo.IsSafari){while (D--) this.TabText+='\xa0';E.SetKeystrokes([9,'Tab']);};E.AttachToElement(A.document);};function FCKEnterKey_OnKeystroke(A,B){var C=this._EnterKey;try{switch (B){case 'Enter':return C.DoEnter();break;case 'ShiftEnter':return C.DoShiftEnter();break;case 'Backspace':return C.DoBackspace();break;case 'Delete':return C.DoDelete();break;case 'Tab':return C.DoTab();break;case 'CtrlBackspace':return C.DoCtrlBackspace();break;}}catch (e){};return false;};FCKEnterKey.prototype.DoEnter=function(A,B){FCKUndo.SaveUndoStep();this._HasShift=(B===true);var C=FCKSelection.GetParentElement();var D=new FCKElementPath(C);var E=A||this.EnterMode;if (E=='br'||D.Block&&D.Block.tagName.toLowerCase()=='pre') return this._ExecuteEnterBr();else return this._ExecuteEnterBlock(E);};FCKEnterKey.prototype.DoShiftEnter=function(){return this.DoEnter(this.ShiftEnterMode,true);};FCKEnterKey.prototype.DoBackspace=function(){var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (FCKBrowserInfo.IsIE&&this._CheckIsAllContentsIncluded(B,this.Window.document.body)){this._FixIESelectAllBug(B);return true;};var C=B.CheckIsCollapsed();if (!C){if (FCKBrowserInfo.IsIE&&this.Window.document.selection.type.toLowerCase()=="control"){var D=this.Window.document.selection.createRange();for (var i=D.length-1;i>=0;i--){var E=D.item(i);E.parentNode.removeChild(E);};return true;};return false;};if (FCKBrowserInfo.IsIE){var F=FCKDomTools.GetPreviousSourceElement(B.StartNode,true);if (F&&F.nodeName.toLowerCase()=='br'){var G=B.Clone();G.SetStart(F,4);if (G.CheckIsEmpty()){F.parentNode.removeChild(F);return true;}}};var H=B.StartBlock;var I=B.EndBlock;if (B.StartBlockLimit==B.EndBlockLimit&&H&&I){if (!C){var J=B.CheckEndOfBlock();B.DeleteContents();if (H!=I){B.SetStart(I,1);B.SetEnd(I,1);};B.Select();A=(H==I);};if (B.CheckStartOfBlock()){var K=B.StartBlock;var L=FCKDomTools.GetPreviousSourceElement(K,true,['BODY',B.StartBlockLimit.nodeName],['UL','OL']);A=this._ExecuteBackspace(B,L,K);}else if (FCKBrowserInfo.IsGeckoLike){B.Select();}};B.Release();return A;};FCKEnterKey.prototype.DoCtrlBackspace=function(){FCKUndo.SaveUndoStep();var A=new FCKDomRange(this.Window);A.MoveToSelection();if (FCKBrowserInfo.IsIE&&this._CheckIsAllContentsIncluded(A,this.Window.document.body)){this._FixIESelectAllBug(A);return true;};return false;};FCKEnterKey.prototype._ExecuteBackspace=function(A,B,C){var D=false;if (!B&&C&&C.nodeName.IEquals('LI')&&C.parentNode.parentNode.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};if (B&&B.nodeName.IEquals('LI')){var E=FCKDomTools.GetLastChild(B,['UL','OL']);while (E){B=FCKDomTools.GetLastChild(E,'LI');E=FCKDomTools.GetLastChild(B,['UL','OL']);}};if (B&&C){if (C.nodeName.IEquals('LI')&&!B.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};var F=C.parentNode;var G=B.nodeName.toLowerCase();if (FCKListsLib.EmptyElements[G]!=null||G=='table'){FCKDomTools.RemoveNode(B);D=true;}else{FCKDomTools.RemoveNode(C);while (F.innerHTML.Trim().length==0){var H=F.parentNode;H.removeChild(F);F=H;};FCKDomTools.LTrimNode(C);FCKDomTools.RTrimNode(B);A.SetStart(B,2,true);A.Collapse(true);var I=A.CreateBookmark(true);if (!C.tagName.IEquals(['TABLE'])) FCKDomTools.MoveChildren(C,B);A.SelectBookmark(I);D=true;}};return D;};FCKEnterKey.prototype.DoDelete=function(){FCKUndo.SaveUndoStep();var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (FCKBrowserInfo.IsIE&&this._CheckIsAllContentsIncluded(B,this.Window.document.body)){this._FixIESelectAllBug(B);return true;};if (B.CheckIsCollapsed()&&B.CheckEndOfBlock(FCKBrowserInfo.IsGeckoLike)){var C=B.StartBlock;var D=FCKTools.GetElementAscensor(C,'td');var E=FCKDomTools.GetNextSourceElement(C,true,[B.StartBlockLimit.nodeName],['UL','OL','TR'],true);if (D){var F=FCKTools.GetElementAscensor(E,'td');if (F!=D) return true;};A=this._ExecuteBackspace(B,C,E);};B.Release();return A;};FCKEnterKey.prototype.DoTab=function(){var A=new FCKDomRange(this.Window);A.MoveToSelection();var B=A._Range.startContainer;while (B){if (B.nodeType==1){var C=B.tagName.toLowerCase();if (C=="tr"||C=="td"||C=="th"||C=="tbody"||C=="table") return false;else break;};B=B.parentNode;};if (this.TabText){A.DeleteContents();A.InsertNode(this.Window.document.createTextNode(this.TabText));A.Collapse(false);A.Select();};return true;};FCKEnterKey.prototype._ExecuteEnterBlock=function(A,B){var C=B||new FCKDomRange(this.Window);var D=C.SplitBlock(A);if (D){var E=D.PreviousBlock;var F=D.NextBlock;var G=D.WasStartOfBlock;var H=D.WasEndOfBlock;if (F){if (F.parentNode.nodeName.IEquals('li')){FCKDomTools.BreakParent(F,F.parentNode);FCKDomTools.MoveNode(F,F.nextSibling,true);}}else if (E&&E.parentNode.nodeName.IEquals('li')){FCKDomTools.BreakParent(E,E.parentNode);C.MoveToElementEditStart(E.nextSibling);FCKDomTools.MoveNode(E,E.previousSibling);};if (!G&&!H){if (F.nodeName.IEquals('li')&&F.firstChild&&F.firstChild.nodeName.IEquals(['ul','ol'])) F.insertBefore(FCKTools.GetElementDocument(F).createTextNode('\xa0'),F.firstChild);if (F) C.MoveToElementEditStart(F);}else{if (G&&H&&E.tagName.toUpperCase()=='LI'){C.MoveToElementStart(E);this._OutdentWithSelection(E,C);C.Release();return true;};var I;if (E){var J=E.tagName.toUpperCase();if (!this._HasShift&&!(/^H[1-6]$/).test(J)){I=FCKDomTools.CloneElement(E);}}else if (F) I=FCKDomTools.CloneElement(F);if (!I) I=this.Window.document.createElement(A);var K=D.ElementPath;if (K){for (var i=0,len=K.Elements.length;i=0&&(C=B[i--])){if (C.name.length>0){if (C.innerHTML!==''){if (FCKBrowserInfo.IsIE) C.className+=' FCK__AnchorC';}else{var D=FCKDocumentProcessor_CreateFakeImage('FCK__Anchor',C.cloneNode(true));D.setAttribute('_fckanchor','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}}}};var FCKPageBreaksProcessor=FCKDocumentProcessor.AppendNew();FCKPageBreaksProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('DIV');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.style.pageBreakAfter=='always'&&C.childNodes.length==1&&C.childNodes[0].style&&C.childNodes[0].style.display=='none'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',C.cloneNode(true));C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}};var FCKEmbedAndObjectProcessor=(function(){var A=[];var B=function(el){var C=el.cloneNode(true);var D;var E=D=FCKDocumentProcessor_CreateFakeImage('FCK__UnknownObject',C);FCKEmbedAndObjectProcessor.RefreshView(E,el);for (var i=0;i=0;i--) B(G[i]);};var H=function(doc){F('object',doc);F('embed',doc);};return FCKTools.Merge(FCKDocumentProcessor.AppendNew(),{ProcessDocument:function(doc){if (FCKBrowserInfo.IsGecko) FCKTools.RunFunction(H,this,[doc]);else H(doc);},RefreshView:function(placeHolder,original){if (original.getAttribute('width')>0) placeHolder.style.width=FCKTools.ConvertHtmlSizeToStyle(original.getAttribute('width'));if (original.getAttribute('height')>0) placeHolder.style.height=FCKTools.ConvertHtmlSizeToStyle(original.getAttribute('height'));},AddCustomHandler:function(func){A.push(func);}});})();FCK.GetRealElement=function(A){var e=FCKTempBin.Elements[A.getAttribute('_fckrealelement')];if (A.getAttribute('_fckflash')){if (A.style.width.length>0) e.width=FCKTools.ConvertStyleSizeToHtml(A.style.width);if (A.style.height.length>0) e.height=FCKTools.ConvertStyleSizeToHtml(A.style.height);};return e;};if (FCKBrowserInfo.IsIE){FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('HR');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){var D=A.createElement('hr');D.mergeAttributes(C,true);FCKDomTools.InsertAfterNode(C,D);C.parentNode.removeChild(C);}}};FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('INPUT');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.type=='hidden'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__InputHidden',C.cloneNode(true));D.setAttribute('_fckinputhidden','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}};FCKEmbedAndObjectProcessor.AddCustomHandler(function(A,B){if (!(A.nodeName.IEquals('embed')&&(A.type=='application/x-shockwave-flash'||/\.swf($|#|\?)/i.test(A.src)))) return;B.className='FCK__Flash';B.setAttribute('_fckflash','true',0);});if (FCKBrowserInfo.IsSafari){FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByClassName?A.getElementsByClassName('Apple-style-span'):Array.prototype.filter.call(A.getElementsByTagName('span'),function(item){ return item.className=='Apple-style-span';});for (var i=B.length-1;i>=0;i--) FCKDomTools.RemoveNode(B[i],true);}}; +var FCKSelection=FCK.Selection={GetParentBlock:function(){var A=this.GetParentElement();while (A){if (FCKListsLib.BlockBoundaries[A.nodeName.toLowerCase()]) break;A=A.parentNode;};return A;},ApplyStyle:function(A){FCKStyles.ApplyStyle(new FCKStyle(A));}}; +FCKSelection.GetType=function(){try{var A=FCKSelection.GetSelection().type;if (A=='Control'||A=='Text') return A;if (this.GetSelection().createRange().parentElement) return 'Text';}catch(e){};return 'None';};FCKSelection.GetSelectedElement=function(){if (this.GetType()=='Control'){var A=this.GetSelection().createRange();if (A&&A.item) return this.GetSelection().createRange().item(0);};return null;};FCKSelection.GetParentElement=function(){switch (this.GetType()){case 'Control':var A=FCKSelection.GetSelectedElement();return A?A.parentElement:null;case 'None':return null;default:return this.GetSelection().createRange().parentElement();}};FCKSelection.GetBoundaryParentElement=function(A){switch (this.GetType()){case 'Control':var B=FCKSelection.GetSelectedElement();return B?B.parentElement:null;case 'None':return null;default:var C=FCK.EditorDocument;var D=C.selection.createRange();D.collapse(A!==false);var B=D.parentElement();return FCKTools.GetElementDocument(B)==C?B:null;}};FCKSelection.SelectNode=function(A){FCK.Focus();this.GetSelection().empty();var B;try{B=FCK.EditorDocument.body.createControlRange();B.addElement(A);B.select();}catch(e){B=FCK.EditorDocument.body.createTextRange();B.moveToElementText(A);B.select();}};FCKSelection.Collapse=function(A){FCK.Focus();if (this.GetType()=='Text'){var B=this.GetSelection().createRange();B.collapse(A==null||A===true);B.select();}};FCKSelection.HasAncestorNode=function(A){var B;if (this.GetSelection().type=="Control"){B=this.GetSelectedElement();}else{var C=this.GetSelection().createRange();B=C.parentElement();}while (B){if (B.nodeName.IEquals(A)) return true;B=B.parentNode;};return false;};FCKSelection.MoveToAncestorNode=function(A){var B,oRange;if (!FCK.EditorDocument) return null;if (this.GetSelection().type=="Control"){oRange=this.GetSelection().createRange();for (i=0;i=0;i--){if (C[i]) FCKTableHandler.DeleteRows(C[i]);};return;};var E=FCKTools.GetElementAscensor(A,'TABLE');if (E.rows.length==1){FCKTableHandler.DeleteTable(E);return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteTable=function(A){if (!A){A=FCKSelection.GetSelectedElement();if (!A||A.tagName!='TABLE') A=FCKSelection.MoveToAncestorNode('TABLE');};if (!A) return;FCKSelection.SelectNode(A);FCKSelection.Collapse();if (A.parentNode.childNodes.length==1) A.parentNode.parentNode.removeChild(A.parentNode);else A.parentNode.removeChild(A);};FCKTableHandler.InsertColumn=function(A){var B=null;var C=this.GetSelectedCells();if (C&&C.length) B=C[A?0:(C.length-1)];if (!B) return;var D=FCKTools.GetElementAscensor(B,'TABLE');var E=B.cellIndex;for (var i=0;i=0;i--){if (B[i]) FCKTableHandler.DeleteColumns(B[i]);};return;};if (!A) return;var C=FCKTools.GetElementAscensor(A,'TABLE');var D=A.cellIndex;for (var i=C.rows.length-1;i>=0;i--){var E=C.rows[i];if (D==0&&E.cells.length==1){FCKTableHandler.DeleteRows(E);continue;};if (E.cells[D]) E.removeChild(E.cells[D]);}};FCKTableHandler.InsertCell=function(A,B){var C=null;var D=this.GetSelectedCells();if (D&&D.length) C=D[B?0:(D.length-1)];if (!C) return null;var E=FCK.EditorDocument.createElement('TD');if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(E);if (!B&&C.cellIndex==C.parentNode.cells.length-1) C.parentNode.appendChild(E);else C.parentNode.insertBefore(E,B?C:C.nextSibling);return E;};FCKTableHandler.DeleteCell=function(A){if (A.parentNode.cells.length==1){FCKTableHandler.DeleteRows(A.parentNode);return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteCells=function(){var A=FCKTableHandler.GetSelectedCells();for (var i=A.length-1;i>=0;i--){FCKTableHandler.DeleteCell(A[i]);}};FCKTableHandler._MarkCells=function(A,B){for (var i=0;i=E.height){for (D=F;D0){var L=K.removeChild(K.firstChild);if (L.nodeType!=1||(L.getAttribute('type',2)!='_moz'&&L.getAttribute('_moz_dirty')!=null)){I.appendChild(L);J++;}}};if (J>0) I.appendChild(FCK.EditorDocument.createElement('br'));};this._ReplaceCellsByMarker(C,'_SelectedCells',B);this._UnmarkCells(A,'_SelectedCells');this._InstallTableMap(C,B.parentNode.parentNode.parentNode);B.appendChild(I);if (FCKBrowserInfo.IsGeckoLike&&(!B.firstChild)) FCKTools.AppendBogusBr(B);this._MoveCaretToCell(B,false);};FCKTableHandler.MergeRight=function(){var A=this.GetMergeRightTarget();if (A==null) return;var B=A.refCell;var C=A.tableMap;var D=A.nextCell;var E=FCK.EditorDocument.createDocumentFragment();while (D&&D.childNodes&&D.childNodes.length>0) E.appendChild(D.removeChild(D.firstChild));D.parentNode.removeChild(D);B.appendChild(E);this._MarkCells([D],'_Replace');this._ReplaceCellsByMarker(C,'_Replace',B);this._InstallTableMap(C,B.parentNode.parentNode.parentNode);this._MoveCaretToCell(B,false);};FCKTableHandler.MergeDown=function(){var A=this.GetMergeDownTarget();if (A==null) return;var B=A.refCell;var C=A.tableMap;var D=A.nextCell;var E=FCKTools.GetElementDocument(B).createDocumentFragment();while (D&&D.childNodes&&D.childNodes.length>0) E.appendChild(D.removeChild(D.firstChild));if (E.firstChild) E.insertBefore(FCK.EditorDocument.createElement('br'),E.firstChild);B.appendChild(E);this._MarkCells([D],'_Replace');this._ReplaceCellsByMarker(C,'_Replace',B);this._InstallTableMap(C,B.parentNode.parentNode.parentNode);this._MoveCaretToCell(B,false);};FCKTableHandler.HorizontalSplitCell=function(){var A=FCKTableHandler.GetSelectedCells();if (A.length!=1) return;var B=A[0];var C=this._CreateTableMap(B);var D=B.parentNode.rowIndex;var E=FCKTableHandler._GetCellIndexSpan(C,D,B);var F=isNaN(B.colSpan)?1:B.colSpan;if (F>1){var G=Math.ceil(F/2);var H=FCK.EditorDocument.createElement(B.nodeName);if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(H);var I=E+G;var J=E+F;var K=isNaN(B.rowSpan)?1:B.rowSpan;for (var r=D;r1){B.rowSpan=Math.ceil(G/2);var H=D+Math.ceil(G/2);var I=C[H];var J=null;for (var i=E+1;i1) K.colSpan=F;if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(K);B.parentNode.parentNode.parentNode.rows[H].insertBefore(K,J);}else{var L=B.parentNode.sectionRowIndex+1;var M=FCK.EditorDocument.createElement('tr');var N=B.parentNode.parentNode;if (N.rows.length>L) N.insertBefore(M,N.rows[L]);else N.appendChild(M);for (var i=0;i1) K.colSpan=F;if (FCKBrowserInfo.IsGeckoLike) FCKTools.AppendBogusBr(K);M.appendChild(K);}};FCKTableHandler._GetCellIndexSpan=function(A,B,C){if (A.lengthE) E=j;if (D._colScanned===true) continue;if (A[i][j-1]==D) D.colSpan++;if (A[i][j+1]!=D) D._colScanned=true;}};for (var i=0;i<=E;i++){for (var j=0;j=0&&C.compareEndPoints('StartToEnd',E)<=0)||(C.compareEndPoints('EndToStart',E)>=0&&C.compareEndPoints('EndToEnd',E)<=0)){B[B.length]=D.cells[i];}}}};return B;}; +var FCKXml=function(){this.Error=false;};FCKXml.GetAttribute=function(A,B,C){var D=A.attributes.getNamedItem(B);return D?D.value:C;};FCKXml.TransformToObject=function(A){if (!A) return null;var B={};var C=A.attributes;for (var i=0;i ';var A=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',e);var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=B.SplitBlock();B.InsertNode(A);FCK.Events.FireEvent('OnSelectionChange');};FCKPageBreakCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;return 0;};var FCKUnlinkCommand=function(){this.Name='Unlink';};FCKUnlinkCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();if (FCKBrowserInfo.IsGeckoLike){var A=FCK.Selection.MoveToAncestorNode('A');if (A) FCKTools.RemoveOuterTags(A);return;};FCK.ExecuteNamedCommand(this.Name);};FCKUnlinkCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;var A=FCK.GetNamedCommandState(this.Name);if (A==0&&FCK.EditMode==0){var B=FCKSelection.MoveToAncestorNode('A');var C=(B&&B.name.length>0&&B.href.length==0);if (C) A=-1;};return A;};var FCKVisitLinkCommand=function(){this.Name='VisitLink';};FCKVisitLinkCommand.prototype={GetState:function(){if (FCK.EditMode!=0) return -1;var A=FCK.GetNamedCommandState('Unlink');if (A==0){var B=FCKSelection.MoveToAncestorNode('A');if (!B.href) A=-1;};return A;},Execute:function(){var A=FCKSelection.MoveToAncestorNode('A');var B=A.getAttribute('_fcksavedurl')||A.getAttribute('href',2);if (!/:\/\//.test(B)){var C=FCKConfig.BaseHref;var D=FCK.GetInstanceObject('parent');if (!C){C=D.document.location.href;C=C.substring(0,C.lastIndexOf('/')+1);};if (/^\//.test(B)){try{C=C.match(/^.*:\/\/+[^\/]+/)[0];}catch (e){C=D.document.location.protocol+'://'+D.parent.document.location.host;}};B=C+B;};if (!window.open(B,'_blank')) alert(FCKLang.VisitLinkBlocked);}};var FCKSelectAllCommand=function(){this.Name='SelectAll';};FCKSelectAllCommand.prototype.Execute=function(){if (FCK.EditMode==0){FCK.ExecuteNamedCommand('SelectAll');}else{var A=FCK.EditingArea.Textarea;if (FCKBrowserInfo.IsIE){A.createTextRange().execCommand('SelectAll');}else{A.selectionStart=0;A.selectionEnd=A.value.length;};A.focus();}};FCKSelectAllCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;return 0;};var FCKPasteCommand=function(){this.Name='Paste';};FCKPasteCommand.prototype={Execute:function(){if (FCKBrowserInfo.IsIE) FCK.Paste();else FCK.ExecuteNamedCommand('Paste');},GetState:function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('Paste');}};var FCKRuleCommand=function(){this.Name='Rule';};FCKRuleCommand.prototype={Execute:function(){FCKUndo.SaveUndoStep();FCK.InsertElement('hr');},GetState:function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('InsertHorizontalRule');}};var FCKCutCopyCommand=function(A){this.Name=A?'Cut':'Copy';};FCKCutCopyCommand.prototype={Execute:function(){var A=false;if (FCKBrowserInfo.IsIE){var B=function(){A=true;};var C='on'+this.Name.toLowerCase();FCK.EditorDocument.body.attachEvent(C,B);FCK.ExecuteNamedCommand(this.Name);FCK.EditorDocument.body.detachEvent(C,B);}else{try{FCK.ExecuteNamedCommand(this.Name);A=true;}catch(e){}};if (!A) alert(FCKLang['PasteError'+this.Name]);},GetState:function(){return FCK.EditMode!=0?-1:FCK.GetNamedCommandState('Cut');}};var FCKAnchorDeleteCommand=function(){this.Name='AnchorDelete';};FCKAnchorDeleteCommand.prototype={Execute:function(){if (FCK.Selection.GetType()=='Control'){FCK.Selection.Delete();}else{var A=FCK.Selection.GetSelectedElement();if (A){if (A.tagName=='IMG'&&A.getAttribute('_fckanchor')) oAnchor=FCK.GetRealElement(A);else A=null;};if (!A){oAnchor=FCK.Selection.MoveToAncestorNode('A');if (oAnchor) FCK.Selection.SelectNode(oAnchor);};if (oAnchor.href.length!=0){oAnchor.removeAttribute('name');if (FCKBrowserInfo.IsIE) oAnchor.className=oAnchor.className.replace(FCKRegexLib.FCK_Class,'');return;};if (A){A.parentNode.removeChild(A);return;};if (oAnchor.innerHTML.length==0){oAnchor.parentNode.removeChild(oAnchor);return;};FCKTools.RemoveOuterTags(oAnchor);};if (FCKBrowserInfo.IsGecko) FCK.Selection.Collapse(true);},GetState:function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('Unlink');}};var FCKDeleteDivCommand=function(){};FCKDeleteDivCommand.prototype={GetState:function(){if (FCK.EditMode!=0) return -1;var A=FCKSelection.GetParentElement();var B=new FCKElementPath(A);return B.BlockLimit&&B.BlockLimit.nodeName.IEquals('div')?0:-1;},Execute:function(){FCKUndo.SaveUndoStep();var A=FCKDomTools.GetSelectedDivContainers();var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=B.CreateBookmark();for (var i=0;i\n \n
    \n '+FCKLang.ColorAutomatic+'\n \n ';FCKTools.AddEventListenerEx(C,'click',FCKTextColorCommand_AutoOnClick,this);if (!FCKBrowserInfo.IsIE) C.style.width='96%';var G=FCKConfig.FontColors.toString().split(',');var H=0;while (H
    ';if (H>=G.length) C.style.visibility='hidden';else FCKTools.AddEventListenerEx(C,'click',FCKTextColorCommand_OnClick,[this,L]);}};if (FCKConfig.EnableMoreFontColors){E=D.insertRow(-1).insertCell(-1);E.colSpan=8;C=E.appendChild(CreateSelectionDiv());C.innerHTML='
    '+FCKLang.ColorMoreColors+'
    ';FCKTools.AddEventListenerEx(C,'click',FCKTextColorCommand_MoreOnClick,this);if (!FCKBrowserInfo.IsIE) C.style.width='96%';}}; +var FCKPastePlainTextCommand=function(){this.Name='PasteText';};FCKPastePlainTextCommand.prototype.Execute=function(){FCK.PasteAsPlainText();};FCKPastePlainTextCommand.prototype.GetState=function(){if (FCK.EditMode!=0) return -1;return FCK.GetNamedCommandState('Paste');}; +var FCKPasteWordCommand=function(){this.Name='PasteWord';};FCKPasteWordCommand.prototype.Execute=function(){FCK.PasteFromWord();};FCKPasteWordCommand.prototype.GetState=function(){if (FCK.EditMode!=0||FCKConfig.ForcePasteAsPlainText) return -1;else return FCK.GetNamedCommandState('Paste');}; +var FCKTableCommand=function(A){this.Name=A;};FCKTableCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();if (!FCKBrowserInfo.IsGecko){switch (this.Name){case 'TableMergeRight':return FCKTableHandler.MergeRight();case 'TableMergeDown':return FCKTableHandler.MergeDown();}};switch (this.Name){case 'TableInsertRowAfter':return FCKTableHandler.InsertRow(false);case 'TableInsertRowBefore':return FCKTableHandler.InsertRow(true);case 'TableDeleteRows':return FCKTableHandler.DeleteRows();case 'TableInsertColumnAfter':return FCKTableHandler.InsertColumn(false);case 'TableInsertColumnBefore':return FCKTableHandler.InsertColumn(true);case 'TableDeleteColumns':return FCKTableHandler.DeleteColumns();case 'TableInsertCellAfter':return FCKTableHandler.InsertCell(null,false);case 'TableInsertCellBefore':return FCKTableHandler.InsertCell(null,true);case 'TableDeleteCells':return FCKTableHandler.DeleteCells();case 'TableMergeCells':return FCKTableHandler.MergeCells();case 'TableHorizontalSplitCell':return FCKTableHandler.HorizontalSplitCell();case 'TableVerticalSplitCell':return FCKTableHandler.VerticalSplitCell();case 'TableDelete':return FCKTableHandler.DeleteTable();default:return alert(FCKLang.UnknownCommand.replace(/%1/g,this.Name));}};FCKTableCommand.prototype.GetState=function(){if (FCK.EditorDocument!=null&&FCKSelection.HasAncestorNode('TABLE')){switch (this.Name){case 'TableHorizontalSplitCell':case 'TableVerticalSplitCell':if (FCKTableHandler.GetSelectedCells().length==1) return 0;else return -1;case 'TableMergeCells':if (FCKTableHandler.CheckIsSelectionRectangular()&&FCKTableHandler.GetSelectedCells().length>1) return 0;else return -1;case 'TableMergeRight':return FCKTableHandler.GetMergeRightTarget()?0:-1;case 'TableMergeDown':return FCKTableHandler.GetMergeDownTarget()?0:-1;default:return 0;}}else return -1;}; +var FCKFitWindow=function(){this.Name='FitWindow';};FCKFitWindow.prototype.Execute=function(){var A=window.frameElement;var B=A.style;var C=parent;var D=C.document.documentElement;var E=C.document.body;var F=E.style;var G;var H,oEditorScrollPos;if (FCK.EditMode==0){H=new FCKDomRange(FCK.EditorWindow);H.MoveToSelection();oEditorScrollPos=FCKTools.GetScrollPosition(FCK.EditorWindow);}else{var I=FCK.EditingArea.Textarea;H=!FCKBrowserInfo.IsIE&&[I.selectionStart,I.selectionEnd];oEditorScrollPos=[I.scrollLeft,I.scrollTop];};if (!this.IsMaximized){if(FCKBrowserInfo.IsIE) C.attachEvent('onresize',FCKFitWindow_Resize);else C.addEventListener('resize',FCKFitWindow_Resize,true);this._ScrollPos=FCKTools.GetScrollPosition(C);G=A;while((G=G.parentNode)){if (G.nodeType==1){G._fckSavedStyles=FCKTools.SaveStyles(G);G.style.zIndex=FCKConfig.FloatingPanelsZIndex-1;}};if (FCKBrowserInfo.IsIE){this.documentElementOverflow=D.style.overflow;D.style.overflow='hidden';F.overflow='hidden';}else{F.overflow='hidden';F.width='0px';F.height='0px';};this._EditorFrameStyles=FCKTools.SaveStyles(A);var J=FCKTools.GetViewPaneSize(C);B.position="absolute";A.offsetLeft;B.zIndex=FCKConfig.FloatingPanelsZIndex-1;B.left="0px";B.top="0px";B.width=J.Width+"px";B.height=J.Height+"px";if (!FCKBrowserInfo.IsIE){B.borderRight=B.borderBottom="9999px solid white";B.backgroundColor="white";};C.scrollTo(0,0);var K=FCKTools.GetWindowPosition(C,A);if (K.x!=0) B.left=(-1*K.x)+"px";if (K.y!=0) B.top=(-1*K.y)+"px";this.IsMaximized=true;}else{if(FCKBrowserInfo.IsIE) C.detachEvent("onresize",FCKFitWindow_Resize);else C.removeEventListener("resize",FCKFitWindow_Resize,true);G=A;while((G=G.parentNode)){if (G._fckSavedStyles){FCKTools.RestoreStyles(G,G._fckSavedStyles);G._fckSavedStyles=null;}};if (FCKBrowserInfo.IsIE) D.style.overflow=this.documentElementOverflow;FCKTools.RestoreStyles(A,this._EditorFrameStyles);C.scrollTo(this._ScrollPos.X,this._ScrollPos.Y);this.IsMaximized=false;};FCKToolbarItems.GetItem('FitWindow').RefreshState();if (FCK.EditMode==0) FCK.EditingArea.MakeEditable();FCK.Focus();if (FCK.EditMode==0){H.Select();FCK.EditorWindow.scrollTo(oEditorScrollPos.X,oEditorScrollPos.Y);}else{if (!FCKBrowserInfo.IsIE){I.selectionStart=H[0];I.selectionEnd=H[1];};I.scrollLeft=oEditorScrollPos[0];I.scrollTop=oEditorScrollPos[1];}};FCKFitWindow.prototype.GetState=function(){if (FCKConfig.ToolbarLocation!='In') return -1;else return (this.IsMaximized?1:0);};function FCKFitWindow_Resize(){var A=FCKTools.GetViewPaneSize(parent);var B=window.frameElement.style;B.width=A.Width+'px';B.height=A.Height+'px';}; +var FCKListCommand=function(A,B){this.Name=A;this.TagName=B;};FCKListCommand.prototype={GetState:function(){if (FCK.EditMode!=0||!FCK.EditorWindow) return -1;var A=FCKSelection.GetBoundaryParentElement(true);var B=A;while (B){if (B.nodeName.IEquals(['ul','ol'])) break;B=B.parentNode;};if (B&&B.nodeName.IEquals(this.TagName)) return 1;else return 0;},Execute:function(){FCKUndo.SaveUndoStep();var A=FCK.EditorDocument;var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=this.GetState();if (C==0){FCKDomTools.TrimNode(A.body);if (!A.body.firstChild){var D=A.createElement('p');A.body.appendChild(D);B.MoveToNodeContents(D);}};var E=B.CreateBookmark();var F=[];var G={};var H=new FCKDomRangeIterator(B);var I;H.ForceBrBreak=(C==0);var J=true;var K=null;while (J){while ((I=H.GetNextParagraph())){var L=new FCKElementPath(I);var M=null;var N=false;var O=L.BlockLimit;for (var i=L.Elements.length-1;i>=0;i--){var P=L.Elements[i];if (P.nodeName.IEquals(['ol','ul'])){if (O._FCK_ListGroupObject) O._FCK_ListGroupObject=null;var Q=P._FCK_ListGroupObject;if (Q) Q.contents.push(I);else{Q={ 'root':P,'contents':[I] };F.push(Q);FCKDomTools.SetElementMarker(G,P,'_FCK_ListGroupObject',Q);};N=true;break;}};if (N) continue;var R=O;if (R._FCK_ListGroupObject) R._FCK_ListGroupObject.contents.push(I);else{var Q={ 'root':R,'contents':[I] };FCKDomTools.SetElementMarker(G,R,'_FCK_ListGroupObject',Q);F.push(Q);}};if (FCKBrowserInfo.IsIE) J=false;else{if (K==null){K=[];var T=FCKSelection.GetSelection();if (T&&F.length==0) K.push(T.getRangeAt(0));for (var i=1;T&&i0){var Q=F.shift();if (C==0){if (Q.root.nodeName.IEquals(['ul','ol'])) this._ChangeListType(Q,G,W);else this._CreateList(Q,W);}else if (C==1&&Q.root.nodeName.IEquals(['ul','ol'])) this._RemoveList(Q,G);};for (var i=0;iC[i-1].indent+1){var H=C[i-1].indent+1-C[i].indent;var I=C[i].indent;while (C[i]&&C[i].indent>=I){C[i].indent+=H;i++;};i--;}};var J=FCKDomTools.ArrayToList(C,B);if (A.root.nextSibling==null||A.root.nextSibling.nodeName.IEquals('br')){if (J.listNode.lastChild.nodeName.IEquals('br')) J.listNode.removeChild(J.listNode.lastChild);};A.root.parentNode.replaceChild(J.listNode,A.root);}}; +var FCKJustifyCommand=function(A){this.AlignValue=A;var B=FCKConfig.ContentLangDirection.toLowerCase();this.IsDefaultAlign=(A=='left'&&B=='ltr')||(A=='right'&&B=='rtl');var C=this._CssClassName=(function(){var D=FCKConfig.JustifyClasses;if (D){switch (A){case 'left':return D[0]||null;case 'center':return D[1]||null;case 'right':return D[2]||null;case 'justify':return D[3]||null;}};return null;})();if (C&&C.length>0) this._CssClassRegex=new RegExp('(?:^|\\s+)'+C+'(?=$|\\s)');};FCKJustifyCommand._GetClassNameRegex=function(){var A=FCKJustifyCommand._ClassRegex;if (A!=undefined) return A;var B=[];var C=FCKConfig.JustifyClasses;if (C){for (var i=0;i<4;i++){var D=C[i];if (D&&D.length>0) B.push(D);}};if (B.length>0) A=new RegExp('(?:^|\\s+)(?:'+B.join('|')+')(?=$|\\s)');else A=null;return FCKJustifyCommand._ClassRegex=A;};FCKJustifyCommand.prototype={Execute:function(){FCKUndo.SaveUndoStep();var A=new FCKDomRange(FCK.EditorWindow);A.MoveToSelection();var B=this.GetState();if (B==-1) return;var C=A.CreateBookmark();var D=this._CssClassName;var E=new FCKDomRangeIterator(A);var F;while ((F=E.GetNextParagraph())){F.removeAttribute('align');if (D){var G=F.className.replace(FCKJustifyCommand._GetClassNameRegex(),'');if (B==0){if (G.length>0) G+=' ';F.className=G+D;}else if (G.length==0) FCKDomTools.RemoveAttribute(F,'class');}else{var H=F.style;if (B==0) H.textAlign=this.AlignValue;else{H.textAlign='';if (H.cssText.length==0) F.removeAttribute('style');}}};A.MoveToBookmark(C);A.Select();FCK.Focus();FCK.Events.FireEvent('OnSelectionChange');},GetState:function(){if (FCK.EditMode!=0||!FCK.EditorWindow) return -1;var A=new FCKElementPath(FCKSelection.GetBoundaryParentElement(true));var B=A.Block||A.BlockLimit;if (!B||B.nodeName.toLowerCase()=='body') return 0;var C;if (FCKBrowserInfo.IsIE) C=B.currentStyle.textAlign;else C=FCK.EditorWindow.getComputedStyle(B,'').getPropertyValue('text-align');C=C.replace(/(-moz-|-webkit-|start|auto)/i,'');if ((!C&&this.IsDefaultAlign)||C==this.AlignValue) return 1;return 0;}}; +var FCKIndentCommand=function(A,B){this.Name=A;this.Offset=B;this.IndentCSSProperty=FCKConfig.ContentLangDirection.IEquals('ltr')?'marginLeft':'marginRight';};FCKIndentCommand._InitIndentModeParameters=function(){if (FCKConfig.IndentClasses&&FCKConfig.IndentClasses.length>0){this._UseIndentClasses=true;this._IndentClassMap={};for (var i=0;i0?H+' ':'')+FCKConfig.IndentClasses[G-1];}else{var I=parseInt(E.style[this.IndentCSSProperty],10);if (isNaN(I)) I=0;I+=this.Offset;I=Math.max(I,0);I=Math.ceil(I/this.Offset)*this.Offset;E.style[this.IndentCSSProperty]=I?I+FCKConfig.IndentUnit:'';if (E.getAttribute('style')=='') E.removeAttribute('style');}}},_IndentList:function(A,B){var C=A.StartContainer;var D=A.EndContainer;while (C&&C.parentNode!=B) C=C.parentNode;while (D&&D.parentNode!=B) D=D.parentNode;if (!C||!D) return;var E=C;var F=[];var G=false;while (G==false){if (E==D) G=true;F.push(E);E=E.nextSibling;};if (F.length<1) return;var H=FCKDomTools.GetParents(B);for (var i=0;iN;i++) M[i].indent+=I;var O=FCKDomTools.ArrayToList(M);if (O) B.parentNode.replaceChild(O.listNode,B);FCKDomTools.ClearAllMarkers(L);}}; +var FCKBlockQuoteCommand=function(){};FCKBlockQuoteCommand.prototype={Execute:function(){FCKUndo.SaveUndoStep();var A=this.GetState();var B=new FCKDomRange(FCK.EditorWindow);B.MoveToSelection();var C=B.CreateBookmark();if (FCKBrowserInfo.IsIE){var D=B.GetBookmarkNode(C,true);var E=B.GetBookmarkNode(C,false);var F;if (D&&D.parentNode.nodeName.IEquals('blockquote')&&!D.previousSibling){F=D;while ((F=F.nextSibling)){if (FCKListsLib.BlockElements[F.nodeName.toLowerCase()]) FCKDomTools.MoveNode(D,F,true);}};if (E&&E.parentNode.nodeName.IEquals('blockquote')&&!E.previousSibling){F=E;while ((F=F.nextSibling)){if (FCKListsLib.BlockElements[F.nodeName.toLowerCase()]){if (F.firstChild==D) FCKDomTools.InsertAfterNode(D,E);else FCKDomTools.MoveNode(E,F,true);}}}};var G=new FCKDomRangeIterator(B);var H;if (A==0){var I=[];while ((H=G.GetNextParagraph())) I.push(H);if (I.length<1){para=B.Window.document.createElement(FCKConfig.EnterMode.IEquals('p')?'p':'div');B.InsertNode(para);para.appendChild(B.Window.document.createTextNode('\ufeff'));B.MoveToBookmark(C);B.MoveToNodeContents(para);B.Collapse(true);C=B.CreateBookmark();I.push(para);};var J=I[0].parentNode;var K=[];for (var i=0;i0){H=I.shift();while (H.parentNode!=J) H=H.parentNode;if (H!=L) K.push(H);L=H;}while (K.length>0){H=K.shift();if (H.nodeName.IEquals('blockquote')){var M=FCKTools.GetElementDocument(H).createDocumentFragment();while (H.firstChild){M.appendChild(H.removeChild(H.firstChild));I.push(M.lastChild);};H.parentNode.replaceChild(M,H);}else I.push(H);};var N=B.Window.document.createElement('blockquote');J.insertBefore(N,I[0]);while (I.length>0){H=I.shift();N.appendChild(H);}}else if (A==1){var O=[];var P={};while ((H=G.GetNextParagraph())){var Q=null;var R=null;while (H.parentNode){if (H.parentNode.nodeName.IEquals('blockquote')){Q=H.parentNode;R=H;break;};H=H.parentNode;};if (Q&&R&&!R._fckblockquotemoveout){O.push(R);FCKDomTools.SetElementMarker(P,R,'_fckblockquotemoveout',true);}};FCKDomTools.ClearAllMarkers(P);var S=[];var T=[],P={};var U=function(N){for (var i=0;i0){var W=O.shift();var N=W.parentNode;if (W==W.parentNode.firstChild) N.parentNode.insertBefore(N.removeChild(W),N);else if (W==W.parentNode.lastChild) N.parentNode.insertBefore(N.removeChild(W),N.nextSibling);else FCKDomTools.BreakParent(W,W.parentNode,B);if (!N._fckbqprocessed){T.push(N);FCKDomTools.SetElementMarker(P,N,'_fckbqprocessed',true);};S.push(W);};for (var i=T.length-1;i>=0;i--){var N=T[i];if (U(N)) FCKDomTools.RemoveNode(N);};FCKDomTools.ClearAllMarkers(P);if (FCKConfig.EnterMode.IEquals('br')){while (S.length){var W=S.shift();var a=true;if (W.nodeName.IEquals('div')){var M=FCKTools.GetElementDocument(W).createDocumentFragment();var c=a&&W.previousSibling&&!FCKListsLib.BlockBoundaries[W.previousSibling.nodeName.toLowerCase()];if (a&&c) M.appendChild(FCKTools.GetElementDocument(W).createElement('br'));var d=W.nextSibling&&!FCKListsLib.BlockBoundaries[W.nextSibling.nodeName.toLowerCase()];while (W.firstChild) M.appendChild(W.removeChild(W.firstChild));if (d) M.appendChild(FCKTools.GetElementDocument(W).createElement('br'));W.parentNode.replaceChild(M,W);a=false;}}}};B.MoveToBookmark(C);B.Select();FCK.Focus();FCK.Events.FireEvent('OnSelectionChange');},GetState:function(){if (FCK.EditMode!=0||!FCK.EditorWindow) return -1;var A=new FCKElementPath(FCKSelection.GetBoundaryParentElement(true));var B=A.Block||A.BlockLimit;if (!B||B.nodeName.toLowerCase()=='body') return 0;for (var i=0;i';B.open();B.write(''+F+'<\/head><\/body><\/html>');B.close();if(FCKBrowserInfo.IsAIR) FCKAdobeAIR.Panel_Contructor(B,window.document.location);FCKTools.AddEventListenerEx(E,'focus',FCKPanel_Window_OnFocus,this);FCKTools.AddEventListenerEx(E,'blur',FCKPanel_Window_OnBlur,this);};B.dir=FCKLang.Dir;FCKTools.AddEventListener(B,'contextmenu',FCKTools.CancelEvent);this.MainNode=B.body.appendChild(B.createElement('DIV'));this.MainNode.style.cssFloat=this.IsRTL?'right':'left';};FCKPanel.prototype.AppendStyleSheet=function(A){FCKTools.AppendStyleSheet(this.Document,A);};FCKPanel.prototype.Preload=function(x,y,A){if (this._Popup) this._Popup.show(x,y,0,0,A);};FCKPanel.prototype.ResizeForSubpanel=function(A,B,C){if (!FCKBrowserInfo.IsIE7) return false;if (!this._Popup.isOpen){this.Subpanel=null;return false;};if (B==0&&C==0){if (this.Subpanel!==A) return false;this.Subpanel=null;this.IncreasedX=0;}else{this.Subpanel=A;if ((this.IncreasedX>=B)&&(this.IncreasedY>=C)) return false;this.IncreasedX=Math.max(this.IncreasedX,B);this.IncreasedY=Math.max(this.IncreasedY,C);};var x=this.ShowRect.x;var w=this.IncreasedX;if (this.IsRTL) x=x-w;var D=this.ShowRect.w+w;var E=Math.max(this.ShowRect.h,this.IncreasedY);if (this.ParentPanel) this.ParentPanel.ResizeForSubpanel(this,D,E);this._Popup.show(x,this.ShowRect.y,D,E,this.RelativeElement);return this.IsRTL;};FCKPanel.prototype.Show=function(x,y,A,B,C){var D;var E=this.MainNode;if (this._Popup){this._Popup.show(x,y,0,0,A);FCKDomTools.SetElementStyles(E,{B:B?B+'px':'',C:C?C+'px':''});D=E.offsetWidth;if (FCKBrowserInfo.IsIE7){if (this.ParentPanel&&this.ParentPanel.ResizeForSubpanel(this,D,E.offsetHeight)){FCKTools.RunFunction(this.Show,this,[x,y,A]);return;}};if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=(x*-1)+A.offsetWidth-D;};if (FCKBrowserInfo.IsIE7){this.ShowRect={x:x,y:y,w:D,h:E.offsetHeight};this.IncreasedX=0;this.IncreasedY=0;this.RelativeElement=A;};this._PopupArgs=[x,y,D,E.offsetHeight,A];this._Popup.show(x,y,D,E.offsetHeight,A);if (this.OnHide){if (this._Timer) CheckPopupOnHide.call(this,true);this._Timer=FCKTools.SetInterval(CheckPopupOnHide,100,this);}}else{if (typeof(FCK.ToolbarSet.CurrentInstance.FocusManager)!='undefined') FCK.ToolbarSet.CurrentInstance.FocusManager.Lock();if (this.ParentPanel){this.ParentPanel.Lock();FCKPanel_Window_OnBlur(null,this.ParentPanel);};if (FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsMac){this._IFrame.scrolling='';FCKTools.RunFunction(function(){ this._IFrame.scrolling='no';},this);};if (FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel&&FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel!=this) FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel.Hide(false,true);FCKDomTools.SetElementStyles(E,{B:B?B+'px':'',C:C?C+'px':''});D=E.offsetWidth;if (!B) this._IFrame.width=1;if (!C) this._IFrame.height=1;D=E.offsetWidth||E.firstChild.offsetWidth;var F=FCKTools.GetDocumentPosition(this._Window,A.nodeType==9?(FCKTools.IsStrictMode(A)?A.documentElement:A.body):A);var G=FCKDomTools.GetPositionedAncestor(this._IFrame.parentNode);if (G){var H=FCKTools.GetDocumentPosition(FCKTools.GetElementWindow(G),G);F.x-=H.x;F.y-=H.y;};if (this.IsRTL&&!this.IsContextMenu) x=(x*-1);x+=F.x;y+=F.y;if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=x+A.offsetWidth-D;}else{var I=FCKTools.GetViewPaneSize(this._Window);var J=FCKTools.GetScrollPosition(this._Window);var K=I.Height+J.Y;var L=I.Width+J.X;if ((x+D)>L) x-=x+D-L;if ((y+E.offsetHeight)>K) y-=y+E.offsetHeight-K;};FCKDomTools.SetElementStyles(this._IFrame,{left:x+'px',top:y+'px'});this._IFrame.contentWindow.focus();this._IsOpened=true;var M=this;this._resizeTimer=setTimeout(function(){var N=E.offsetWidth||E.firstChild.offsetWidth;var O=E.offsetHeight;M._IFrame.style.width=N+'px';M._IFrame.style.height=O+'px';},0);FCK.ToolbarSet.CurrentInstance.GetInstanceObject('FCKPanel')._OpenedPanel=this;};FCKTools.RunFunction(this.OnShow,this);};FCKPanel.prototype.Hide=function(A,B){if (this._Popup) this._Popup.hide();else{if (!this._IsOpened||this._LockCounter>0) return;if (typeof(FCKFocusManager)!='undefined'&&!B) FCKFocusManager.Unlock();this._IFrame.style.width=this._IFrame.style.height='0px';this._IsOpened=false;if (this._resizeTimer){clearTimeout(this._resizeTimer);this._resizeTimer=null;};if (this.ParentPanel) this.ParentPanel.Unlock();if (!A) FCKTools.RunFunction(this.OnHide,this);}};FCKPanel.prototype.CheckIsOpened=function(){if (this._Popup) return this._Popup.isOpen;else return this._IsOpened;};FCKPanel.prototype.CreateChildPanel=function(){var A=this._Popup?FCKTools.GetDocumentWindow(this.Document):this._Window;var B=new FCKPanel(A);B.ParentPanel=this;return B;};FCKPanel.prototype.Lock=function(){this._LockCounter++;};FCKPanel.prototype.Unlock=function(){if (--this._LockCounter==0&&!this.HasFocus) this.Hide();};function FCKPanel_Window_OnFocus(e,A){A.HasFocus=true;};function FCKPanel_Window_OnBlur(e,A){A.HasFocus=false;if (A._LockCounter==0) FCKTools.RunFunction(A.Hide,A);};function CheckPopupOnHide(A){if (A||!this._Popup.isOpen){window.clearInterval(this._Timer);this._Timer=null;if (this._Popup&&this.ParentPanel&&!A) this.ParentPanel.ResizeForSubpanel(this,0,0);FCKTools.RunFunction(this.OnHide,this);}};function FCKPanel_Cleanup(){this._Popup=null;this._Window=null;this.Document=null;this.MainNode=null;this.RelativeElement=null;}; +var FCKIcon=function(A){var B=A?typeof(A):'undefined';switch (B){case 'number':this.Path=FCKConfig.SkinPath+'fck_strip.gif';this.Size=16;this.Position=A;break;case 'undefined':this.Path=FCK_SPACER_PATH;break;case 'string':this.Path=A;break;default:this.Path=A[0];this.Size=A[1];this.Position=A[2];}};FCKIcon.prototype.CreateIconElement=function(A){var B,eIconImage;if (this.Position){var C='-'+((this.Position-1)*this.Size)+'px';if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path;eIconImage.style.top=C;}else{B=A.createElement('IMG');B.src=FCK_SPACER_PATH;B.style.backgroundPosition='0px '+C;B.style.backgroundImage='url("'+this.Path+'")';}}else{if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path?this.Path:FCK_SPACER_PATH;}else{B=A.createElement('IMG');B.src=this.Path?this.Path:FCK_SPACER_PATH;}};B.className='TB_Button_Image';return B;}; +var FCKToolbarButtonUI=function(A,B,C,D,E,F){this.Name=A;this.Label=B||A;this.Tooltip=C||this.Label;this.Style=E||0;this.State=F||0;this.Icon=new FCKIcon(D);if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarButtonUI_Cleanup);};FCKToolbarButtonUI.prototype._CreatePaddingElement=function(A){var B=A.createElement('IMG');B.className='TB_Button_Padding';B.src=FCK_SPACER_PATH;return B;};FCKToolbarButtonUI.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var C=this.MainElement=B.createElement('DIV');C.title=this.Tooltip;if (FCKBrowserInfo.IsGecko) C.onmousedown=FCKTools.CancelEvent;FCKTools.AddEventListenerEx(C,'mouseover',FCKToolbarButtonUI_OnMouseOver,this);FCKTools.AddEventListenerEx(C,'mouseout',FCKToolbarButtonUI_OnMouseOut,this);FCKTools.AddEventListenerEx(C,'click',FCKToolbarButtonUI_OnClick,this);this.ChangeState(this.State,true);if (this.Style==0&&!this.ShowArrow){C.appendChild(this.Icon.CreateIconElement(B));}else{var D=C.appendChild(B.createElement('TABLE'));D.cellPadding=0;D.cellSpacing=0;var E=D.insertRow(-1);var F=E.insertCell(-1);if (this.Style==0||this.Style==2) F.appendChild(this.Icon.CreateIconElement(B));else F.appendChild(this._CreatePaddingElement(B));if (this.Style==1||this.Style==2){F=E.insertCell(-1);F.className='TB_Button_Text';F.noWrap=true;F.appendChild(B.createTextNode(this.Label));};if (this.ShowArrow){if (this.Style!=0){E.insertCell(-1).appendChild(this._CreatePaddingElement(B));};F=E.insertCell(-1);var G=F.appendChild(B.createElement('IMG'));G.src=FCKConfig.SkinPath+'images/toolbar.buttonarrow.gif';G.width=5;G.height=3;};F=E.insertCell(-1);F.appendChild(this._CreatePaddingElement(B));};A.appendChild(C);};FCKToolbarButtonUI.prototype.ChangeState=function(A,B){if (!B&&this.State==A) return;var e=this.MainElement;if (!e) return;switch (parseInt(A,10)){case 0:e.className='TB_Button_Off';break;case 1:e.className='TB_Button_On';break;case -1:e.className='TB_Button_Disabled';break;};this.State=A;};function FCKToolbarButtonUI_OnMouseOver(A,B){if (B.State==0) this.className='TB_Button_Off_Over';else if (B.State==1) this.className='TB_Button_On_Over';};function FCKToolbarButtonUI_OnMouseOut(A,B){if (B.State==0) this.className='TB_Button_Off';else if (B.State==1) this.className='TB_Button_On';};function FCKToolbarButtonUI_OnClick(A,B){if (B.OnClick&&B.State!=-1) B.OnClick(B);};function FCKToolbarButtonUI_Cleanup(){this.MainElement=null;}; +var FCKToolbarButton=function(A,B,C,D,E,F,G){this.CommandName=A;this.Label=B;this.Tooltip=C;this.Style=D;this.SourceView=E?true:false;this.ContextSensitive=F?true:false;if (G==null) this.IconPath=FCKConfig.SkinPath+'toolbar/'+A.toLowerCase()+'.gif';else if (typeof(G)=='number') this.IconPath=[FCKConfig.SkinPath+'fck_strip.gif',16,G];else this.IconPath=G;};FCKToolbarButton.prototype.Create=function(A){this._UIButton=new FCKToolbarButtonUI(this.CommandName,this.Label,this.Tooltip,this.IconPath,this.Style);this._UIButton.OnClick=this.Click;this._UIButton._ToolbarButton=this;this._UIButton.Create(A);};FCKToolbarButton.prototype.RefreshState=function(){var A=this._UIButton;if (!A) return;var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (B==A.State) return;A.ChangeState(B);};FCKToolbarButton.prototype.Click=function(){var A=this._ToolbarButton||this;FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(A.CommandName).Execute();};FCKToolbarButton.prototype.Enable=function(){this.RefreshState();};FCKToolbarButton.prototype.Disable=function(){this._UIButton.ChangeState(-1);}; +var FCKSpecialCombo=function(A,B,C,D,E){this.FieldWidth=B||100;this.PanelWidth=C||150;this.PanelMaxHeight=D||150;this.Label=' ';this.Caption=A;this.Tooltip=A;this.Style=2;this.Enabled=true;this.Items={};this._Panel=new FCKPanel(E||window);this._Panel.AppendStyleSheet(FCKConfig.SkinEditorCSS);this._PanelBox=this._Panel.MainNode.appendChild(this._Panel.Document.createElement('DIV'));this._PanelBox.className='SC_Panel';this._PanelBox.style.width=this.PanelWidth+'px';this._PanelBox.innerHTML='
    ';this._ItemsHolderEl=this._PanelBox.getElementsByTagName('TD')[0];if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKSpecialCombo_Cleanup);};function FCKSpecialCombo_ItemOnMouseOver(){this.className+=' SC_ItemOver';};function FCKSpecialCombo_ItemOnMouseOut(){this.className=this.originalClass;};function FCKSpecialCombo_ItemOnClick(A,B,C){this.className=this.originalClass;B._Panel.Hide();B.SetLabel(this.FCKItemLabel);if (typeof(B.OnSelect)=='function') B.OnSelect(C,this);};FCKSpecialCombo.prototype.ClearItems=function (){if (this.Items) this.Items={};var A=this._ItemsHolderEl;while (A.firstChild) A.removeChild(A.firstChild);};FCKSpecialCombo.prototype.AddItem=function(A,B,C,D){var E=this._ItemsHolderEl.appendChild(this._Panel.Document.createElement('DIV'));E.className=E.originalClass='SC_Item';E.innerHTML=B;E.FCKItemLabel=C||A;E.Selected=false;if (FCKBrowserInfo.IsIE) E.style.width='100%';if (D) E.style.backgroundColor=D;FCKTools.AddEventListenerEx(E,'mouseover',FCKSpecialCombo_ItemOnMouseOver);FCKTools.AddEventListenerEx(E,'mouseout',FCKSpecialCombo_ItemOnMouseOut);FCKTools.AddEventListenerEx(E,'click',FCKSpecialCombo_ItemOnClick,[this,A]);this.Items[A.toString().toLowerCase()]=E;return E;};FCKSpecialCombo.prototype.SelectItem=function(A){if (typeof A=='string') A=this.Items[A.toString().toLowerCase()];if (A){A.className=A.originalClass='SC_ItemSelected';A.Selected=true;}};FCKSpecialCombo.prototype.SelectItemByLabel=function(A,B){for (var C in this.Items){var D=this.Items[C];if (D.FCKItemLabel==A){D.className=D.originalClass='SC_ItemSelected';D.Selected=true;if (B) this.SetLabel(A);}}};FCKSpecialCombo.prototype.DeselectAll=function(A){for (var i in this.Items){if (!this.Items[i]) continue;this.Items[i].className=this.Items[i].originalClass='SC_Item';this.Items[i].Selected=false;};if (A) this.SetLabel('');};FCKSpecialCombo.prototype.SetLabelById=function(A){A=A?A.toString().toLowerCase():'';var B=this.Items[A];this.SetLabel(B?B.FCKItemLabel:'');};FCKSpecialCombo.prototype.SetLabel=function(A){A=(!A||A.length==0)?' ':A;if (A==this.Label) return;this.Label=A;var B=this._LabelEl;if (B){B.innerHTML=A;FCKTools.DisableSelection(B);}};FCKSpecialCombo.prototype.SetEnabled=function(A){this.Enabled=A;if (this._OuterTable) this._OuterTable.className=A?'':'SC_FieldDisabled';};FCKSpecialCombo.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var C=this._OuterTable=A.appendChild(B.createElement('TABLE'));C.cellPadding=0;C.cellSpacing=0;C.insertRow(-1);var D;var E;switch (this.Style){case 0:D='TB_ButtonType_Icon';E=false;break;case 1:D='TB_ButtonType_Text';E=false;break;case 2:E=true;break;};if (this.Caption&&this.Caption.length>0&&E){var F=C.rows[0].insertCell(-1);F.innerHTML=this.Caption;F.className='SC_FieldCaption';};var G=FCKTools.AppendElement(C.rows[0].insertCell(-1),'div');if (E){G.className='SC_Field';G.style.width=this.FieldWidth+'px';G.innerHTML='
     
    ';this._LabelEl=G.getElementsByTagName('label')[0];this._LabelEl.innerHTML=this.Label;}else{G.className='TB_Button_Off';G.innerHTML='
    '+this.Caption+'
    ';};FCKTools.AddEventListenerEx(G,'mouseover',FCKSpecialCombo_OnMouseOver,this);FCKTools.AddEventListenerEx(G,'mouseout',FCKSpecialCombo_OnMouseOut,this);FCKTools.AddEventListenerEx(G,'click',FCKSpecialCombo_OnClick,this);FCKTools.DisableSelection(this._Panel.Document.body);};function FCKSpecialCombo_Cleanup(){this._LabelEl=null;this._OuterTable=null;this._ItemsHolderEl=null;this._PanelBox=null;if (this.Items){for (var A in this.Items) this.Items[A]=null;}};function FCKSpecialCombo_OnMouseOver(A,B){if (B.Enabled){switch (B.Style){case 0:this.className='TB_Button_On_Over';break;case 1:this.className='TB_Button_On_Over';break;case 2:this.className='SC_Field SC_FieldOver';break;}}};function FCKSpecialCombo_OnMouseOut(A,B){switch (B.Style){case 0:this.className='TB_Button_Off';break;case 1:this.className='TB_Button_Off';break;case 2:this.className='SC_Field';break;}};function FCKSpecialCombo_OnClick(e,A){if (A.Enabled){var B=A._Panel;var C=A._PanelBox;var D=A._ItemsHolderEl;var E=A.PanelMaxHeight;if (A.OnBeforeClick) A.OnBeforeClick(A);if (FCKBrowserInfo.IsIE) B.Preload(0,this.offsetHeight,this);if (D.offsetHeight>E) C.style.height=E+'px';else C.style.height='';B.Show(0,this.offsetHeight,this);}}; +var FCKToolbarSpecialCombo=function(){this.SourceView=false;this.ContextSensitive=true;this.FieldWidth=null;this.PanelWidth=null;this.PanelMaxHeight=null;};FCKToolbarSpecialCombo.prototype.DefaultLabel='';function FCKToolbarSpecialCombo_OnSelect(A,B){FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).Execute(A,B);};FCKToolbarSpecialCombo.prototype.Create=function(A){this._Combo=new FCKSpecialCombo(this.GetLabel(),this.FieldWidth,this.PanelWidth,this.PanelMaxHeight,FCKBrowserInfo.IsIE?window:FCKTools.GetElementWindow(A).parent);this._Combo.Tooltip=this.Tooltip;this._Combo.Style=this.Style;this.CreateItems(this._Combo);this._Combo.Create(A);this._Combo.CommandName=this.CommandName;this._Combo.OnSelect=FCKToolbarSpecialCombo_OnSelect;};function FCKToolbarSpecialCombo_RefreshActiveItems(A,B){A.DeselectAll();A.SelectItem(B);A.SetLabelById(B);};FCKToolbarSpecialCombo.prototype.RefreshState=function(){var A;var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (B!=-1){A=1;if (this.RefreshActiveItems) this.RefreshActiveItems(this._Combo,B);else{if (this._LastValue!==B){this._LastValue=B;if (!B||B.length==0){this._Combo.DeselectAll();this._Combo.SetLabel(this.DefaultLabel);}else FCKToolbarSpecialCombo_RefreshActiveItems(this._Combo,B);}}}else A=-1;if (A==this.State) return;if (A==-1){this._Combo.DeselectAll();this._Combo.SetLabel('');};this.State=A;this._Combo.SetEnabled(A!=-1);};FCKToolbarSpecialCombo.prototype.Enable=function(){this.RefreshState();};FCKToolbarSpecialCombo.prototype.Disable=function(){this.State=-1;this._Combo.DeselectAll();this._Combo.SetLabel('');this._Combo.SetEnabled(false);}; +var FCKToolbarStyleCombo=function(A,B){if (A===false) return;this.CommandName='Style';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;this.DefaultLabel=FCKConfig.DefaultStyleLabel||'';};FCKToolbarStyleCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarStyleCombo.prototype.GetLabel=function(){return FCKLang.Style;};FCKToolbarStyleCombo.prototype.GetStyles=function(){var A={};var B=FCK.ToolbarSet.CurrentInstance.Styles.GetStyles();for (var C in B){var D=B[C];if (!D.IsCore) A[C]=D;};return A;};FCKToolbarStyleCombo.prototype.CreateItems=function(A){var B=A._Panel.Document;FCKTools.AppendStyleSheet(B,FCKConfig.ToolbarComboPreviewCSS);FCKTools.AppendStyleString(B,FCKConfig.EditorAreaStyles);B.body.className+=' ForceBaseFont';FCKConfig.ApplyBodyAttributes(B.body);var C=this.GetStyles();for (var D in C){var E=C[D];var F=E.GetType()==2?D:FCKToolbarStyleCombo_BuildPreview(E,E.Label||D);var G=A.AddItem(D,F);G.Style=E;};A.OnBeforeClick=this.StyleCombo_OnBeforeClick;};FCKToolbarStyleCombo.prototype.RefreshActiveItems=function(A){var B=FCK.ToolbarSet.CurrentInstance.Selection.GetBoundaryParentElement(true);if (B){var C=new FCKElementPath(B);var D=C.Elements;for (var e=0;e');var E=A.Element;if (E=='bdo') E='span';D=['<',E];var F=A._StyleDesc.Attributes;if (F){for (var G in F){D.push(' ',G,'="',A.GetFinalAttributeValue(G),'"');}};if (A._GetStyleText().length>0) D.push(' style="',A.GetFinalStyleValue(),'"');D.push('>',B,'');if (C==0) D.push('');return D.join('');}; +var FCKToolbarFontFormatCombo=function(A,B){if (A===false) return;this.CommandName='FontFormat';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;this.NormalLabel='Normal';this.PanelWidth=190;this.DefaultLabel=FCKConfig.DefaultFontFormatLabel||'';};FCKToolbarFontFormatCombo.prototype=new FCKToolbarStyleCombo(false);FCKToolbarFontFormatCombo.prototype.GetLabel=function(){return FCKLang.FontFormat;};FCKToolbarFontFormatCombo.prototype.GetStyles=function(){var A={};var B=FCKLang['FontFormats'].split(';');var C={p:B[0],pre:B[1],address:B[2],h1:B[3],h2:B[4],h3:B[5],h4:B[6],h5:B[7],h6:B[8],div:B[9]||(B[0]+' (DIV)')};var D=FCKConfig.FontFormats.split(';');for (var i=0;iEnable SCAYT';return C?'Disable SCAYT':'Enable SCAYT';};var Z=function(tooltip,style){this.Command=FCKCommands.GetCommand('Scayt');this.CommandName='Scayt';this.Label=this.GetLabel();this.Tooltip=FCKLang.ScaytTitle;this.Style=1;};Z.prototype=new FCKToolbarSpecialCombo;Z.prototype.CreateItems=function(){this._Combo.AddItem('Trigger','Enable SCAYT');this._Combo.AddItem('Options',FCKLang.ScaytTitleOptions||"Options");this._Combo.AddItem('Langs',FCKLang.ScaytTitleLangs||"Languages");this._Combo.AddItem('About',FCKLang.ScaytTitleAbout||"About");};Z.prototype.GetLabel=function(){var a=FCKConfig.SkinPath+'fck_strip.gif';return FCKBrowserInfo.IsIE?'
    ':'';};function ScaytMessage(m){m&&alert(m);};var b=function(){name='ScaytContext';};b.prototype.Execute=function(contextInfo){var c=contextInfo&&contextInfo.action,g=c&&contextInfo.node,Q=window.scayt_control;if (g){switch (c){case 'Suggestion':Q.replace(g,contextInfo.suggestion);break;case 'Ignore':Q.ignore(g);break;case 'Ignore All':Q.ignoreAll(g);break;case 'Add Word':var E=FCK.EditorWindow.parent.parent;E.scayt.addWordToUserDictionary(g);break;}}};function InitSetup(){FCK.ContextMenu.RegisterListener({AddItems:function(menu){var E=FCK.EditorWindow.parent.parent;var Q=window.scayt_control,P=E.scayt;if (!Q) return;var g=Q.getScaytNode();if (!g) return;var h=P.getSuggestion(Q.getWord(g),Q.getLang());if (!h||!h.length) return;menu.AddSeparator();var j=FCK.Config.ScaytMaxSuggestions||5;var k=(j==-1)?h.length:j;for (var i=0;i';G.open();G.write(''+H+''+document.getElementById('xToolbarSpace').innerHTML+'');G.close();if(FCKBrowserInfo.IsAIR) FCKAdobeAIR.ToolbarSet_InitOutFrame(G);FCKTools.AddEventListener(G,'contextmenu',FCKTools.CancelEvent);FCKTools.AppendStyleSheet(G,FCKConfig.SkinEditorCSS);B=D.__FCKToolbarSet=new FCKToolbarSet(G);B._IFrame=F;if (FCK.IECleanup) FCK.IECleanup.AddItem(D,FCKToolbarSet_Target_Cleanup);};B.CurrentInstance=FCK;if (!B.ToolbarItems) B.ToolbarItems=FCKToolbarItems;FCK.AttachToOnSelectionChange(B.RefreshItemsState);return B;};function FCK_OnBlur(A){var B=A.ToolbarSet;if (B.CurrentInstance==A) B.Disable();};function FCK_OnFocus(A){var B=A.ToolbarSet;var C=A||FCK;B.CurrentInstance.FocusManager.RemoveWindow(B._IFrame.contentWindow);B.CurrentInstance=C;C.FocusManager.AddWindow(B._IFrame.contentWindow,true);B.Enable();};function FCKToolbarSet_Cleanup(){this._TargetElement=null;this._IFrame=null;};function FCKToolbarSet_Target_Cleanup(){this.__FCKToolbarSet=null;};var FCKToolbarSet=function(A){this._Document=A;this._TargetElement=A.getElementById('xToolbar');var B=A.getElementById('xExpandHandle');var C=A.getElementById('xCollapseHandle');B.title=FCKLang.ToolbarExpand;FCKTools.AddEventListener(B,'click',FCKToolbarSet_Expand_OnClick);C.title=FCKLang.ToolbarCollapse;FCKTools.AddEventListener(C,'click',FCKToolbarSet_Collapse_OnClick);if (!FCKConfig.ToolbarCanCollapse||FCKConfig.ToolbarStartExpanded) this.Expand();else this.Collapse();C.style.display=FCKConfig.ToolbarCanCollapse?'':'none';if (FCKConfig.ToolbarCanCollapse) C.style.display='';else A.getElementById('xTBLeftBorder').style.display='';this.Toolbars=[];this.IsLoaded=false;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarSet_Cleanup);};function FCKToolbarSet_Expand_OnClick(){FCK.ToolbarSet.Expand();};function FCKToolbarSet_Collapse_OnClick(){FCK.ToolbarSet.Collapse();};FCKToolbarSet.prototype.Expand=function(){this._ChangeVisibility(false);};FCKToolbarSet.prototype.Collapse=function(){this._ChangeVisibility(true);};FCKToolbarSet.prototype._ChangeVisibility=function(A){this._Document.getElementById('xCollapsed').style.display=A?'':'none';this._Document.getElementById('xExpanded').style.display=A?'none':'';if (window.onresize){FCKTools.RunFunction(window.onresize);}};FCKToolbarSet.prototype.Load=function(A){this.Name=A;this.Items=[];this.ItemsWysiwygOnly=[];this.ItemsContextSensitive=[];this._TargetElement.innerHTML='';var B=FCKConfig.ToolbarSets[A];if (!B){alert(FCKLang.UnknownToolbarSet.replace(/%1/g,A));return;};this.Toolbars=[];for (var x=0;x0) break;}catch (e){break;};D=D.parent;};var E=D.document;var F=function(){if (!B) B=FCKConfig.FloatingPanelsZIndex+999;return++B;};var G=function(){if (!C) return;var H=FCKTools.IsStrictMode(E)?E.documentElement:E.body;FCKDomTools.SetElementStyles(C,{'width':Math.max(H.scrollWidth,H.clientWidth,E.scrollWidth||0)-1+'px','height':Math.max(H.scrollHeight,H.clientHeight,E.scrollHeight||0)-1+'px'});};return {OpenDialog:function(dialogName,dialogTitle,dialogPage,width,height,customValue,resizable){if (!A) this.DisplayMainCover();var I={Title:dialogTitle,Page:dialogPage,Editor:window,CustomValue:customValue,TopWindow:D};FCK.ToolbarSet.CurrentInstance.Selection.Save(true);var J=FCKTools.GetViewPaneSize(D);var K={ 'X':0,'Y':0 };var L=FCKBrowserInfo.IsIE&&(!FCKBrowserInfo.IsIE7||!FCKTools.IsStrictMode(D.document));if (L) K=FCKTools.GetScrollPosition(D);var M=Math.max(K.Y+(J.Height-height-20)/2,0);var N=Math.max(K.X+(J.Width-width-20)/2,0);var O=E.createElement('iframe');FCKTools.ResetStyles(O);O.src=FCKConfig.BasePath+'fckdialog.html';O.frameBorder=0;O.allowTransparency=true;FCKDomTools.SetElementStyles(O,{'position':(L)?'absolute':'fixed','top':M+'px','left':N+'px','width':width+'px','height':height+'px','zIndex':F()});O._DialogArguments=I;E.body.appendChild(O);O._ParentDialog=A;A=O;},OnDialogClose:function(dialogWindow){var O=dialogWindow.frameElement;FCKDomTools.RemoveNode(O);if (O._ParentDialog){A=O._ParentDialog;O._ParentDialog.contentWindow.SetEnabled(true);}else{if (!FCKBrowserInfo.IsIE) FCK.Focus();this.HideMainCover();setTimeout(function(){ A=null;},0);FCK.ToolbarSet.CurrentInstance.Selection.Release();}},DisplayMainCover:function(){C=E.createElement('div');FCKTools.ResetStyles(C);FCKDomTools.SetElementStyles(C,{'position':'absolute','zIndex':F(),'top':'0px','left':'0px','backgroundColor':FCKConfig.BackgroundBlockerColor});FCKDomTools.SetOpacity(C,FCKConfig.BackgroundBlockerOpacity);if (FCKBrowserInfo.IsIE&&!FCKBrowserInfo.IsIE7){var Q=E.createElement('iframe');FCKTools.ResetStyles(Q);Q.hideFocus=true;Q.frameBorder=0;Q.src=FCKTools.GetVoidUrl();FCKDomTools.SetElementStyles(Q,{'width':'100%','height':'100%','position':'absolute','left':'0px','top':'0px','filter':'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'});C.appendChild(Q);};FCKTools.AddEventListener(D,'resize',G);G();E.body.appendChild(C);FCKFocusManager.Lock();var R=FCK.ToolbarSet.CurrentInstance.GetInstanceObject('frameElement');R._fck_originalTabIndex=R.tabIndex;R.tabIndex=-1;},HideMainCover:function(){FCKDomTools.RemoveNode(C);FCKFocusManager.Unlock();var R=FCK.ToolbarSet.CurrentInstance.GetInstanceObject('frameElement');R.tabIndex=R._fck_originalTabIndex;FCKDomTools.ClearElementJSProperty(R,'_fck_originalTabIndex');},GetCover:function(){return C;}};})(); +var FCKMenuItem=function(A,B,C,D,E,F){this.Name=B;this.Label=C||B;this.IsDisabled=E;this.Icon=new FCKIcon(D);this.SubMenu=new FCKMenuBlockPanel();this.SubMenu.Parent=A;this.SubMenu.OnClick=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnClick,this);this.CustomData=F;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuItem_Cleanup);};FCKMenuItem.prototype.AddItem=function(A,B,C,D,E){this.HasSubMenu=true;return this.SubMenu.AddItem(A,B,C,D,E);};FCKMenuItem.prototype.AddSeparator=function(){this.SubMenu.AddSeparator();};FCKMenuItem.prototype.Create=function(A){var B=this.HasSubMenu;var C=FCKTools.GetElementDocument(A);var r=this.MainElement=A.insertRow(-1);r.className=this.IsDisabled?'MN_Item_Disabled':'MN_Item';if (!this.IsDisabled){FCKTools.AddEventListenerEx(r,'mouseover',FCKMenuItem_OnMouseOver,[this]);FCKTools.AddEventListenerEx(r,'click',FCKMenuItem_OnClick,[this]);if (!B) FCKTools.AddEventListenerEx(r,'mouseout',FCKMenuItem_OnMouseOut,[this]);};var D=r.insertCell(-1);D.className='MN_Icon';D.appendChild(this.Icon.CreateIconElement(C));D=r.insertCell(-1);D.className='MN_Label';D.noWrap=true;D.appendChild(C.createTextNode(this.Label));D=r.insertCell(-1);if (B){D.className='MN_Arrow';var E=D.appendChild(C.createElement('IMG'));E.src=FCK_IMAGES_PATH+'arrow_'+FCKLang.Dir+'.gif';E.width=4;E.height=7;this.SubMenu.Create();this.SubMenu.Panel.OnHide=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnHide,this);}};FCKMenuItem.prototype.Activate=function(){this.MainElement.className='MN_Item_Over';if (this.HasSubMenu){this.SubMenu.Show(this.MainElement.offsetWidth+2,-2,this.MainElement);};FCKTools.RunFunction(this.OnActivate,this);};FCKMenuItem.prototype.Deactivate=function(){this.MainElement.className='MN_Item';if (this.HasSubMenu) this.SubMenu.Hide();};function FCKMenuItem_SubMenu_OnClick(A,B){FCKTools.RunFunction(B.OnClick,B,[A]);};function FCKMenuItem_SubMenu_OnHide(A){A.Deactivate();};function FCKMenuItem_OnClick(A,B){if (B.HasSubMenu) B.Activate();else{B.Deactivate();FCKTools.RunFunction(B.OnClick,B,[B]);}};function FCKMenuItem_OnMouseOver(A,B){B.Activate();};function FCKMenuItem_OnMouseOut(A,B){B.Deactivate();};function FCKMenuItem_Cleanup(){this.MainElement=null;}; +var FCKMenuBlock=function(){this._Items=[];};FCKMenuBlock.prototype.Count=function(){return this._Items.length;};FCKMenuBlock.prototype.AddItem=function(A,B,C,D,E){var F=new FCKMenuItem(this,A,B,C,D,E);F.OnClick=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnClick,this);F.OnActivate=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnActivate,this);this._Items.push(F);return F;};FCKMenuBlock.prototype.AddSeparator=function(){this._Items.push(new FCKMenuSeparator());};FCKMenuBlock.prototype.RemoveAllItems=function(){this._Items=[];var A=this._ItemsTable;if (A){while (A.rows.length>0) A.deleteRow(0);}};FCKMenuBlock.prototype.Create=function(A){if (!this._ItemsTable){if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuBlock_Cleanup);this._Window=FCKTools.GetElementWindow(A);var B=FCKTools.GetElementDocument(A);var C=A.appendChild(B.createElement('table'));C.cellPadding=0;C.cellSpacing=0;FCKTools.DisableSelection(C);var D=C.insertRow(-1).insertCell(-1);D.className='MN_Menu';var E=this._ItemsTable=D.appendChild(B.createElement('table'));E.cellPadding=0;E.cellSpacing=0;};for (var i=0;i0&&F.href.length==0);if (G) return;menu.AddSeparator();menu.AddItem('VisitLink',FCKLang.VisitLink);menu.AddSeparator();if (E) menu.AddItem('Link',FCKLang.EditLink,34);menu.AddItem('Unlink',FCKLang.RemoveLink,35);}}};case 'Image':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&!tag.getAttribute('_fckfakelement')){menu.AddSeparator();menu.AddItem('Image',FCKLang.ImageProperties,37);}}};case 'Anchor':return {AddItems:function(menu,tag,tagName){var F=FCKSelection.MoveToAncestorNode('A');var G=(F&&F.name.length>0);if (G||(tagName=='IMG'&&tag.getAttribute('_fckanchor'))){menu.AddSeparator();menu.AddItem('Anchor',FCKLang.AnchorProp,36);menu.AddItem('AnchorDelete',FCKLang.AnchorDelete);}}};case 'Flash':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckflash')){menu.AddSeparator();menu.AddItem('Flash',FCKLang.FlashProperties,38);}}};case 'Form':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('FORM')){menu.AddSeparator();menu.AddItem('Form',FCKLang.FormProp,48);}}};case 'Checkbox':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='checkbox'){menu.AddSeparator();menu.AddItem('Checkbox',FCKLang.CheckboxProp,49);}}};case 'Radio':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='radio'){menu.AddSeparator();menu.AddItem('Radio',FCKLang.RadioButtonProp,50);}}};case 'TextField':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='text'||tag.type=='password')){menu.AddSeparator();menu.AddItem('TextField',FCKLang.TextFieldProp,51);}}};case 'HiddenField':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckinputhidden')){menu.AddSeparator();menu.AddItem('HiddenField',FCKLang.HiddenFieldProp,56);}}};case 'ImageButton':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='image'){menu.AddSeparator();menu.AddItem('ImageButton',FCKLang.ImageButtonProp,55);}}};case 'Button':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='button'||tag.type=='submit'||tag.type=='reset')){menu.AddSeparator();menu.AddItem('Button',FCKLang.ButtonProp,54);}}};case 'Select':return {AddItems:function(menu,tag,tagName){if (tagName=='SELECT'){menu.AddSeparator();menu.AddItem('Select',FCKLang.SelectionFieldProp,53);}}};case 'Textarea':return {AddItems:function(menu,tag,tagName){if (tagName=='TEXTAREA'){menu.AddSeparator();menu.AddItem('Textarea',FCKLang.TextareaProp,52);}}};case 'BulletedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('UL')){menu.AddSeparator();menu.AddItem('BulletedList',FCKLang.BulletedListProp,27);}}};case 'NumberedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('OL')){menu.AddSeparator();menu.AddItem('NumberedList',FCKLang.NumberedListProp,26);}}};case 'DivContainer':return {AddItems:function(menu,tag,tagName){var J=FCKDomTools.GetSelectedDivContainers();if (J.length>0){menu.AddSeparator();menu.AddItem('EditDiv',FCKLang.EditDiv,75);menu.AddItem('DeleteDiv',FCKLang.DeleteDiv,76);}}};};return null;};function FCK_ContextMenu_OnBeforeOpen(){FCK.Events.FireEvent('OnSelectionChange');var A,sTagName;if ((A=FCKSelection.GetSelectedElement())) sTagName=A.tagName;var B=FCK.ContextMenu._InnerContextMenu;B.RemoveAllItems();var C=FCK.ContextMenu.Listeners;for (var i=0;i0){D=A.substr(0,B.index);this._sourceHtml=A.substr(B.index);}else{C=true;D=B[0];this._sourceHtml=A.substr(B[0].length);}}else{D=A;this._sourceHtml=null;};return { 'isTag':C,'value':D };},Each:function(A){var B;while ((B=this.Next())) A(B.isTag,B.value);}};var FCKHtmlIterator=function(A){this._sourceHtml=A;};FCKHtmlIterator.prototype={Next:function(){var A=this._sourceHtml;if (A==null) return null;var B=FCKRegexLib.HtmlTag.exec(A);var C=false;var D="";if (B){if (B.index>0){D=A.substr(0,B.index);this._sourceHtml=A.substr(B.index);}else{C=true;D=B[0];this._sourceHtml=A.substr(B[0].length);}}else{D=A;this._sourceHtml=null;};return { 'isTag':C,'value':D };},Each:function(A){var B;while ((B=this.Next())) A(B.isTag,B.value);}}; +var FCKPlugin=function(A,B,C){this.Name=A;this.BasePath=C?C:FCKConfig.PluginsPath;this.Path=this.BasePath+A+'/';if (!B||B.length==0) this.AvailableLangs=[];else this.AvailableLangs=B.split(',');};FCKPlugin.prototype.Load=function(){if (this.AvailableLangs.length>0){var A;if (this.AvailableLangs.IndexOf(FCKLanguageManager.ActiveLanguage.Code)>=0) A=FCKLanguageManager.ActiveLanguage.Code;else A=this.AvailableLangs[0];LoadScript(this.Path+'lang/'+A+'.js');};LoadScript(this.Path+'fckplugin.js');}; +var FCKPlugins=FCK.Plugins={};FCKPlugins.ItemsCount=0;FCKPlugins.Items={};FCKPlugins.Load=function(){var A=FCKPlugins.Items;for (var i=0;i", +DlgInfoTab : "Info", +DlgAlertUrl : "Voeg asseblief die URL in", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Taal rigting", +DlgGenLangDirLtr : "Links na regs (LTR)", +DlgGenLangDirRtl : "Regs na links (RTL)", +DlgGenLangCode : "Taal kode", +DlgGenAccessKey : "Toegang sleutel", +DlgGenName : "Naam", +DlgGenTabIndex : "Tab Index", +DlgGenLongDescr : "Lang beskreiwing URL", +DlgGenClass : "Skakel Tiepe", +DlgGenTitle : "Voorbeveelings Titel", +DlgGenContType : "Voorbeveelings inhoud soort", +DlgGenLinkCharset : "Geskakelde voorbeeld karakterstel", +DlgGenStyle : "Styl", + +// Image Dialog +DlgImgTitle : "Beeld eienskappe", +DlgImgInfoTab : "Beeld informasie", +DlgImgBtnUpload : "Stuur dit na die Server", +DlgImgURL : "URL", +DlgImgUpload : "Uplaai", +DlgImgAlt : "Alternatiewe beskrywing", +DlgImgWidth : "Weidte", +DlgImgHeight : "Hoogde", +DlgImgLockRatio : "Behou preporsie", +DlgBtnResetSize : "Herstel groote", +DlgImgBorder : "Kant", +DlgImgHSpace : "HSpasie", +DlgImgVSpace : "VSpasie", +DlgImgAlign : "Paradeer", +DlgImgAlignLeft : "Links", +DlgImgAlignAbsBottom: "Abs Onder", +DlgImgAlignAbsMiddle: "Abs Middel", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Onder", +DlgImgAlignMiddle : "Middel", +DlgImgAlignRight : "Regs", +DlgImgAlignTextTop : "Text Bo", +DlgImgAlignTop : "Bo", +DlgImgPreview : "Voorskou", +DlgImgAlertUrl : "Voeg asseblief Beeld URL in.", +DlgImgLinkTab : "Skakel", + +// Flash Dialog +DlgFlashTitle : "Flash eienskappe", +DlgFlashChkPlay : "Automaties Speel", +DlgFlashChkLoop : "Herhaling", +DlgFlashChkMenu : "Laat Flash Menu toe", +DlgFlashScale : "Scale", +DlgFlashScaleAll : "Wys alles", +DlgFlashScaleNoBorder : "Geen kante", +DlgFlashScaleFit : "Presiese pas", + +// Link Dialog +DlgLnkWindowTitle : "Skakel", +DlgLnkInfoTab : "Skakel informasie", +DlgLnkTargetTab : "Mikpunt", + +DlgLnkType : "Skakel soort", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Skakel na plekhouers in text", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protokol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Kies 'n plekhouer", +DlgLnkAnchorByName : "Volgens plekhouer naam", +DlgLnkAnchorById : "Volgens element Id", +DlgLnkNoAnchors : "(Geen plekhouers beskikbaar in dokument}", +DlgLnkEMail : "E-Mail Adres", +DlgLnkEMailSubject : "Boodskap Opskrif", +DlgLnkEMailBody : "Boodskap Inhoud", +DlgLnkUpload : "Oplaai", +DlgLnkBtnUpload : "Stuur na Server", + +DlgLnkTarget : "Mikpunt", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nuwe Venster (_blank)", +DlgLnkTargetParent : "Vorige Venster (_parent)", +DlgLnkTargetSelf : "Selfde Venster (_self)", +DlgLnkTargetTop : "Boonste Venster (_top)", +DlgLnkTargetFrameName : "Mikpunt Venster Naam", +DlgLnkPopWinName : "Popup Venster Naam", +DlgLnkPopWinFeat : "Popup Venster Geaartheid", +DlgLnkPopResize : "Verstelbare Groote", +DlgLnkPopLocation : "Adres Balk", +DlgLnkPopMenu : "Menu Balk", +DlgLnkPopScroll : "Gleibalkstuk", +DlgLnkPopStatus : "Status Balk", +DlgLnkPopToolbar : "Gereedskap Balk", +DlgLnkPopFullScrn : "Voll Skerm (IE)", +DlgLnkPopDependent : "Afhanklik (Netscape)", +DlgLnkPopWidth : "Weite", +DlgLnkPopHeight : "Hoogde", +DlgLnkPopLeft : "Links Posisie", +DlgLnkPopTop : "Bo Posisie", + +DlnLnkMsgNoUrl : "Voeg asseblief die URL in", +DlnLnkMsgNoEMail : "Voeg asseblief die e-mail adres in", +DlnLnkMsgNoAnchor : "Kies asseblief 'n plekhouer", +DlnLnkMsgInvPopName : "Die popup naam moet begin met alphabetiese karakters sonder spasies.", + +// Color Dialog +DlgColorTitle : "Kies Kleur", +DlgColorBtnClear : "Maak skoon", +DlgColorHighlight : "Highlight", +DlgColorSelected : "Geselekteer", + +// Smiley Dialog +DlgSmileyTitle : "Voeg Smiley by", + +// Special Character Dialog +DlgSpecialCharTitle : "Kies spesiale karakter", + +// Table Dialog +DlgTableTitle : "Tabel eienskappe", +DlgTableRows : "Reie", +DlgTableColumns : "Kolome", +DlgTableBorder : "Kant groote", +DlgTableAlign : "Parideering", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Links", +DlgTableAlignCenter : "Middel", +DlgTableAlignRight : "Regs", +DlgTableWidth : "Weite", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "percent", +DlgTableHeight : "Hoogde", +DlgTableCellSpace : "Cell spasieering", +DlgTableCellPad : "Cell buffer", +DlgTableCaption : "Beskreiwing", +DlgTableSummary : "Opsomming", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Cell eienskappe", +DlgCellWidth : "Weite", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "percent", +DlgCellHeight : "Hoogde", +DlgCellWordWrap : "Woord Wrap", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Ja", +DlgCellWordWrapNo : "Nee", +DlgCellHorAlign : "Horisontale rigting", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Links", +DlgCellHorAlignCenter : "Middel", +DlgCellHorAlignRight: "Regs", +DlgCellVerAlign : "Vertikale rigting", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Bo", +DlgCellVerAlignMiddle : "Middel", +DlgCellVerAlignBottom : "Onder", +DlgCellVerAlignBaseline : "Baseline", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Rei strekking", +DlgCellCollSpan : "Kolom strekking", +DlgCellBackColor : "Agtergrond Kleur", +DlgCellBorderColor : "Kant Kleur", +DlgCellBtnSelect : "Keuse...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "Vind", +DlgFindFindBtn : "Vind", +DlgFindNotFoundMsg : "Die gespesifiseerde karakters word nie gevind nie.", + +// Replace Dialog +DlgReplaceTitle : "Vervang", +DlgReplaceFindLbl : "Soek wat:", +DlgReplaceReplaceLbl : "Vervang met:", +DlgReplaceCaseChk : "Vergelyk karakter skryfweise", +DlgReplaceReplaceBtn : "Vervang", +DlgReplaceReplAllBtn : "Vervang alles", +DlgReplaceWordChk : "Vergelyk komplete woord", + +// Paste Operations / Dialog +PasteErrorCut : "U browser se sekuriteit instelling behinder die uitsny aksie. Gebruik asseblief die sleutel kombenasie(Ctrl+X).", +PasteErrorCopy : "U browser se sekuriteit instelling behinder die kopieerings aksie. Gebruik asseblief die sleutel kombenasie(Ctrl+C).", + +PasteAsText : "Voeg slegs karakters by", +PasteFromWord : "Byvoeging uit Word", + +DlgPasteMsg2 : "Voeg asseblief die inhoud in die gegewe box by met sleutel kombenasie(Ctrl+V) en druk OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "Ignoreer karakter soort defenisies", +DlgPasteRemoveStyles : "Verweider Styl defenisies", + +// Color Picker +ColorAutomatic : "Automaties", +ColorMoreColors : "Meer Kleure...", + +// Document Properties +DocProps : "Dokument Eienskappe", + +// Anchor Dialog +DlgAnchorTitle : "Plekhouer Eienskappe", +DlgAnchorName : "Plekhouer Naam", +DlgAnchorErrorName : "Voltooi die plekhouer naam asseblief", + +// Speller Pages Dialog +DlgSpellNotInDic : "Nie in woordeboek nie", +DlgSpellChangeTo : "Verander na", +DlgSpellBtnIgnore : "Ignoreer", +DlgSpellBtnIgnoreAll : "Ignoreer na-volgende", +DlgSpellBtnReplace : "Vervang", +DlgSpellBtnReplaceAll : "vervang na-volgende", +DlgSpellBtnUndo : "Ont-skep", +DlgSpellNoSuggestions : "- Geen voorstel -", +DlgSpellProgress : "Spelling word beproef...", +DlgSpellNoMispell : "Spellproef kompleet: Geen foute", +DlgSpellNoChanges : "Spellproef kompleet: Geen woord veranderings", +DlgSpellOneChange : "Spellproef kompleet: Een woord verander", +DlgSpellManyChanges : "Spellproef kompleet: %1 woorde verander", + +IeSpellDownload : "Geen Spellproefer geinstaleer nie. Wil U dit aflaai?", + +// Button Dialog +DlgButtonText : "Karakters (Waarde)", +DlgButtonType : "Soort", +DlgButtonTypeBtn : "Knop", +DlgButtonTypeSbm : "Indien", +DlgButtonTypeRst : "Reset", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Naam", +DlgCheckboxValue : "Waarde", +DlgCheckboxSelected : "Uitgekies", + +// Form Dialog +DlgFormName : "Naam", +DlgFormAction : "Aksie", +DlgFormMethod : "Metode", + +// Select Field Dialog +DlgSelectName : "Naam", +DlgSelectValue : "Waarde", +DlgSelectSize : "Grote", +DlgSelectLines : "lyne", +DlgSelectChkMulti : "Laat meerere keuses toe", +DlgSelectOpAvail : "Beskikbare Opsies", +DlgSelectOpText : "Karakters", +DlgSelectOpValue : "Waarde", +DlgSelectBtnAdd : "Byvoeg", +DlgSelectBtnModify : "Verander", +DlgSelectBtnUp : "Op", +DlgSelectBtnDown : "Af", +DlgSelectBtnSetValue : "Stel as uitgekiesde waarde", +DlgSelectBtnDelete : "Verweider", + +// Textarea Dialog +DlgTextareaName : "Naam", +DlgTextareaCols : "Kolom", +DlgTextareaRows : "Reie", + +// Text Field Dialog +DlgTextName : "Naam", +DlgTextValue : "Waarde", +DlgTextCharWidth : "Karakter weite", +DlgTextMaxChars : "Maximale karakters", +DlgTextType : "Soort", +DlgTextTypeText : "Karakters", +DlgTextTypePass : "Wagwoord", + +// Hidden Field Dialog +DlgHiddenName : "Naam", +DlgHiddenValue : "Waarde", + +// Bulleted List Dialog +BulletedListProp : "Gepunkte lys eienskappe", +NumberedListProp : "Genommerde lys eienskappe", +DlgLstStart : "Begin", +DlgLstType : "Soort", +DlgLstTypeCircle : "Sirkel", +DlgLstTypeDisc : "Skyf", +DlgLstTypeSquare : "Vierkant", +DlgLstTypeNumbers : "Nommer (1, 2, 3)", +DlgLstTypeLCase : "Klein Letters (a, b, c)", +DlgLstTypeUCase : "Hoof Letters (A, B, C)", +DlgLstTypeSRoman : "Klein Romeinse nommers (i, ii, iii)", +DlgLstTypeLRoman : "Groot Romeinse nommers (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Algemeen", +DlgDocBackTab : "Agtergrond", +DlgDocColorsTab : "Kleure en Rante", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Bladsy Opskrif", +DlgDocLangDir : "Taal rigting", +DlgDocLangDirLTR : "Link na Regs (LTR)", +DlgDocLangDirRTL : "Regs na Links (RTL)", +DlgDocLangCode : "Taal Kode", +DlgDocCharSet : "Karakterstel Kodeering", +DlgDocCharSetCE : "Sentraal Europa", +DlgDocCharSetCT : "Chinees Traditioneel (Big5)", +DlgDocCharSetCR : "Cyrillic", +DlgDocCharSetGR : "Grieks", +DlgDocCharSetJP : "Japanees", +DlgDocCharSetKR : "Koreans", +DlgDocCharSetTR : "Turks", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Western European", +DlgDocCharSetOther : "Ander Karakterstel Kodeering", + +DlgDocDocType : "Dokument Opskrif Soort", +DlgDocDocTypeOther : "Ander Dokument Opskrif Soort", +DlgDocIncXHTML : "Voeg XHTML verklaring by", +DlgDocBgColor : "Agtergrond kleur", +DlgDocBgImage : "Agtergrond Beeld URL", +DlgDocBgNoScroll : "Vasgeklemde Agtergrond", +DlgDocCText : "Karakters", +DlgDocCLink : "Skakel", +DlgDocCVisited : "Besoekte Skakel", +DlgDocCActive : "Aktiewe Skakel", +DlgDocMargins : "Bladsy Rante", +DlgDocMaTop : "Bo", +DlgDocMaLeft : "Links", +DlgDocMaRight : "Regs", +DlgDocMaBottom : "Onder", +DlgDocMeIndex : "Dokument Index Sleutelwoorde(comma verdeelt)", +DlgDocMeDescr : "Dokument Beskrywing", +DlgDocMeAuthor : "Skrywer", +DlgDocMeCopy : "Kopiereg", +DlgDocPreview : "Voorskou", + +// Templates Dialog +Templates : "Templates", +DlgTemplatesTitle : "Inhoud Templates", +DlgTemplatesSelMsg : "Kies die template om te gebruik in die editor
    (Inhoud word vervang!):", +DlgTemplatesLoading : "Templates word gelaai. U geduld asseblief...", +DlgTemplatesNoTpl : "(Geen templates gedefinieerd)", +DlgTemplatesReplace : "Vervang bestaande inhoud", + +// About Dialog +DlgAboutAboutTab : "Meer oor", +DlgAboutBrowserInfoTab : "Blaai Informasie deur", +DlgAboutLicenseTab : "Lesensie", +DlgAboutVersion : "weergawe", +DlgAboutInfo : "Vir meer informasie gaan na ", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/ar.js b/www/js/FCKeditor/editor/lang/ar.js new file mode 100644 index 0000000..622c632 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/ar.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Arabic language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "rtl", + +ToolbarCollapse : "ضم شريط الأدوات", +ToolbarExpand : "تمدد شريط الأدوات", + +// Toolbar Items and Context Menu +Save : "Ø­Ùظ", +NewPage : "صÙحة جديدة", +Preview : "معاينة الصÙحة", +Cut : "قص", +Copy : "نسخ", +Paste : "لصق", +PasteText : "لصق كنص بسيط", +PasteWord : "لصق من وورد", +Print : "طباعة", +SelectAll : "تحديد الكل", +RemoveFormat : "إزالة التنسيقات", +InsertLinkLbl : "رابط", +InsertLink : "إدراج/تحرير رابط", +RemoveLink : "إزالة رابط", +VisitLink : "اÙتح الرابط", +Anchor : "إدراج/تحرير إشارة مرجعية", +AnchorDelete : "إزالة إشارة مرجعية", +InsertImageLbl : "صورة", +InsertImage : "إدراج/تحرير صورة", +InsertFlashLbl : "Ùلاش", +InsertFlash : "إدراج/تحرير Ùيلم Ùلاش", +InsertTableLbl : "جدول", +InsertTable : "إدراج/تحرير جدول", +InsertLineLbl : "خط Ùاصل", +InsertLine : "إدراج خط Ùاصل", +InsertSpecialCharLbl: "رموز", +InsertSpecialChar : "إدراج رموز..Ù", +InsertSmileyLbl : "ابتسامات", +InsertSmiley : "إدراج ابتسامات", +About : "حول FCKeditor", +Bold : "غامق", +Italic : "مائل", +Underline : "تسطير", +StrikeThrough : "يتوسطه خط", +Subscript : "منخÙض", +Superscript : "مرتÙع", +LeftJustify : "محاذاة إلى اليسار", +CenterJustify : "توسيط", +RightJustify : "محاذاة إلى اليمين", +BlockJustify : "ضبط", +DecreaseIndent : "إنقاص المساÙØ© البادئة", +IncreaseIndent : "زيادة المساÙØ© البادئة", +Blockquote : "اقتباس", +CreateDiv : "إنشاء حاوية Div", +EditDiv : "تعديل حاوية Div", +DeleteDiv : "إزالة حاوية Div", +Undo : "تراجع", +Redo : "إعادة", +NumberedListLbl : "تعداد رقمي", +NumberedList : "إدراج/إلغاء تعداد رقمي", +BulletedListLbl : "تعداد نقطي", +BulletedList : "إدراج/إلغاء تعداد نقطي", +ShowTableBorders : "معاينة حدود الجداول", +ShowDetails : "معاينة التÙاصيل", +Style : "نمط", +FontFormat : "تنسيق", +Font : "خط", +FontSize : "حجم الخط", +TextColor : "لون النص", +BGColor : "لون الخلÙية", +Source : "Ø´Ùرة المصدر", +Find : "بحث", +Replace : "إستبدال", +SpellCheck : "تدقيق إملائي", +UniversalKeyboard : "لوحة المÙاتيح العالمية", +PageBreakLbl : "Ùصل الصÙحة", +PageBreak : "إدخال صÙحة جديدة", + +Form : "نموذج", +Checkbox : "خانة إختيار", +RadioButton : "زر خيار", +TextField : "مربع نص", +Textarea : "ناحية نص", +HiddenField : "إدراج حقل Ø®ÙÙŠ", +Button : "زر ضغط", +SelectionField : "قائمة منسدلة", +ImageButton : "زر صورة", + +FitWindow : "تكبير حجم المحرر", +ShowBlocks : "مخطط تÙصيلي", + +// Context Menu +EditLink : "تحرير رابط", +CellCM : "خلية", +RowCM : "صÙ", +ColumnCM : "عمود", +InsertRowAfter : "إدراج ص٠بعد", +InsertRowBefore : "إدراج ص٠قبل", +DeleteRows : "حذ٠صÙÙˆÙ", +InsertColumnAfter : "إدراج عمود بعد", +InsertColumnBefore : "إدراج عمود قبل", +DeleteColumns : "حذ٠أعمدة", +InsertCellAfter : "إدراج خلية بعد", +InsertCellBefore : "إدراج خلية قبل", +DeleteCells : "حذ٠خلايا", +MergeCells : "دمج خلايا", +MergeRight : "دمج لليمين", +MergeDown : "دمج للأسÙÙ„", +HorizontalSplitCell : "تقسيم الخلية Ø£Ùقياً", +VerticalSplitCell : "تقسيم الخلية عمودياً", +TableDelete : "حذ٠الجدول", +CellProperties : "خصائص الخلية", +TableProperties : "خصائص الجدول", +ImageProperties : "خصائص الصورة", +FlashProperties : "خصائص Ùيلم الÙلاش", + +AnchorProp : "خصائص الإشارة المرجعية", +ButtonProp : "خصائص زر الضغط", +CheckboxProp : "خصائص خانة الإختيار", +HiddenFieldProp : "خصائص الحقل الخÙÙŠ", +RadioButtonProp : "خصائص زر الخيار", +ImageButtonProp : "خصائص زر الصورة", +TextFieldProp : "خصائص مربع النص", +SelectionFieldProp : "خصائص القائمة المنسدلة", +TextareaProp : "خصائص ناحية النص", +FormProp : "خصائص النموذج", + +FontFormats : "عادي;منسّق;دوس;العنوان 1;العنوان 2;العنوان 3;العنوان 4;العنوان 5;العنوان 6", + +// Alerts and Messages +ProcessingXHTML : "إنتظر قليلاً ريثما تتم معالَجة†XHTML. لن يستغرق طويلاً...", +Done : "تم", +PasteWordConfirm : "يبدو أن النص المراد لصقه منسوخ من برنامج وورد. هل تود تنظيÙÙ‡ قبل الشروع ÙÙŠ عملية اللصق؟", +NotCompatiblePaste : "هذه الميزة تحتاج لمتصÙØ­ من النوعInternet Explorer إصدار 5.5 Ùما Ùوق. هل تود اللصق دون تنظي٠الكود؟", +UnknownToolbarItem : "عنصر شريط أدوات غير معرو٠\"%1\"", +UnknownCommand : "أمر غير معرو٠\"%1\"", +NotImplemented : "لم يتم دعم هذا الأمر", +UnknownToolbarSet : "لم أتمكن من العثور على طقم الأدوات \"%1\" ", +NoActiveX : "لتأمين متصÙحك يجب أن تحدد بعض مميزات المحرر. يتوجب عليك تمكين الخيار \"Run ActiveX controls and plug-ins\". قد تواجة أخطاء وتلاحظ مميزات Ù…Ùقودة", +BrowseServerBlocked : "لايمكن Ùتح مصدر المتصÙØ­. Ùضلا يجب التأكد بأن جميع موانع النواÙØ° المنبثقة معطلة", +DialogBlocked : "لايمكن Ùتح ناÙذة الحوار . Ùضلا تأكد من أن مانع النواÙØ° المنبثة معطل .", +VisitLinkBlocked : "لا يمكن Ùتح ناÙذة جديدة. تأكد من إيقا٠كل مانعي Ùتح النواÙØ° من العمل.", + +// Dialogs +DlgBtnOK : "مواÙÙ‚", +DlgBtnCancel : "إلغاء الأمر", +DlgBtnClose : "إغلاق", +DlgBtnBrowseServer : "تصÙØ­ الخادم", +DlgAdvancedTag : "متقدم", +DlgOpOther : "<أخرى>", +DlgInfoTab : "معلومات", +DlgAlertUrl : "الرجاء كتابة عنوان الإنترنت", + +// General Dialogs Labels +DlgGenNotSet : "<بدون تحديد>", +DlgGenId : "الرقم", +DlgGenLangDir : "إتجاه النص", +DlgGenLangDirLtr : "اليسار لليمين (LTR)", +DlgGenLangDirRtl : "اليمين لليسار (RTL)", +DlgGenLangCode : "رمز اللغة", +DlgGenAccessKey : "Ù…Ùاتيح الإختصار", +DlgGenName : "الاسم", +DlgGenTabIndex : "الترتيب", +DlgGenLongDescr : "عنوان الوص٠المÙصّل", +DlgGenClass : "Ùئات التنسيق", +DlgGenTitle : "تلميح الشاشة", +DlgGenContType : "نوع التلميح", +DlgGenLinkCharset : "ترميز المادة المطلوبة", +DlgGenStyle : "نمط", + +// Image Dialog +DlgImgTitle : "خصائص الصورة", +DlgImgInfoTab : "معلومات الصورة", +DlgImgBtnUpload : "أرسلها للخادم", +DlgImgURL : "موقع الصورة", +DlgImgUpload : "رÙع", +DlgImgAlt : "الوصÙ", +DlgImgWidth : "العرض", +DlgImgHeight : "الإرتÙاع", +DlgImgLockRatio : "تناسق الحجم", +DlgBtnResetSize : "إستعادة الحجم الأصلي", +DlgImgBorder : "سمك الحدود", +DlgImgHSpace : "تباعد Ø£Ùقي", +DlgImgVSpace : "تباعد عمودي", +DlgImgAlign : "محاذاة", +DlgImgAlignLeft : "يسار", +DlgImgAlignAbsBottom: "أسÙÙ„ النص", +DlgImgAlignAbsMiddle: "وسط السطر", +DlgImgAlignBaseline : "على السطر", +DlgImgAlignBottom : "أسÙÙ„", +DlgImgAlignMiddle : "وسط", +DlgImgAlignRight : "يمين", +DlgImgAlignTextTop : "أعلى النص", +DlgImgAlignTop : "أعلى", +DlgImgPreview : "معاينة", +DlgImgAlertUrl : "Ùضلاً أكتب الموقع الذي توجد عليه هذه الصورة.", +DlgImgLinkTab : "الرابط", + +// Flash Dialog +DlgFlashTitle : "خصائص Ùيلم الÙلاش", +DlgFlashChkPlay : "تشغيل تلقائي", +DlgFlashChkLoop : "تكرار", +DlgFlashChkMenu : "تمكين قائمة Ùيلم الÙلاش", +DlgFlashScale : "الحجم", +DlgFlashScaleAll : "إظهار الكل", +DlgFlashScaleNoBorder : "بلا حدود", +DlgFlashScaleFit : "ضبط تام", + +// Link Dialog +DlgLnkWindowTitle : "إرتباط تشعبي", +DlgLnkInfoTab : "معلومات الرابط", +DlgLnkTargetTab : "الهدÙ", + +DlgLnkType : "نوع الربط", +DlgLnkTypeURL : "العنوان", +DlgLnkTypeAnchor : "مكان ÙÙŠ هذا المستند", +DlgLnkTypeEMail : "بريد إلكتروني", +DlgLnkProto : "البروتوكول", +DlgLnkProtoOther : "<أخرى>", +DlgLnkURL : "الموقع", +DlgLnkAnchorSel : "اختر علامة مرجعية", +DlgLnkAnchorByName : "حسب اسم العلامة", +DlgLnkAnchorById : "حسب تعري٠العنصر", +DlgLnkNoAnchors : "(لا يوجد علامات مرجعية ÙÙŠ هذا المستند)", +DlgLnkEMail : "عنوان بريد إلكتروني", +DlgLnkEMailSubject : "موضوع الرسالة", +DlgLnkEMailBody : "محتوى الرسالة", +DlgLnkUpload : "رÙع", +DlgLnkBtnUpload : "أرسلها للخادم", + +DlgLnkTarget : "الهدÙ", +DlgLnkTargetFrame : "<إطار>", +DlgLnkTargetPopup : "<ناÙذة منبثقة>", +DlgLnkTargetBlank : "إطار جديد (_blank)", +DlgLnkTargetParent : "الإطار الأصل (_parent)", +DlgLnkTargetSelf : "Ù†Ùس الإطار (_self)", +DlgLnkTargetTop : "صÙحة كاملة (_top)", +DlgLnkTargetFrameName : "اسم الإطار الهدÙ", +DlgLnkPopWinName : "تسمية الناÙذة المنبثقة", +DlgLnkPopWinFeat : "خصائص الناÙذة المنبثقة", +DlgLnkPopResize : "قابلة للتحجيم", +DlgLnkPopLocation : "شريط العنوان", +DlgLnkPopMenu : "القوائم الرئيسية", +DlgLnkPopScroll : "أشرطة التمرير", +DlgLnkPopStatus : "شريط الحالة السÙلي", +DlgLnkPopToolbar : "شريط الأدوات", +DlgLnkPopFullScrn : "ملئ الشاشة (IE)", +DlgLnkPopDependent : "تابع (Netscape)", +DlgLnkPopWidth : "العرض", +DlgLnkPopHeight : "الإرتÙاع", +DlgLnkPopLeft : "التمركز لليسار", +DlgLnkPopTop : "التمركز للأعلى", + +DlnLnkMsgNoUrl : "Ùضلاً أدخل عنوان الموقع الذي يشير إليه الرابط", +DlnLnkMsgNoEMail : "Ùضلاً أدخل عنوان البريد الإلكتروني", +DlnLnkMsgNoAnchor : "Ùضلاً حدد العلامة المرجعية المرغوبة", +DlnLnkMsgInvPopName : "اسم الناÙذة المنبثقة يجب أن يبدأ بحر٠أبجدي دون مساÙات", + +// Color Dialog +DlgColorTitle : "اختر لوناً", +DlgColorBtnClear : "مسح", +DlgColorHighlight : "تحديد", +DlgColorSelected : "إختيار", + +// Smiley Dialog +DlgSmileyTitle : "إدراج إبتسامات ", + +// Special Character Dialog +DlgSpecialCharTitle : "إدراج رمز", + +// Table Dialog +DlgTableTitle : "إدراج جدول", +DlgTableRows : "صÙÙˆÙ", +DlgTableColumns : "أعمدة", +DlgTableBorder : "سمك الحدود", +DlgTableAlign : "المحاذاة", +DlgTableAlignNotSet : "<بدون تحديد>", +DlgTableAlignLeft : "يسار", +DlgTableAlignCenter : "وسط", +DlgTableAlignRight : "يمين", +DlgTableWidth : "العرض", +DlgTableWidthPx : "بكسل", +DlgTableWidthPc : "بالمئة", +DlgTableHeight : "الإرتÙاع", +DlgTableCellSpace : "تباعد الخلايا", +DlgTableCellPad : "المساÙØ© البادئة", +DlgTableCaption : "الوصÙ", +DlgTableSummary : "الخلاصة", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "خصائص الخلية", +DlgCellWidth : "العرض", +DlgCellWidthPx : "بكسل", +DlgCellWidthPc : "بالمئة", +DlgCellHeight : "الإرتÙاع", +DlgCellWordWrap : "التÙا٠النص", +DlgCellWordWrapNotSet : "<بدون تحديد>", +DlgCellWordWrapYes : "نعم", +DlgCellWordWrapNo : "لا", +DlgCellHorAlign : "المحاذاة الأÙقية", +DlgCellHorAlignNotSet : "<بدون تحديد>", +DlgCellHorAlignLeft : "يسار", +DlgCellHorAlignCenter : "وسط", +DlgCellHorAlignRight: "يمين", +DlgCellVerAlign : "المحاذاة العمودية", +DlgCellVerAlignNotSet : "<بدون تحديد>", +DlgCellVerAlignTop : "أعلى", +DlgCellVerAlignMiddle : "وسط", +DlgCellVerAlignBottom : "أسÙÙ„", +DlgCellVerAlignBaseline : "على السطر", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "إمتداد الصÙÙˆÙ", +DlgCellCollSpan : "إمتداد الأعمدة", +DlgCellBackColor : "لون الخلÙية", +DlgCellBorderColor : "لون الحدود", +DlgCellBtnSelect : "حدّد...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "بحث واستبدال", + +// Find Dialog +DlgFindTitle : "بحث", +DlgFindFindBtn : "ابحث", +DlgFindNotFoundMsg : "لم يتم العثور على النص المحدد.", + +// Replace Dialog +DlgReplaceTitle : "إستبدال", +DlgReplaceFindLbl : "البحث عن:", +DlgReplaceReplaceLbl : "إستبدال بـ:", +DlgReplaceCaseChk : "مطابقة حالة الأحرÙ", +DlgReplaceReplaceBtn : "إستبدال", +DlgReplaceReplAllBtn : "إستبدال الكل", +DlgReplaceWordChk : "الكلمة بالكامل Ùقط", + +// Paste Operations / Dialog +PasteErrorCut : "الإعدادات الأمنية للمتصÙØ­ الذي تستخدمه تمنع القص التلقائي. Ùضلاً إستخدم لوحة المÙاتيح Ù„Ùعل ذلك (Ctrl+X).", +PasteErrorCopy : "الإعدادات الأمنية للمتصÙØ­ الذي تستخدمه تمنع النسخ التلقائي. Ùضلاً إستخدم لوحة المÙاتيح Ù„Ùعل ذلك (Ctrl+C).", + +PasteAsText : "لصق كنص بسيط", +PasteFromWord : "لصق من وورد", + +DlgPasteMsg2 : "الصق داخل الصندوق بإستخدام زرّي (Ctrl+V) ÙÙŠ لوحة المÙاتيح، ثم اضغط زر مواÙÙ‚.", +DlgPasteSec : "نظراً لإعدادات الأمان الخاصة بمتصÙحك، لن يتمكن هذا المحرر من الوصول لمحتوى حاÙظتك، لذا وجب عليك لصق المحتوى مرة أخرى ÙÙŠ هذه الناÙذة.", +DlgPasteIgnoreFont : "تجاهل تعريÙات أسماء الخطوط", +DlgPasteRemoveStyles : "إزالة تعريÙات الأنماط", + +// Color Picker +ColorAutomatic : "تلقائي", +ColorMoreColors : "ألوان إضاÙية...", + +// Document Properties +DocProps : "خصائص الصÙحة", + +// Anchor Dialog +DlgAnchorTitle : "خصائص إشارة مرجعية", +DlgAnchorName : "اسم الإشارة المرجعية", +DlgAnchorErrorName : "الرجاء كتابة اسم الإشارة المرجعية", + +// Speller Pages Dialog +DlgSpellNotInDic : "ليست ÙÙŠ القاموس", +DlgSpellChangeTo : "التغيير إلى", +DlgSpellBtnIgnore : "تجاهل", +DlgSpellBtnIgnoreAll : "تجاهل الكل", +DlgSpellBtnReplace : "تغيير", +DlgSpellBtnReplaceAll : "تغيير الكل", +DlgSpellBtnUndo : "تراجع", +DlgSpellNoSuggestions : "- لا توجد إقتراحات -", +DlgSpellProgress : "جاري التدقيق إملائياً", +DlgSpellNoMispell : "تم إكمال التدقيق الإملائي: لم يتم العثور على أي أخطاء إملائية", +DlgSpellNoChanges : "تم إكمال التدقيق الإملائي: لم يتم تغيير أي كلمة", +DlgSpellOneChange : "تم إكمال التدقيق الإملائي: تم تغيير كلمة واحدة Ùقط", +DlgSpellManyChanges : "تم إكمال التدقيق الإملائي: تم تغيير %1 كلمات\كلمة", + +IeSpellDownload : "المدقق الإملائي (الإنجليزي) غير مثبّت. هل تود تحميله الآن؟", + +// Button Dialog +DlgButtonText : "القيمة/التسمية", +DlgButtonType : "نوع الزر", +DlgButtonTypeBtn : "زر", +DlgButtonTypeSbm : "إرسال", +DlgButtonTypeRst : "إعادة تعيين", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "الاسم", +DlgCheckboxValue : "القيمة", +DlgCheckboxSelected : "محدد", + +// Form Dialog +DlgFormName : "الاسم", +DlgFormAction : "اسم الملÙ", +DlgFormMethod : "الأسلوب", + +// Select Field Dialog +DlgSelectName : "الاسم", +DlgSelectValue : "القيمة", +DlgSelectSize : "الحجم", +DlgSelectLines : "الأسطر", +DlgSelectChkMulti : "السماح بتحديدات متعددة", +DlgSelectOpAvail : "الخيارات المتاحة", +DlgSelectOpText : "النص", +DlgSelectOpValue : "القيمة", +DlgSelectBtnAdd : "إضاÙØ©", +DlgSelectBtnModify : "تعديل", +DlgSelectBtnUp : "تحريك لأعلى", +DlgSelectBtnDown : "تحريك لأسÙÙ„", +DlgSelectBtnSetValue : "إجعلها محددة", +DlgSelectBtnDelete : "إزالة", + +// Textarea Dialog +DlgTextareaName : "الاسم", +DlgTextareaCols : "الأعمدة", +DlgTextareaRows : "الصÙÙˆÙ", + +// Text Field Dialog +DlgTextName : "الاسم", +DlgTextValue : "القيمة", +DlgTextCharWidth : "العرض بالأحرÙ", +DlgTextMaxChars : "عدد الحرو٠الأقصى", +DlgTextType : "نوع المحتوى", +DlgTextTypeText : "نص", +DlgTextTypePass : "كلمة مرور", + +// Hidden Field Dialog +DlgHiddenName : "الاسم", +DlgHiddenValue : "القيمة", + +// Bulleted List Dialog +BulletedListProp : "خصائص التعداد النقطي", +NumberedListProp : "خصائص التعداد الرقمي", +DlgLstStart : "البدء عند", +DlgLstType : "النوع", +DlgLstTypeCircle : "دائرة", +DlgLstTypeDisc : "قرص", +DlgLstTypeSquare : "مربع", +DlgLstTypeNumbers : "أرقام (1ØŒ 2ØŒ 3)ÙŽ", +DlgLstTypeLCase : "حرو٠صغيرة (a, b, c)ÙŽ", +DlgLstTypeUCase : "حرو٠كبيرة (A, B, C)ÙŽ", +DlgLstTypeSRoman : "ترقيم روماني صغير (i, ii, iii)ÙŽ", +DlgLstTypeLRoman : "ترقيم روماني كبير (I, II, III)ÙŽ", + +// Document Properties Dialog +DlgDocGeneralTab : "عام", +DlgDocBackTab : "الخلÙية", +DlgDocColorsTab : "الألوان والهوامش", +DlgDocMetaTab : "المعرّÙات الرأسية", + +DlgDocPageTitle : "عنوان الصÙحة", +DlgDocLangDir : "إتجاه اللغة", +DlgDocLangDirLTR : "اليسار لليمين (LTR)", +DlgDocLangDirRTL : "اليمين لليسار (RTL)", +DlgDocLangCode : "رمز اللغة", +DlgDocCharSet : "ترميز الحروÙ", +DlgDocCharSetCE : "أوروبا الوسطى", +DlgDocCharSetCT : "الصينية التقليدية (Big5)", +DlgDocCharSetCR : "السيريلية", +DlgDocCharSetGR : "اليونانية", +DlgDocCharSetJP : "اليابانية", +DlgDocCharSetKR : "الكورية", +DlgDocCharSetTR : "التركية", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "أوروبا الغربية", +DlgDocCharSetOther : "ترميز آخر", + +DlgDocDocType : "ترويسة نوع الصÙحة", +DlgDocDocTypeOther : "ترويسة نوع صÙحة أخرى", +DlgDocIncXHTML : "تضمين إعلانات†لغة XHTMLÙŽ", +DlgDocBgColor : "لون الخلÙية", +DlgDocBgImage : "رابط الصورة الخلÙية", +DlgDocBgNoScroll : "جعلها علامة مائية", +DlgDocCText : "النص", +DlgDocCLink : "الروابط", +DlgDocCVisited : "المزارة", +DlgDocCActive : "النشطة", +DlgDocMargins : "هوامش الصÙحة", +DlgDocMaTop : "علوي", +DlgDocMaLeft : "أيسر", +DlgDocMaRight : "أيمن", +DlgDocMaBottom : "سÙلي", +DlgDocMeIndex : "الكلمات الأساسية (Ù…Ùصولة بÙواصل)ÙŽ", +DlgDocMeDescr : "وص٠الصÙحة", +DlgDocMeAuthor : "الكاتب", +DlgDocMeCopy : "المالك", +DlgDocPreview : "معاينة", + +// Templates Dialog +Templates : "القوالب", +DlgTemplatesTitle : "قوالب المحتوى", +DlgTemplatesSelMsg : "اختر القالب الذي تود وضعه ÙÙŠ المحرر
    (سيتم Ùقدان المحتوى الحالي):", +DlgTemplatesLoading : "جاري تحميل قائمة القوالب، الرجاء الإنتظار...", +DlgTemplatesNoTpl : "(لم يتم تعري٠أي قالب)", +DlgTemplatesReplace : "استبدال المحتوى", + +// About Dialog +DlgAboutAboutTab : "نبذة", +DlgAboutBrowserInfoTab : "معلومات متصÙحك", +DlgAboutLicenseTab : "الترخيص", +DlgAboutVersion : "الإصدار", +DlgAboutInfo : "لمزيد من المعلومات تÙضل بزيارة", + +// Div Dialog +DlgDivGeneralTab : "عام", +DlgDivAdvancedTab : "متقدم", +DlgDivStyle : "المظهر", +DlgDivInlineStyle : "المظهر المضمن", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/bg.js b/www/js/FCKeditor/editor/lang/bg.js new file mode 100644 index 0000000..a58a094 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/bg.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Bulgarian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Скрий панела Ñ Ð¸Ð½Ñтрументите", +ToolbarExpand : "Покажи панела Ñ Ð¸Ð½Ñтрументите", + +// Toolbar Items and Context Menu +Save : "Запази", +NewPage : "Ðова Ñтраница", +Preview : "Предварителен изглед", +Cut : "Изрежи", +Copy : "Запамети", +Paste : "Вмъкни", +PasteText : "Вмъкни Ñамо текÑÑ‚", +PasteWord : "Вмъкни от MS Word", +Print : "Печат", +SelectAll : "Селектирай вÑичко", +RemoveFormat : "Изтрий форматирането", +InsertLinkLbl : "Връзка", +InsertLink : "Добави/Редактирай връзка", +RemoveLink : "Изтрий връзка", +VisitLink : "Open Link", //MISSING +Anchor : "Добави/Редактирай котва", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "Изображение", +InsertImage : "Добави/Редактирай изображение", +InsertFlashLbl : "Flash", +InsertFlash : "Добави/Редактиай Flash обект", +InsertTableLbl : "Таблица", +InsertTable : "Добави/Редактирай таблица", +InsertLineLbl : "ЛиниÑ", +InsertLine : "Вмъкни хоризонтална линиÑ", +InsertSpecialCharLbl: "Специален Ñимвол", +InsertSpecialChar : "Вмъкни Ñпециален Ñимвол", +InsertSmileyLbl : "УÑмивка", +InsertSmiley : "Добави уÑмивка", +About : "За FCKeditor", +Bold : "Удебелен", +Italic : "КурÑив", +Underline : "Подчертан", +StrikeThrough : "Зачертан", +Subscript : "Ð˜Ð½Ð´ÐµÐºÑ Ð·Ð° база", +Superscript : "Ð˜Ð½Ð´ÐµÐºÑ Ð·Ð° Ñтепен", +LeftJustify : "ПодравнÑване в лÑво", +CenterJustify : "ПодравнÑвне в Ñредата", +RightJustify : "ПодравнÑване в дÑÑно", +BlockJustify : "ДвуÑтранно подравнÑване", +DecreaseIndent : "Ðамали отÑтъпа", +IncreaseIndent : "Увеличи отÑтъпа", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Отмени", +Redo : "Повтори", +NumberedListLbl : "Ðумериран ÑпиÑък", +NumberedList : "Добави/Изтрий нумериран ÑпиÑък", +BulletedListLbl : "Ðенумериран ÑпиÑък", +BulletedList : "Добави/Изтрий ненумериран ÑпиÑък", +ShowTableBorders : "Покажи рамките на таблицата", +ShowDetails : "Покажи подробноÑти", +Style : "Стил", +FontFormat : "Формат", +Font : "Шрифт", +FontSize : "Размер", +TextColor : "ЦвÑÑ‚ на текÑта", +BGColor : "ЦвÑÑ‚ на фона", +Source : "Код", +Find : "ТърÑи", +Replace : "ЗамеÑти", +SpellCheck : "Провери правопиÑа", +UniversalKeyboard : "УниверÑална клавиатура", +PageBreakLbl : "Ðов ред", +PageBreak : "Вмъкни нов ред", + +Form : "ФормулÑÑ€", +Checkbox : "Поле за отметка", +RadioButton : "Поле за опциÑ", +TextField : "ТекÑтово поле", +Textarea : "ТекÑтова облаÑÑ‚", +HiddenField : "Скрито поле", +Button : "Бутон", +SelectionField : "Падащо меню Ñ Ð¾Ð¿Ñ†Ð¸Ð¸", +ImageButton : "Бутон-изображение", + +FitWindow : "Maximize the editor size", //MISSING +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Редактирай връзка", +CellCM : "Cell", //MISSING +RowCM : "Row", //MISSING +ColumnCM : "Column", //MISSING +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "Изтрий редовете", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "Изтрий колоните", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "Изтрий клетките", +MergeCells : "Обедини клетките", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "Изтрий таблицата", +CellProperties : "Параметри на клетката", +TableProperties : "Параметри на таблицата", +ImageProperties : "Параметри на изображението", +FlashProperties : "Параметри на Flash обекта", + +AnchorProp : "Параметри на котвата", +ButtonProp : "Параметри на бутона", +CheckboxProp : "Параметри на полето за отметка", +HiddenFieldProp : "Параметри на Ñкритото поле", +RadioButtonProp : "Параметри на полето за опциÑ", +ImageButtonProp : "Параметри на бутона-изображение", +TextFieldProp : "Параметри на текÑтовото-поле", +SelectionFieldProp : "Параметри на падащото меню Ñ Ð¾Ð¿Ñ†Ð¸Ð¸", +TextareaProp : "Параметри на текÑтовата облаÑÑ‚", +FormProp : "Параметри на формулÑра", + +FontFormats : "Ðормален;Форматиран;ÐдреÑ;Заглавие 1;Заглавие 2;Заглавие 3;Заглавие 4;Заглавие 5;Заглавие 6;Параграф (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Обработка на XHTML. ÐœÐ¾Ð»Ñ Ð¸Ð·Ñ‡Ð°ÐºÐ°Ð¹Ñ‚Ðµ...", +Done : "Готово", +PasteWordConfirm : "ТекÑÑ‚ÑŠÑ‚, който иÑкате да вмъкнете е копиран от MS Word. Желаете ли да бъде изчиÑтен преди вмъкването?", +NotCompatiblePaste : "Тази Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¸Ð·Ð¸Ñква MS Internet Explorer верÑÐ¸Ñ 5.5 или по-виÑока. Желаете ли да вмъкнете запаметеното без изчиÑтване?", +UnknownToolbarItem : "Ðепознат инÑтрумент \"%1\"", +UnknownCommand : "Ðепозната команда \"%1\"", +NotImplemented : "Командата не е имплементирана", +UnknownToolbarSet : "Панелът \"%1\" не ÑъщеÑтвува", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "ОК", +DlgBtnCancel : "Отказ", +DlgBtnClose : "Затвори", +DlgBtnBrowseServer : "Разгледай Ñървъра", +DlgAdvancedTag : "ПодробноÑти...", +DlgOpOther : "<Друго>", +DlgInfoTab : "ИнформациÑ", +DlgAlertUrl : "МолÑ, въведете Ð¿ÑŠÐ»Ð½Ð¸Ñ Ð¿ÑŠÑ‚ (URL)", + +// General Dialogs Labels +DlgGenNotSet : "<не е наÑтроен>", +DlgGenId : "Идентификатор", +DlgGenLangDir : "поÑока на речта", +DlgGenLangDirLtr : "От лÑво на дÑÑно", +DlgGenLangDirRtl : "От дÑÑно на лÑво", +DlgGenLangCode : "Код на езика", +DlgGenAccessKey : "Бърз клавиш", +DlgGenName : "Име", +DlgGenTabIndex : "Ред на доÑтъп", +DlgGenLongDescr : "ОпиÑание на връзката", +DlgGenClass : "ÐšÐ»Ð°Ñ Ð¾Ñ‚ Ñтиловите таблици", +DlgGenTitle : "Препоръчително заглавие", +DlgGenContType : "Препоръчителен тип на Ñъдържанието", +DlgGenLinkCharset : "Тип на ÑÐ²ÑŠÑ€Ð·Ð°Ð½Ð¸Ñ Ñ€ÐµÑурÑ", +DlgGenStyle : "Стил", + +// Image Dialog +DlgImgTitle : "Параметри на изображението", +DlgImgInfoTab : "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° изображението", +DlgImgBtnUpload : "Прати към Ñървъра", +DlgImgURL : "Пълен път (URL)", +DlgImgUpload : "Качи", +DlgImgAlt : "Ðлтернативен текÑÑ‚", +DlgImgWidth : "Ширина", +DlgImgHeight : "ВиÑочина", +DlgImgLockRatio : "Запази пропорциÑта", +DlgBtnResetSize : "ВъзÑтанови размера", +DlgImgBorder : "Рамка", +DlgImgHSpace : "Хоризонтален отÑтъп", +DlgImgVSpace : "Вертикален отÑтъп", +DlgImgAlign : "ПодравнÑване", +DlgImgAlignLeft : "ЛÑво", +DlgImgAlignAbsBottom: "Ðай-долу", +DlgImgAlignAbsMiddle: "Точно по Ñредата", +DlgImgAlignBaseline : "По базовата линиÑ", +DlgImgAlignBottom : "Долу", +DlgImgAlignMiddle : "По Ñредата", +DlgImgAlignRight : "ДÑÑно", +DlgImgAlignTextTop : "Върху текÑта", +DlgImgAlignTop : "Отгоре", +DlgImgPreview : "Изглед", +DlgImgAlertUrl : "МолÑ, въведете Ð¿ÑŠÐ»Ð½Ð¸Ñ Ð¿ÑŠÑ‚ до изображението", +DlgImgLinkTab : "Връзка", + +// Flash Dialog +DlgFlashTitle : "Параметри на Flash обекта", +DlgFlashChkPlay : "Ðвтоматично Ñтартиране", +DlgFlashChkLoop : "Ðово Ñтартиране Ñлед завършването", +DlgFlashChkMenu : "Разрешено Flash меню", +DlgFlashScale : "ОразмерÑване", +DlgFlashScaleAll : "Покажи Ñ†ÐµÐ»Ð¸Ñ Ð¾Ð±ÐµÐºÑ‚", +DlgFlashScaleNoBorder : "Без рамка", +DlgFlashScaleFit : "Според мÑÑтото", + +// Link Dialog +DlgLnkWindowTitle : "Връзка", +DlgLnkInfoTab : "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° връзката", +DlgLnkTargetTab : "Цел", + +DlgLnkType : "Вид на връзката", +DlgLnkTypeURL : "Пълен път (URL)", +DlgLnkTypeAnchor : "Котва в текущата Ñтраница", +DlgLnkTypeEMail : "Е-поща", +DlgLnkProto : "Протокол", +DlgLnkProtoOther : "<друго>", +DlgLnkURL : "Пълен път (URL)", +DlgLnkAnchorSel : "Изберете котва", +DlgLnkAnchorByName : "По име на котвата", +DlgLnkAnchorById : "По идентификатор на елемент", +DlgLnkNoAnchors : "(ÐÑма котви в Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚)", +DlgLnkEMail : "ÐÐ´Ñ€ÐµÑ Ð·Ð° е-поща", +DlgLnkEMailSubject : "Тема на пиÑмото", +DlgLnkEMailBody : "ТекÑÑ‚ на пиÑмото", +DlgLnkUpload : "Качи", +DlgLnkBtnUpload : "Прати на Ñървъра", + +DlgLnkTarget : "Цел", +DlgLnkTargetFrame : "<рамка>", +DlgLnkTargetPopup : "<дъщерен прозорец>", +DlgLnkTargetBlank : "Ðов прозорец (_blank)", +DlgLnkTargetParent : "РодителÑки прозорец (_parent)", +DlgLnkTargetSelf : "ÐÐºÑ‚Ð¸Ð²Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ† (_self)", +DlgLnkTargetTop : "Ð¦ÐµÐ»Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ† (_top)", +DlgLnkTargetFrameName : "Име на Ñ†ÐµÐ»ÐµÐ²Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ†", +DlgLnkPopWinName : "Име на Ð´ÑŠÑ‰ÐµÑ€Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ†", +DlgLnkPopWinFeat : "Параметри на Ð´ÑŠÑ‰ÐµÑ€Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ†", +DlgLnkPopResize : "С променливи размери", +DlgLnkPopLocation : "Поле за адреÑ", +DlgLnkPopMenu : "Меню", +DlgLnkPopScroll : "Плъзгач", +DlgLnkPopStatus : "Поле за ÑтатуÑ", +DlgLnkPopToolbar : "Панел Ñ Ð±ÑƒÑ‚Ð¾Ð½Ð¸", +DlgLnkPopFullScrn : "ГолÑм екран (MS IE)", +DlgLnkPopDependent : "ЗавиÑим (Netscape)", +DlgLnkPopWidth : "Ширина", +DlgLnkPopHeight : "ВиÑочина", +DlgLnkPopLeft : "Координати - X", +DlgLnkPopTop : "Координати - Y", + +DlnLnkMsgNoUrl : "МолÑ, напишете Ð¿ÑŠÐ»Ð½Ð¸Ñ Ð¿ÑŠÑ‚ (URL)", +DlnLnkMsgNoEMail : "МолÑ, напишете адреÑа за е-поща", +DlnLnkMsgNoAnchor : "МолÑ, изберете котва", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING + +// Color Dialog +DlgColorTitle : "Изберете цвÑÑ‚", +DlgColorBtnClear : "ИзчиÑти", +DlgColorHighlight : "Текущ", +DlgColorSelected : "Избран", + +// Smiley Dialog +DlgSmileyTitle : "Добави уÑмивка", + +// Special Character Dialog +DlgSpecialCharTitle : "Изберете Ñпециален Ñимвол", + +// Table Dialog +DlgTableTitle : "Параметри на таблицата", +DlgTableRows : "Редове", +DlgTableColumns : "Колони", +DlgTableBorder : "Размер на рамката", +DlgTableAlign : "ПодравнÑване", +DlgTableAlignNotSet : "<Ðе е избрано>", +DlgTableAlignLeft : "ЛÑво", +DlgTableAlignCenter : "Център", +DlgTableAlignRight : "ДÑÑно", +DlgTableWidth : "Ширина", +DlgTableWidthPx : "пикÑели", +DlgTableWidthPc : "проценти", +DlgTableHeight : "ВиÑочина", +DlgTableCellSpace : "РазÑтоÑние между клетките", +DlgTableCellPad : "ОтÑтъп на Ñъдържанието в клетките", +DlgTableCaption : "Заглавие", +DlgTableSummary : "Резюме", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Параметри на клетката", +DlgCellWidth : "Ширина", +DlgCellWidthPx : "пикÑели", +DlgCellWidthPc : "проценти", +DlgCellHeight : "ВиÑочина", +DlgCellWordWrap : "пренаÑÑне на нов ред", +DlgCellWordWrapNotSet : "<Ðе е наÑтроено>", +DlgCellWordWrapYes : "Да", +DlgCellWordWrapNo : "не", +DlgCellHorAlign : "Хоризонтално подравнÑване", +DlgCellHorAlignNotSet : "<Ðе е наÑтроено>", +DlgCellHorAlignLeft : "ЛÑво", +DlgCellHorAlignCenter : "Център", +DlgCellHorAlignRight: "ДÑÑно", +DlgCellVerAlign : "Вертикално подравнÑване", +DlgCellVerAlignNotSet : "<Ðе е наÑтроено>", +DlgCellVerAlignTop : "Горе", +DlgCellVerAlignMiddle : "По Ñредата", +DlgCellVerAlignBottom : "Долу", +DlgCellVerAlignBaseline : "По базовата линиÑ", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "повече от един ред", +DlgCellCollSpan : "повече от една колона", +DlgCellBackColor : "фонов цвÑÑ‚", +DlgCellBorderColor : "цвÑÑ‚ на рамката", +DlgCellBtnSelect : "Изберете...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "ТърÑи", +DlgFindFindBtn : "ТърÑи", +DlgFindNotFoundMsg : "Ð£ÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ñ‚ÐµÐºÑÑ‚ не беше намерен.", + +// Replace Dialog +DlgReplaceTitle : "ЗамеÑти", +DlgReplaceFindLbl : "ТърÑи:", +DlgReplaceReplaceLbl : "ЗамеÑти Ñ:", +DlgReplaceCaseChk : "Ð¡ÑŠÑ ÑÑŠÑ‰Ð¸Ñ Ñ€ÐµÐ³Ð¸ÑÑ‚ÑŠÑ€", +DlgReplaceReplaceBtn : "ЗамеÑти", +DlgReplaceReplAllBtn : "ЗамеÑти вÑички", +DlgReplaceWordChk : "ТърÑи Ñъщата дума", + +// Paste Operations / Dialog +PasteErrorCut : "ÐаÑтройките за ÑигурноÑÑ‚ на Ð²Ð°ÑˆÐ¸Ñ Ð±Ñ€Ð°Ð·ÑƒÑŠÑ€ не разрешават на редактора да изпълни изрÑзването. За целта използвайте клавиатурата (Ctrl+X).", +PasteErrorCopy : "ÐаÑтройките за ÑигурноÑÑ‚ на Ð²Ð°ÑˆÐ¸Ñ Ð±Ñ€Ð°Ð·ÑƒÑŠÑ€ не разрешават на редактора да изпълни запаметÑването. За целта използвайте клавиатурата (Ctrl+C).", + +PasteAsText : "Вмъкни като чиÑÑ‚ текÑÑ‚", +PasteFromWord : "Вмъкни от MS Word", + +DlgPasteMsg2 : "Вмъкнете тук Ñъдъжанието Ñ ÐºÐ»Ð°Ð²Ð¸Ð°Ñ‚ÑƒÐ°Ñ€Ð°Ñ‚Ð° (Ctrl+V) и натиÑнете OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "Игнорирай шрифтовите дефиниции", +DlgPasteRemoveStyles : "Изтрий Ñтиловите дефиниции", + +// Color Picker +ColorAutomatic : "По подразбиране", +ColorMoreColors : "Други цветове...", + +// Document Properties +DocProps : "Параметри на документа", + +// Anchor Dialog +DlgAnchorTitle : "Параметри на котвата", +DlgAnchorName : "Име на котвата", +DlgAnchorErrorName : "МолÑ, въведете име на котвата", + +// Speller Pages Dialog +DlgSpellNotInDic : "ЛипÑва в речника", +DlgSpellChangeTo : "Промени на", +DlgSpellBtnIgnore : "Игнорирай", +DlgSpellBtnIgnoreAll : "Игнорирай вÑички", +DlgSpellBtnReplace : "ЗамеÑти", +DlgSpellBtnReplaceAll : "ЗамеÑти вÑички", +DlgSpellBtnUndo : "Отмени", +DlgSpellNoSuggestions : "- ÐÑма Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ -", +DlgSpellProgress : "Извършване на проверката за правопиÑ...", +DlgSpellNoMispell : "Проверката за Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð²ÑŠÑ€ÑˆÐµÐ½Ð°: не Ñа открити правопиÑни грешки", +DlgSpellNoChanges : "Проверката за Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð²ÑŠÑ€ÑˆÐµÐ½Ð°: нÑма променени думи", +DlgSpellOneChange : "Проверката за Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð²ÑŠÑ€ÑˆÐµÐ½Ð°: една дума е променена", +DlgSpellManyChanges : "Проверката за Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð²ÑŠÑ€ÑˆÐµÐ½Ð°: %1 думи Ñа променени", + +IeSpellDownload : "ИнÑтрументът за проверка на Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð½Ðµ е инÑталиран. Желаете ли да го инÑталирате ?", + +// Button Dialog +DlgButtonText : "ТекÑÑ‚ (СтойноÑÑ‚)", +DlgButtonType : "Тип", +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Име", +DlgCheckboxValue : "СтойноÑÑ‚", +DlgCheckboxSelected : "Отметнато", + +// Form Dialog +DlgFormName : "Име", +DlgFormAction : "ДейÑтвие", +DlgFormMethod : "Метод", + +// Select Field Dialog +DlgSelectName : "Име", +DlgSelectValue : "СтойноÑÑ‚", +DlgSelectSize : "Размер", +DlgSelectLines : "линии", +DlgSelectChkMulti : "Разрешено множеÑтвено Ñелектиране", +DlgSelectOpAvail : "Възможни опции", +DlgSelectOpText : "ТекÑÑ‚", +DlgSelectOpValue : "СтойноÑÑ‚", +DlgSelectBtnAdd : "Добави", +DlgSelectBtnModify : "Промени", +DlgSelectBtnUp : "Ðагоре", +DlgSelectBtnDown : "Ðадолу", +DlgSelectBtnSetValue : "ÐаÑтрой като избрана ÑтойноÑÑ‚", +DlgSelectBtnDelete : "Изтрий", + +// Textarea Dialog +DlgTextareaName : "Име", +DlgTextareaCols : "Колони", +DlgTextareaRows : "Редове", + +// Text Field Dialog +DlgTextName : "Име", +DlgTextValue : "СтойноÑÑ‚", +DlgTextCharWidth : "Ширина на Ñимволите", +DlgTextMaxChars : "МакÑимум Ñимволи", +DlgTextType : "Тип", +DlgTextTypeText : "ТекÑÑ‚", +DlgTextTypePass : "Парола", + +// Hidden Field Dialog +DlgHiddenName : "Име", +DlgHiddenValue : "СтойноÑÑ‚", + +// Bulleted List Dialog +BulletedListProp : "Параметри на Ð½ÐµÐ½ÑƒÐ¼ÐµÑ€Ð¸Ñ€Ð°Ð½Ð¸Ñ ÑпиÑък", +NumberedListProp : "Параметри на Ð½ÑƒÐ¼ÐµÑ€Ð¸Ñ€Ð°Ð½Ð¸Ñ ÑпиÑък", +DlgLstStart : "Start", //MISSING +DlgLstType : "Тип", +DlgLstTypeCircle : "ОкръжноÑÑ‚", +DlgLstTypeDisc : "Кръг", +DlgLstTypeSquare : "Квадрат", +DlgLstTypeNumbers : "ЧиÑла (1, 2, 3)", +DlgLstTypeLCase : "Малки букви (a, b, c)", +DlgLstTypeUCase : "Големи букви (A, B, C)", +DlgLstTypeSRoman : "Малки римÑки чиÑла (i, ii, iii)", +DlgLstTypeLRoman : "Големи римÑки чиÑла (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Общи", +DlgDocBackTab : "Фон", +DlgDocColorsTab : "Цветове и отÑтъпи", +DlgDocMetaTab : "Мета данни", + +DlgDocPageTitle : "Заглавие на Ñтраницата", +DlgDocLangDir : "ПоÑока на речта", +DlgDocLangDirLTR : "От лÑво на дÑÑно", +DlgDocLangDirRTL : "От дÑÑно на лÑво", +DlgDocLangCode : "Код на езика", +DlgDocCharSet : "Кодиране на Ñимволите", +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "Друго кодиране на Ñимволите", + +DlgDocDocType : "Тип на документа", +DlgDocDocTypeOther : "Друг тип на документа", +DlgDocIncXHTML : "Включи XHTML декларациÑ", +DlgDocBgColor : "ЦвÑÑ‚ на фона", +DlgDocBgImage : "Пълен път до фоновото изображение", +DlgDocBgNoScroll : "Ðе-повтарÑщо Ñе фоново изображение", +DlgDocCText : "ТекÑÑ‚", +DlgDocCLink : "Връзка", +DlgDocCVisited : "ПоÑетена връзка", +DlgDocCActive : "Ðктивна връзка", +DlgDocMargins : "ОтÑтъпи на Ñтраницата", +DlgDocMaTop : "Горе", +DlgDocMaLeft : "ЛÑво", +DlgDocMaRight : "ДÑÑно", +DlgDocMaBottom : "Долу", +DlgDocMeIndex : "Ключови думи за документа (разделени ÑÑŠÑ Ð·Ð°Ð¿ÐµÑ‚Ð°Ð¸)", +DlgDocMeDescr : "ОпиÑание на документа", +DlgDocMeAuthor : "Ðвтор", +DlgDocMeCopy : "ÐвторÑки права", +DlgDocPreview : "Изглед", + +// Templates Dialog +Templates : "Шаблони", +DlgTemplatesTitle : "Шаблони", +DlgTemplatesSelMsg : "Изберете шаблон
    (текущото Ñъдържание на редактора ще бъде загубено):", +DlgTemplatesLoading : "Зареждане на ÑпиÑъка Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð¸Ñ‚Ðµ. ÐœÐ¾Ð»Ñ Ð¸Ð·Ñ‡Ð°ÐºÐ°Ð¹Ñ‚Ðµ...", +DlgTemplatesNoTpl : "(ÐÑма дефинирани шаблони)", +DlgTemplatesReplace : "Replace actual contents", //MISSING + +// About Dialog +DlgAboutAboutTab : "За", +DlgAboutBrowserInfoTab : "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° браузъра", +DlgAboutLicenseTab : "License", //MISSING +DlgAboutVersion : "верÑиÑ", +DlgAboutInfo : "За повече Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ñетете", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/bn.js b/www/js/FCKeditor/editor/lang/bn.js new file mode 100644 index 0000000..375cb49 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/bn.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Bengali/Bangla language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "টূলবার গà§à¦Ÿà¦¿à§Ÿà§‡ দাও", +ToolbarExpand : "টূলবার ছড়িয়ে দাও", + +// Toolbar Items and Context Menu +Save : "সংরকà§à¦·à¦¨ কর", +NewPage : "নতà§à¦¨ পেজ", +Preview : "পà§à¦°à¦¿à¦­à¦¿à¦‰", +Cut : "কাট", +Copy : "কপি", +Paste : "পেসà§à¦Ÿ", +PasteText : "পেসà§à¦Ÿ (সাদা টেকà§à¦¸à¦Ÿ)", +PasteWord : "পেসà§à¦Ÿ (শবà§à¦¦)", +Print : "পà§à¦°à¦¿à¦¨à§à¦Ÿ", +SelectAll : "সব সিলেকà§à¦Ÿ কর", +RemoveFormat : "ফরমেট সরাও", +InsertLinkLbl : "লিংকের যà§à¦•à§à¦¤ করার লেবেল", +InsertLink : "লিংক যà§à¦•à§à¦¤ কর", +RemoveLink : "লিংক সরাও", +VisitLink : "Open Link", //MISSING +Anchor : "নোঙà§à¦—র", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "ছবির লেবেল যà§à¦•à§à¦¤ কর", +InsertImage : "ছবি যà§à¦•à§à¦¤ কর", +InsertFlashLbl : "ফà§à¦²à¦¾à¦¶ লেবেল যà§à¦•à§à¦¤ কর", +InsertFlash : "ফà§à¦²à¦¾à¦¶ যà§à¦•à§à¦¤ কর", +InsertTableLbl : "টেবিলের লেবেল যà§à¦•à§à¦¤ কর", +InsertTable : "টেবিল যà§à¦•à§à¦¤ কর", +InsertLineLbl : "রেখা যà§à¦•à§à¦¤ কর", +InsertLine : "রেখা যà§à¦•à§à¦¤ কর", +InsertSpecialCharLbl: "বিশেষ অকà§à¦·à¦°à§‡à¦° লেবেল যà§à¦•à§à¦¤ কর", +InsertSpecialChar : "বিশেষ অকà§à¦·à¦° যà§à¦•à§à¦¤ কর", +InsertSmileyLbl : "সà§à¦®à¦¾à¦‡à¦²à§€", +InsertSmiley : "সà§à¦®à¦¾à¦‡à¦²à§€ যà§à¦•à§à¦¤ কর", +About : "FCKeditor কে বানিয়েছে", +Bold : "বোলà§à¦¡", +Italic : "ইটালিক", +Underline : "আনà§à¦¡à¦¾à¦°à¦²à¦¾à¦‡à¦¨", +StrikeThrough : "সà§à¦Ÿà§à¦°à¦¾à¦‡à¦• থà§à¦°à§", +Subscript : "অধোলেখ", +Superscript : "অভিলেখ", +LeftJustify : "বা দিকে ঘেà¦à¦·à¦¾", +CenterJustify : "মাঠবরাবর ঘেষা", +RightJustify : "ডান দিকে ঘেà¦à¦·à¦¾", +BlockJustify : "বà§à¦²à¦• জাসà§à¦Ÿà¦¿à¦«à¦¾à¦‡", +DecreaseIndent : "ইনডেনà§à¦Ÿ কমাও", +IncreaseIndent : "ইনডেনà§à¦Ÿ বাড়াও", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "আনডà§", +Redo : "রি-ডà§", +NumberedListLbl : "সাংখà§à¦¯à¦¿à¦• লিসà§à¦Ÿà§‡à¦° লেবেল", +NumberedList : "সাংখà§à¦¯à¦¿à¦• লিসà§à¦Ÿ", +BulletedListLbl : "বà§à¦²à§‡à¦Ÿ লিসà§à¦Ÿ লেবেল", +BulletedList : "বà§à¦²à§‡à¦Ÿà§‡à¦¡ লিসà§à¦Ÿ", +ShowTableBorders : "টেবিল বরà§à¦¡à¦¾à¦°", +ShowDetails : "সবটà§à¦•à§ দেখাও", +Style : "সà§à¦Ÿà¦¾à¦‡à¦²", +FontFormat : "ফনà§à¦Ÿ ফরমেট", +Font : "ফনà§à¦Ÿ", +FontSize : "সাইজ", +TextColor : "টেকà§à¦¸à§à¦Ÿ রং", +BGColor : "বেকগà§à¦°à¦¾à¦‰à¦¨à§à¦¡ রং", +Source : "সোরà§à¦¸", +Find : "খোজো", +Replace : "রিপà§à¦²à§‡à¦¸", +SpellCheck : "বানান চেক", +UniversalKeyboard : "সারà§à¦¬à¦œà¦¨à§€à¦¨ কিবোরà§à¦¡", +PageBreakLbl : "পেজ বà§à¦°à§‡à¦• লেবেল", +PageBreak : "পেজ বà§à¦°à§‡à¦•", + +Form : "ফরà§à¦®", +Checkbox : "চেক বাকà§à¦¸", +RadioButton : "রেডিও বাটন", +TextField : "টেকà§à¦¸à¦Ÿ ফীলà§à¦¡", +Textarea : "টেকà§à¦¸à¦Ÿ à¦à¦°à¦¿à§Ÿà¦¾", +HiddenField : "গà§à¦ªà§à¦¤ ফীলà§à¦¡", +Button : "বাটন", +SelectionField : "বাছাই ফীলà§à¦¡", +ImageButton : "ছবির বাটন", + +FitWindow : "উইনà§à¦¡à§‹ ফিট কর", +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "লিংক সমà§à¦ªà¦¾à¦¦à¦¨", +CellCM : "সেল", +RowCM : "রো", +ColumnCM : "কলাম", +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "রো মà§à¦›à§‡ দাও", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "কলাম মà§à¦›à§‡ দাও", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "সেল মà§à¦›à§‡ দাও", +MergeCells : "সেল জোড়া দাও", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "টেবিল ডিলীট কর", +CellProperties : "সেলের পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿à¦œ", +TableProperties : "টেবিল পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +ImageProperties : "ছবি পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +FlashProperties : "ফà§à¦²à¦¾à¦¶ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", + +AnchorProp : "নোঙর পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +ButtonProp : "বাটন পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +CheckboxProp : "চেক বকà§à¦¸ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +HiddenFieldProp : "গà§à¦ªà§à¦¤ ফীলà§à¦¡ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +RadioButtonProp : "রেডিও বাটন পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +ImageButtonProp : "ছবি বাটন পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +TextFieldProp : "টেকà§à¦¸à¦Ÿ ফীলà§à¦¡ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +SelectionFieldProp : "বাছাই ফীলà§à¦¡ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +TextareaProp : "টেকà§à¦¸à¦Ÿ à¦à¦°à¦¿à§Ÿà¦¾ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +FormProp : "ফরà§à¦® পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", + +FontFormats : "সাধারণ;ফরà§à¦®à§‡à¦Ÿà§‡à¦¡;ঠিকানা;শীরà§à¦·à¦• ১;শীরà§à¦·à¦• ২;শীরà§à¦·à¦• ৩;শীরà§à¦·à¦• ৪;শীরà§à¦·à¦• ৫;শীরà§à¦·à¦• ৬;শীরà§à¦·à¦• (DIV)", + +// Alerts and Messages +ProcessingXHTML : "XHTML পà§à¦°à¦¸à§‡à¦¸ করা হচà§à¦›à§‡", +Done : "শেষ হয়েছে", +PasteWordConfirm : "যে টেকসà§à¦Ÿà¦Ÿà¦¿ আপনি পেসà§à¦Ÿ করতে চাচà§à¦›à§‡à¦¨ মনে হচà§à¦›à§‡ সেটি ওয়ারà§à¦¡ থেকে কপি করা। আপনি কি পেসà§à¦Ÿ করার আগে à¦à¦•à§‡ পরিষà§à¦•à¦¾à¦° করতে চান?", +NotCompatiblePaste : "à¦à¦‡ কমানà§à¦¡à¦Ÿà¦¿ শà§à¦§à§à¦®à¦¾à¦¤à§à¦° ইনà§à¦Ÿà¦¾à¦°à¦¨à§‡à¦Ÿ à¦à¦•à§à¦¸à¦ªà§à¦²à§‹à¦°à¦¾à¦° ৫.০ বা তার পরের ভারà§à¦¸à¦¨à§‡ পাওয়া সমà§à¦­à¦¬à¥¤ আপনি কি পরিষà§à¦•à¦¾à¦° না করেই পেসà§à¦Ÿ করতে চান?", +UnknownToolbarItem : "অজানা টà§à¦²à¦¬à¦¾à¦° আইটেম \"%1\"", +UnknownCommand : "অজানা কমানà§à¦¡ \"%1\"", +NotImplemented : "কমানà§à¦¡ ইমপà§à¦²à¦¿à¦®à§‡à¦¨à§à¦Ÿ করা হয়নি", +UnknownToolbarSet : "টà§à¦²à¦¬à¦¾à¦° সেট \"%1\" à¦à¦° অসà§à¦¤à¦¿à¦¤à§à¦¬ নেই", +NoActiveX : "আপনার বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° সà§à¦°à¦•à§à¦·à¦¾ সেটিংস কারনে à¦à¦¡à¦¿à¦Ÿà¦°à§‡à¦° কিছৠফিচার পাওয়া নাও যেতে পারে। আপনাকে অবশà§à¦¯à¦‡ \"Run ActiveX controls and plug-ins\" à¦à¦¨à¦¾à¦¬à§‡à¦² করে নিতে হবে। আপনি ভà§à¦²à¦­à§à¦°à¦¾à¦¨à§à¦¤à¦¿ কিছৠকিছৠফিচারের অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤à¦¿ উপলবà§à¦§à¦¿ করতে পারেন।", +BrowseServerBlocked : "রিসোরà§à¦¸ বà§à¦°à¦¾à¦‰à¦œà¦¾à¦° খোলা গেল না। নিশà§à¦šà¦¿à¦¤ করà§à¦¨ যে সব পপআপ বà§à¦²à¦•à¦¾à¦° বনà§à¦§ করা আছে।", +DialogBlocked : "ডায়ালগ ইউনà§à¦¡à§‹ খোলা গেল না। নিশà§à¦šà¦¿à¦¤ করà§à¦¨ যে সব পপআপ বà§à¦²à¦•à¦¾à¦° বনà§à¦§ করা আছে।", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "ওকে", +DlgBtnCancel : "বাতিল", +DlgBtnClose : "বনà§à¦§ কর", +DlgBtnBrowseServer : "বà§à¦°à¦¾à¦‰à¦œ সারà§à¦­à¦¾à¦°", +DlgAdvancedTag : "à¦à¦¡à¦­à¦¾à¦¨à§à¦¸à¦¡", +DlgOpOther : "<অনà§à¦¯>", +DlgInfoTab : "তথà§à¦¯", +DlgAlertUrl : "দয়া করে URL যà§à¦•à§à¦¤ করà§à¦¨", + +// General Dialogs Labels +DlgGenNotSet : "<সেট নেই>", +DlgGenId : "আইডি", +DlgGenLangDir : "ভাষা লেখার দিক", +DlgGenLangDirLtr : "বাম থেকে ডান (LTR)", +DlgGenLangDirRtl : "ডান থেকে বাম (RTL)", +DlgGenLangCode : "ভাষা কোড", +DlgGenAccessKey : "à¦à¦•à§à¦¸à§‡à¦¸ কী", +DlgGenName : "নাম", +DlgGenTabIndex : "টà§à¦¯à¦¾à¦¬ ইনà§à¦¡à§‡à¦•à§à¦¸", +DlgGenLongDescr : "URL à¦à¦° লমà§à¦¬à¦¾ বরà§à¦£à¦¨à¦¾", +DlgGenClass : "সà§à¦Ÿà¦¾à¦‡à¦²-শীট কà§à¦²à¦¾à¦¸", +DlgGenTitle : "পরামরà§à¦¶ শীরà§à¦·à¦•", +DlgGenContType : "পরামরà§à¦¶ কনà§à¦Ÿà§‡à¦¨à§à¦Ÿà§‡à¦° পà§à¦°à¦•à¦¾à¦°", +DlgGenLinkCharset : "লিংক রিসোরà§à¦¸ কà§à¦¯à¦¾à¦°à§‡à¦•à§à¦Ÿà¦° সেট", +DlgGenStyle : "সà§à¦Ÿà¦¾à¦‡à¦²", + +// Image Dialog +DlgImgTitle : "ছবির পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +DlgImgInfoTab : "ছবির তথà§à¦¯", +DlgImgBtnUpload : "ইহাকে সারà§à¦­à¦¾à¦°à§‡ পà§à¦°à§‡à¦°à¦¨ কর", +DlgImgURL : "URL", +DlgImgUpload : "আপলোড", +DlgImgAlt : "বিকলà§à¦ª টেকà§à¦¸à¦Ÿ", +DlgImgWidth : "পà§à¦°à¦¸à§à¦¥", +DlgImgHeight : "দৈরà§à¦˜à§à¦¯", +DlgImgLockRatio : "অনà§à¦ªà¦¾à¦¤ লক কর", +DlgBtnResetSize : "সাইজ পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à§Ÿ ফিরিয়ে দাও", +DlgImgBorder : "বরà§à¦¡à¦¾à¦°", +DlgImgHSpace : "হরাইজনà§à¦Ÿà¦¾à¦² সà§à¦ªà§‡à¦¸", +DlgImgVSpace : "ভারà§à¦Ÿà¦¿à¦•à§‡à¦² সà§à¦ªà§‡à¦¸", +DlgImgAlign : "à¦à¦²à¦¾à¦‡à¦¨", +DlgImgAlignLeft : "বামে", +DlgImgAlignAbsBottom: "Abs নীচে", +DlgImgAlignAbsMiddle: "Abs উপর", +DlgImgAlignBaseline : "মূল রেখা", +DlgImgAlignBottom : "নীচে", +DlgImgAlignMiddle : "মধà§à¦¯", +DlgImgAlignRight : "ডানে", +DlgImgAlignTextTop : "টেকà§à¦¸à¦Ÿ উপর", +DlgImgAlignTop : "উপর", +DlgImgPreview : "পà§à¦°à§€à¦­à¦¿à¦‰", +DlgImgAlertUrl : "অনà§à¦—à§à¦°à¦¹à¦• করে ছবির URL টাইপ করà§à¦¨", +DlgImgLinkTab : "লিংক", + +// Flash Dialog +DlgFlashTitle : "ফà§à¦²à§à¦¯à¦¾à¦¶ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +DlgFlashChkPlay : "অটো পà§à¦²à§‡", +DlgFlashChkLoop : "লূপ", +DlgFlashChkMenu : "ফà§à¦²à§à¦¯à¦¾à¦¶ মেনৠà¦à¦¨à¦¾à¦¬à¦² কর", +DlgFlashScale : "সà§à¦•à§‡à¦²", +DlgFlashScaleAll : "সব দেখাও", +DlgFlashScaleNoBorder : "কোনো বরà§à¦¡à¦¾à¦° নেই", +DlgFlashScaleFit : "নিখà§à¦à¦¤ ফিট", + +// Link Dialog +DlgLnkWindowTitle : "লিংক", +DlgLnkInfoTab : "লিংক তথà§à¦¯", +DlgLnkTargetTab : "টারà§à¦—েট", + +DlgLnkType : "লিংক পà§à¦°à¦•à¦¾à¦°", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "à¦à¦‡ পেজে নোঙর কর", +DlgLnkTypeEMail : "ইমেইল", +DlgLnkProto : "পà§à¦°à§‹à¦Ÿà§‹à¦•à¦²", +DlgLnkProtoOther : "<অনà§à¦¯>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "নোঙর বাছাই", +DlgLnkAnchorByName : "নোঙরের নাম দিয়ে", +DlgLnkAnchorById : "নোঙরের আইডি দিয়ে", +DlgLnkNoAnchors : "(No anchors available in the document)", //MISSING +DlgLnkEMail : "ইমেইল ঠিকানা", +DlgLnkEMailSubject : "মেসেজের বিষয়", +DlgLnkEMailBody : "মেসেজের দেহ", +DlgLnkUpload : "আপলোড", +DlgLnkBtnUpload : "à¦à¦•à§‡ সারà§à¦­à¦¾à¦°à§‡ পাঠাও", + +DlgLnkTarget : "টারà§à¦—েট", +DlgLnkTargetFrame : "<ফà§à¦°à§‡à¦®>", +DlgLnkTargetPopup : "<পপআপ উইনà§à¦¡à§‹>", +DlgLnkTargetBlank : "নতà§à¦¨ উইনà§à¦¡à§‹ (_blank)", +DlgLnkTargetParent : "মূল উইনà§à¦¡à§‹ (_parent)", +DlgLnkTargetSelf : "à¦à¦‡ উইনà§à¦¡à§‹ (_self)", +DlgLnkTargetTop : "শীরà§à¦· উইনà§à¦¡à§‹ (_top)", +DlgLnkTargetFrameName : "টারà§à¦—েট ফà§à¦°à§‡à¦®à§‡à¦° নাম", +DlgLnkPopWinName : "পপআপ উইনà§à¦¡à§‹à¦° নাম", +DlgLnkPopWinFeat : "পপআপ উইনà§à¦¡à§‹ ফীচার সমূহ", +DlgLnkPopResize : "রিসাইজ করা সমà§à¦­à¦¬", +DlgLnkPopLocation : "লোকেশন বার", +DlgLnkPopMenu : "মেনà§à¦¯à§ বার", +DlgLnkPopScroll : "সà§à¦•à§à¦°à¦² বার", +DlgLnkPopStatus : "সà§à¦Ÿà§à¦¯à¦¾à¦Ÿà¦¾à¦¸ বার", +DlgLnkPopToolbar : "টà§à¦² বার", +DlgLnkPopFullScrn : "পূরà§à¦£ পরà§à¦¦à¦¾ জà§à§œà§‡ (IE)", +DlgLnkPopDependent : "ডিপেনà§à¦¡à§‡à¦¨à§à¦Ÿ (Netscape)", +DlgLnkPopWidth : "পà§à¦°à¦¸à§à¦¥", +DlgLnkPopHeight : "দৈরà§à¦˜à§à¦¯", +DlgLnkPopLeft : "বামের পজিশন", +DlgLnkPopTop : "ডানের পজিশন", + +DlnLnkMsgNoUrl : "অনà§à¦—à§à¦°à¦¹ করে URL লিংক টাইপ করà§à¦¨", +DlnLnkMsgNoEMail : "অনà§à¦—à§à¦°à¦¹ করে ইমেইল à¦à¦¡à§à¦°à§‡à¦¸ টাইপ করà§à¦¨", +DlnLnkMsgNoAnchor : "অনà§à¦—à§à¦°à¦¹ করে নোঙর বাছাই করà§à¦¨", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING + +// Color Dialog +DlgColorTitle : "রং বাছাই কর", +DlgColorBtnClear : "পরিষà§à¦•à¦¾à¦° কর", +DlgColorHighlight : "হাইলাইট", +DlgColorSelected : "সিলেকà§à¦Ÿà§‡à¦¡", + +// Smiley Dialog +DlgSmileyTitle : "সà§à¦®à¦¾à¦‡à¦²à§€ যà§à¦•à§à¦¤ কর", + +// Special Character Dialog +DlgSpecialCharTitle : "বিশেষ কà§à¦¯à¦¾à¦°à§‡à¦•à§à¦Ÿà¦¾à¦° বাছাই কর", + +// Table Dialog +DlgTableTitle : "টেবিল পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +DlgTableRows : "রো", +DlgTableColumns : "কলাম", +DlgTableBorder : "বরà§à¦¡à¦¾à¦° সাইজ", +DlgTableAlign : "à¦à¦²à¦¾à¦‡à¦¨à¦®à§‡à¦¨à§à¦Ÿ", +DlgTableAlignNotSet : "<সেট নেই>", +DlgTableAlignLeft : "বামে", +DlgTableAlignCenter : "মাà¦à¦–ানে", +DlgTableAlignRight : "ডানে", +DlgTableWidth : "পà§à¦°à¦¸à§à¦¥", +DlgTableWidthPx : "পিকà§à¦¸à§‡à¦²", +DlgTableWidthPc : "শতকরা", +DlgTableHeight : "দৈরà§à¦˜à§à¦¯", +DlgTableCellSpace : "সেল সà§à¦ªà§‡à¦¸", +DlgTableCellPad : "সেল পà§à¦¯à¦¾à¦¡à¦¿à¦‚", +DlgTableCaption : "শীরà§à¦·à¦•", +DlgTableSummary : "সারাংশ", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "সেল পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +DlgCellWidth : "পà§à¦°à¦¸à§à¦¥", +DlgCellWidthPx : "পিকà§à¦¸à§‡à¦²", +DlgCellWidthPc : "শতকরা", +DlgCellHeight : "দৈরà§à¦˜à§à¦¯", +DlgCellWordWrap : "ওয়ারà§à¦¡ রেপ", +DlgCellWordWrapNotSet : "<সেট নেই>", +DlgCellWordWrapYes : "হাà¦", +DlgCellWordWrapNo : "না", +DlgCellHorAlign : "হরাইজনà§à¦Ÿà¦¾à¦² à¦à¦²à¦¾à¦‡à¦¨à¦®à§‡à¦¨à§à¦Ÿ", +DlgCellHorAlignNotSet : "<সেট নেই>", +DlgCellHorAlignLeft : "বামে", +DlgCellHorAlignCenter : "মাà¦à¦–ানে", +DlgCellHorAlignRight: "ডানে", +DlgCellVerAlign : "ভারà§à¦Ÿà¦¿à¦•à§à¦¯à¦¾à¦² à¦à¦²à¦¾à¦‡à¦¨à¦®à§‡à¦¨à§à¦Ÿ", +DlgCellVerAlignNotSet : "<সেট নেই>", +DlgCellVerAlignTop : "উপর", +DlgCellVerAlignMiddle : "মধà§à¦¯", +DlgCellVerAlignBottom : "নীচে", +DlgCellVerAlignBaseline : "মূলরেখা", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "রো সà§à¦ªà§à¦¯à¦¾à¦¨", +DlgCellCollSpan : "কলাম সà§à¦ªà§à¦¯à¦¾à¦¨", +DlgCellBackColor : "বà§à¦¯à¦¾à¦•à¦—à§à¦°à¦¾à¦‰à¦¨à§à¦¡ রং", +DlgCellBorderColor : "বরà§à¦¡à¦¾à¦°à§‡à¦° রং", +DlgCellBtnSelect : "বাছাই কর", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "খোà¦à¦œà§‹", +DlgFindFindBtn : "খোà¦à¦œà§‹", +DlgFindNotFoundMsg : "আপনার উলà§à¦²à§‡à¦–িত টেকসà§à¦Ÿ পাওয়া যায়নি", + +// Replace Dialog +DlgReplaceTitle : "বদলে দাও", +DlgReplaceFindLbl : "যা খà§à¦à¦œà¦¤à§‡ হবে:", +DlgReplaceReplaceLbl : "যার সাথে বদলাতে হবে:", +DlgReplaceCaseChk : "কেস মিলাও", +DlgReplaceReplaceBtn : "বদলে দাও", +DlgReplaceReplAllBtn : "সব বদলে দাও", +DlgReplaceWordChk : "পà§à¦°à¦¾ শবà§à¦¦ মেলাও", + +// Paste Operations / Dialog +PasteErrorCut : "আপনার বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° সà§à¦°à¦•à§à¦·à¦¾ সেটিংস à¦à¦¡à¦¿à¦Ÿà¦°à¦•à§‡ অটোমেটিক কাট করার অনà§à¦®à¦¤à¦¿ দেয়নি। দয়া করে à¦à¦‡ কাজের জনà§à¦¯ কিবোরà§à¦¡ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨ (Ctrl+X)।", +PasteErrorCopy : "আপনার বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° সà§à¦°à¦•à§à¦·à¦¾ সেটিংস à¦à¦¡à¦¿à¦Ÿà¦°à¦•à§‡ অটোমেটিক কপি করার অনà§à¦®à¦¤à¦¿ দেয়নি। দয়া করে à¦à¦‡ কাজের জনà§à¦¯ কিবোরà§à¦¡ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨ (Ctrl+C)।", + +PasteAsText : "সাদা টেকà§à¦¸à¦Ÿ হিসেবে পেসà§à¦Ÿ কর", +PasteFromWord : "ওয়ারà§à¦¡ থেকে পেসà§à¦Ÿ কর", + +DlgPasteMsg2 : "অনà§à¦—à§à¦°à¦¹ করে নীচের বাকà§à¦¸à§‡ কিবোরà§à¦¡ বà§à¦¯à¦¬à¦¹à¦¾à¦° করে (Ctrl+V) পেসà§à¦Ÿ করà§à¦¨ à¦à¦¬à¦‚ OK চাপ দিন", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "ফনà§à¦Ÿ ফেস ডেফিনেশন ইগনোর করà§à¦¨", +DlgPasteRemoveStyles : "সà§à¦Ÿà¦¾à¦‡à¦² ডেফিনেশন সরিয়ে দিন", + +// Color Picker +ColorAutomatic : "অটোমেটিক", +ColorMoreColors : "আরও রং...", + +// Document Properties +DocProps : "ডকà§à¦¯à§à¦®à§‡à¦¨à§à¦Ÿ পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", + +// Anchor Dialog +DlgAnchorTitle : "নোঙরের পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +DlgAnchorName : "নোঙরের নাম", +DlgAnchorErrorName : "নোঙরের নাম টাইপ করà§à¦¨", + +// Speller Pages Dialog +DlgSpellNotInDic : "শবà§à¦¦à¦•à§‹à¦·à§‡ নেই", +DlgSpellChangeTo : "à¦à¦¤à§‡ বদলাও", +DlgSpellBtnIgnore : "ইগনোর কর", +DlgSpellBtnIgnoreAll : "সব ইগনোর কর", +DlgSpellBtnReplace : "বদলে দাও", +DlgSpellBtnReplaceAll : "সব বদলে দাও", +DlgSpellBtnUndo : "আনà§à¦¡à§", +DlgSpellNoSuggestions : "- কোন সাজেশন নেই -", +DlgSpellProgress : "বানান পরীকà§à¦·à¦¾ চলছে...", +DlgSpellNoMispell : "বানান পরীকà§à¦·à¦¾ শেষ: কোন ভà§à¦² বানান পাওয়া যায়নি", +DlgSpellNoChanges : "বানান পরীকà§à¦·à¦¾ শেষ: কোন শবà§à¦¦ পরিবরà§à¦¤à¦¨ করা হয়নি", +DlgSpellOneChange : "বানান পরীকà§à¦·à¦¾ শেষ: à¦à¦•à¦Ÿà¦¿ মাতà§à¦° শবà§à¦¦ পরিবরà§à¦¤à¦¨ করা হয়েছে", +DlgSpellManyChanges : "বানান পরীকà§à¦·à¦¾ শেষ: %1 গà§à¦²à§‹ শবà§à¦¦ বদলে গà§à¦¯à¦¾à¦›à§‡", + +IeSpellDownload : "বানান পরীকà§à¦·à¦• ইনসà§à¦Ÿà¦² করা নেই। আপনি কি à¦à¦–নই à¦à¦Ÿà¦¾ ডাউনলোড করতে চান?", + +// Button Dialog +DlgButtonText : "টেকà§à¦¸à¦Ÿ (ভà§à¦¯à¦¾à¦²à§)", +DlgButtonType : "পà§à¦°à¦•à¦¾à¦°", +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "নাম", +DlgCheckboxValue : "ভà§à¦¯à¦¾à¦²à§", +DlgCheckboxSelected : "সিলেকà§à¦Ÿà§‡à¦¡", + +// Form Dialog +DlgFormName : "নাম", +DlgFormAction : "à¦à¦•à¦¶à§à¦¯à¦¨", +DlgFormMethod : "পদà§à¦§à¦¤à¦¿", + +// Select Field Dialog +DlgSelectName : "নাম", +DlgSelectValue : "ভà§à¦¯à¦¾à¦²à§", +DlgSelectSize : "সাইজ", +DlgSelectLines : "লাইন সমূহ", +DlgSelectChkMulti : "à¦à¦•à¦¾à¦§à¦¿à¦• সিলেকশন à¦à¦²à¦¾à¦‰ কর", +DlgSelectOpAvail : "অনà§à¦¯à¦¾à¦¨à§à¦¯ বিকলà§à¦ª", +DlgSelectOpText : "টেকà§à¦¸à¦Ÿ", +DlgSelectOpValue : "ভà§à¦¯à¦¾à¦²à§", +DlgSelectBtnAdd : "যà§à¦•à§à¦¤", +DlgSelectBtnModify : "বদলে দাও", +DlgSelectBtnUp : "উপর", +DlgSelectBtnDown : "নীচে", +DlgSelectBtnSetValue : "বাছাই করা ভà§à¦¯à¦¾à¦²à§ হিসেবে সেট কর", +DlgSelectBtnDelete : "ডিলীট", + +// Textarea Dialog +DlgTextareaName : "নাম", +DlgTextareaCols : "কলাম", +DlgTextareaRows : "রো", + +// Text Field Dialog +DlgTextName : "নাম", +DlgTextValue : "ভà§à¦¯à¦¾à¦²à§", +DlgTextCharWidth : "কà§à¦¯à¦¾à¦°à§‡à¦•à§à¦Ÿà¦¾à¦° পà§à¦°à¦¶à¦¸à§à¦¤à¦¤à¦¾", +DlgTextMaxChars : "সরà§à¦¬à¦¾à¦§à¦¿à¦• কà§à¦¯à¦¾à¦°à§‡à¦•à§à¦Ÿà¦¾à¦°", +DlgTextType : "টাইপ", +DlgTextTypeText : "টেকà§à¦¸à¦Ÿ", +DlgTextTypePass : "পাসওয়ারà§à¦¡", + +// Hidden Field Dialog +DlgHiddenName : "নাম", +DlgHiddenValue : "ভà§à¦¯à¦¾à¦²à§", + +// Bulleted List Dialog +BulletedListProp : "বà§à¦²à§‡à¦Ÿà§‡à¦¡ সূচী পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +NumberedListProp : "সাংখà§à¦¯à¦¿à¦• সূচী পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿", +DlgLstStart : "Start", //MISSING +DlgLstType : "পà§à¦°à¦•à¦¾à¦°", +DlgLstTypeCircle : "গোল", +DlgLstTypeDisc : "ডিসà§à¦•", +DlgLstTypeSquare : "চৌকোণা", +DlgLstTypeNumbers : "সংখà§à¦¯à¦¾ (1, 2, 3)", +DlgLstTypeLCase : "ছোট অকà§à¦·à¦° (a, b, c)", +DlgLstTypeUCase : "বড় অকà§à¦·à¦° (A, B, C)", +DlgLstTypeSRoman : "ছোট রোমান সংখà§à¦¯à¦¾ (i, ii, iii)", +DlgLstTypeLRoman : "বড় রোমান সংখà§à¦¯à¦¾ (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "সাধারন", +DlgDocBackTab : "বà§à¦¯à¦¾à¦•à¦—à§à¦°à¦¾à¦‰à¦¨à§à¦¡", +DlgDocColorsTab : "রং à¦à¦¬à¦‚ মারà§à¦œà¦¿à¦¨", +DlgDocMetaTab : "মেটাডেটা", + +DlgDocPageTitle : "পেজ শীরà§à¦·à¦•", +DlgDocLangDir : "ভাষা লিখার দিক", +DlgDocLangDirLTR : "বাম থেকে ডানে (LTR)", +DlgDocLangDirRTL : "ডান থেকে বামে (RTL)", +DlgDocLangCode : "ভাষা কোড", +DlgDocCharSet : "কà§à¦¯à¦¾à¦°à§‡à¦•à§à¦Ÿà¦¾à¦° সেট à¦à¦¨à¦•à§‹à¦¡à¦¿à¦‚", +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "অনà§à¦¯ কà§à¦¯à¦¾à¦°à§‡à¦•à§à¦Ÿà¦¾à¦° সেট à¦à¦¨à¦•à§‹à¦¡à¦¿à¦‚", + +DlgDocDocType : "ডকà§à¦¯à§à¦®à§‡à¦¨à§à¦Ÿ টাইপ হেডিং", +DlgDocDocTypeOther : "অনà§à¦¯ ডকà§à¦¯à§à¦®à§‡à¦¨à§à¦Ÿ টাইপ হেডিং", +DlgDocIncXHTML : "XHTML ডেকà§à¦²à¦¾à¦°à§‡à¦¶à¦¨ যà§à¦•à§à¦¤ কর", +DlgDocBgColor : "বà§à¦¯à¦¾à¦•à¦—à§à¦°à¦¾à¦‰à¦¨à§à¦¡ রং", +DlgDocBgImage : "বà§à¦¯à¦¾à¦•à¦—à§à¦°à¦¾à¦‰à¦¨à§à¦¡ ছবির URL", +DlgDocBgNoScroll : "সà§à¦•à§à¦°à¦²à¦¹à§€à¦¨ বà§à¦¯à¦¾à¦•à¦—à§à¦°à¦¾à¦‰à¦¨à§à¦¡", +DlgDocCText : "টেকà§à¦¸à¦Ÿ", +DlgDocCLink : "লিংক", +DlgDocCVisited : "ভিজিট করা লিংক", +DlgDocCActive : "সকà§à¦°à¦¿à§Ÿ লিংক", +DlgDocMargins : "পেজ মারà§à¦œà¦¿à¦¨", +DlgDocMaTop : "উপর", +DlgDocMaLeft : "বামে", +DlgDocMaRight : "ডানে", +DlgDocMaBottom : "নীচে", +DlgDocMeIndex : "ডকà§à¦¯à§à¦®à§‡à¦¨à§à¦Ÿ ইনà§à¦¡à§‡à¦•à§à¦¸ কিওয়ারà§à¦¡ (কমা দà§à¦¬à¦¾à¦°à¦¾ বিচà§à¦›à¦¿à¦¨à§à¦¨)", +DlgDocMeDescr : "ডকà§à¦¯à§‚মেনà§à¦Ÿ বরà§à¦£à¦¨à¦¾", +DlgDocMeAuthor : "লেখক", +DlgDocMeCopy : "কপীরাইট", +DlgDocPreview : "পà§à¦°à§€à¦­à¦¿à¦‰", + +// Templates Dialog +Templates : "টেমপà§à¦²à§‡à¦Ÿ", +DlgTemplatesTitle : "কনটেনà§à¦Ÿ টেমপà§à¦²à§‡à¦Ÿ", +DlgTemplatesSelMsg : "অনà§à¦—à§à¦°à¦¹ করে à¦à¦¡à¦¿à¦Ÿà¦°à§‡ ওপেন করার জনà§à¦¯ টেমপà§à¦²à§‡à¦Ÿ বাছাই করà§à¦¨
    (আসল কনটেনà§à¦Ÿ হারিয়ে যাবে):", +DlgTemplatesLoading : "টেমপà§à¦²à§‡à¦Ÿ লিসà§à¦Ÿ হারিয়ে যাবে। অনà§à¦—à§à¦°à¦¹ করে অপেকà§à¦·à¦¾ করà§à¦¨...", +DlgTemplatesNoTpl : "(কোন টেমপà§à¦²à§‡à¦Ÿ ডিফাইন করা নেই)", +DlgTemplatesReplace : "Replace actual contents", //MISSING + +// About Dialog +DlgAboutAboutTab : "কে বানিয়েছে", +DlgAboutBrowserInfoTab : "বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° বà§à¦¯à¦¾à¦ªà¦¾à¦°à§‡ তথà§à¦¯", +DlgAboutLicenseTab : "লাইসেনà§à¦¸", +DlgAboutVersion : "ভারà§à¦¸à¦¨", +DlgAboutInfo : "আরও তথà§à¦¯à§‡à¦° জনà§à¦¯ যান", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/bs.js b/www/js/FCKeditor/editor/lang/bs.js new file mode 100644 index 0000000..1de61e4 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/bs.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Bosnian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Skupi trake sa alatima", +ToolbarExpand : "Otvori trake sa alatima", + +// Toolbar Items and Context Menu +Save : "Snimi", +NewPage : "Novi dokument", +Preview : "Prikaži", +Cut : "Izreži", +Copy : "Kopiraj", +Paste : "Zalijepi", +PasteText : "Zalijepi kao obièan tekst", +PasteWord : "Zalijepi iz Word-a", +Print : "Å tampaj", +SelectAll : "Selektuj sve", +RemoveFormat : "PoniÅ¡ti format", +InsertLinkLbl : "Link", +InsertLink : "Ubaci/Izmjeni link", +RemoveLink : "IzbriÅ¡i link", +VisitLink : "Open Link", //MISSING +Anchor : "Insert/Edit Anchor", //MISSING +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "Slika", +InsertImage : "Ubaci/Izmjeni sliku", +InsertFlashLbl : "Flash", //MISSING +InsertFlash : "Insert/Edit Flash", //MISSING +InsertTableLbl : "Tabela", +InsertTable : "Ubaci/Izmjeni tabelu", +InsertLineLbl : "Linija", +InsertLine : "Ubaci horizontalnu liniju", +InsertSpecialCharLbl: "Specijalni karakter", +InsertSpecialChar : "Ubaci specijalni karater", +InsertSmileyLbl : "SmjeÅ¡ko", +InsertSmiley : "Ubaci smjeÅ¡ka", +About : "O FCKeditor-u", +Bold : "Boldiraj", +Italic : "Ukosi", +Underline : "Podvuci", +StrikeThrough : "Precrtaj", +Subscript : "Subscript", +Superscript : "Superscript", +LeftJustify : "Lijevo poravnanje", +CenterJustify : "Centralno poravnanje", +RightJustify : "Desno poravnanje", +BlockJustify : "Puno poravnanje", +DecreaseIndent : "Smanji uvod", +IncreaseIndent : "Poveæaj uvod", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Vrati", +Redo : "Ponovi", +NumberedListLbl : "Numerisana lista", +NumberedList : "Ubaci/Izmjeni numerisanu listu", +BulletedListLbl : "Lista", +BulletedList : "Ubaci/Izmjeni listu", +ShowTableBorders : "Pokaži okvire tabela", +ShowDetails : "Pokaži detalje", +Style : "Stil", +FontFormat : "Format", +Font : "Font", +FontSize : "Velièina", +TextColor : "Boja teksta", +BGColor : "Boja pozadine", +Source : "HTML kôd", +Find : "Naði", +Replace : "Zamjeni", +SpellCheck : "Check Spelling", //MISSING +UniversalKeyboard : "Universal Keyboard", //MISSING +PageBreakLbl : "Page Break", //MISSING +PageBreak : "Insert Page Break", //MISSING + +Form : "Form", //MISSING +Checkbox : "Checkbox", //MISSING +RadioButton : "Radio Button", //MISSING +TextField : "Text Field", //MISSING +Textarea : "Textarea", //MISSING +HiddenField : "Hidden Field", //MISSING +Button : "Button", //MISSING +SelectionField : "Selection Field", //MISSING +ImageButton : "Image Button", //MISSING + +FitWindow : "Maximize the editor size", //MISSING +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Izmjeni link", +CellCM : "Cell", //MISSING +RowCM : "Row", //MISSING +ColumnCM : "Column", //MISSING +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "BriÅ¡i redove", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "BriÅ¡i kolone", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "BriÅ¡i æelije", +MergeCells : "Spoji æelije", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "Delete Table", //MISSING +CellProperties : "Svojstva æelije", +TableProperties : "Svojstva tabele", +ImageProperties : "Svojstva slike", +FlashProperties : "Flash Properties", //MISSING + +AnchorProp : "Anchor Properties", //MISSING +ButtonProp : "Button Properties", //MISSING +CheckboxProp : "Checkbox Properties", //MISSING +HiddenFieldProp : "Hidden Field Properties", //MISSING +RadioButtonProp : "Radio Button Properties", //MISSING +ImageButtonProp : "Image Button Properties", //MISSING +TextFieldProp : "Text Field Properties", //MISSING +SelectionFieldProp : "Selection Field Properties", //MISSING +TextareaProp : "Textarea Properties", //MISSING +FormProp : "Form Properties", //MISSING + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6", + +// Alerts and Messages +ProcessingXHTML : "Procesiram XHTML. Molim saèekajte...", +Done : "Gotovo", +PasteWordConfirm : "Tekst koji želite zalijepiti èini se da je kopiran iz Worda. Da li želite da se prvo oèisti?", +NotCompatiblePaste : "Ova komanda je podržana u Internet Explorer-u verzijama 5.5 ili novijim. Da li želite da izvrÅ¡ite lijepljenje teksta bez èišæenja?", +UnknownToolbarItem : "Nepoznata stavka sa trake sa alatima \"%1\"", +UnknownCommand : "Nepoznata komanda \"%1\"", +NotImplemented : "Komanda nije implementirana", +UnknownToolbarSet : "Traka sa alatima \"%1\" ne postoji", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Odustani", +DlgBtnClose : "Zatvori", +DlgBtnBrowseServer : "Browse Server", //MISSING +DlgAdvancedTag : "Naprednije", +DlgOpOther : "", //MISSING +DlgInfoTab : "Info", //MISSING +DlgAlertUrl : "Please insert the URL", //MISSING + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Smjer pisanja", +DlgGenLangDirLtr : "S lijeva na desno (LTR)", +DlgGenLangDirRtl : "S desna na lijevo (RTL)", +DlgGenLangCode : "Jezièni kôd", +DlgGenAccessKey : "Pristupna tipka", +DlgGenName : "Naziv", +DlgGenTabIndex : "Tab indeks", +DlgGenLongDescr : "Dugaèki opis URL-a", +DlgGenClass : "Klase CSS stilova", +DlgGenTitle : "Advisory title", +DlgGenContType : "Advisory vrsta sadržaja", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "Stil", + +// Image Dialog +DlgImgTitle : "Svojstva slike", +DlgImgInfoTab : "Info slike", +DlgImgBtnUpload : "Å alji na server", +DlgImgURL : "URL", +DlgImgUpload : "Å alji", +DlgImgAlt : "Tekst na slici", +DlgImgWidth : "Å irina", +DlgImgHeight : "Visina", +DlgImgLockRatio : "Zakljuèaj odnos", +DlgBtnResetSize : "Resetuj dimenzije", +DlgImgBorder : "Okvir", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Poravnanje", +DlgImgAlignLeft : "Lijevo", +DlgImgAlignAbsBottom: "Abs dole", +DlgImgAlignAbsMiddle: "Abs sredina", +DlgImgAlignBaseline : "Bazno", +DlgImgAlignBottom : "Dno", +DlgImgAlignMiddle : "Sredina", +DlgImgAlignRight : "Desno", +DlgImgAlignTextTop : "Vrh teksta", +DlgImgAlignTop : "Vrh", +DlgImgPreview : "Prikaz", +DlgImgAlertUrl : "Molimo ukucajte URL od slike.", +DlgImgLinkTab : "Link", //MISSING + +// Flash Dialog +DlgFlashTitle : "Flash Properties", //MISSING +DlgFlashChkPlay : "Auto Play", //MISSING +DlgFlashChkLoop : "Loop", //MISSING +DlgFlashChkMenu : "Enable Flash Menu", //MISSING +DlgFlashScale : "Scale", //MISSING +DlgFlashScaleAll : "Show all", //MISSING +DlgFlashScaleNoBorder : "No Border", //MISSING +DlgFlashScaleFit : "Exact Fit", //MISSING + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link info", +DlgLnkTargetTab : "Prozor", + +DlgLnkType : "Tip linka", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Sidro na ovoj stranici", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protokol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Izaberi sidro", +DlgLnkAnchorByName : "Po nazivu sidra", +DlgLnkAnchorById : "Po Id-u elementa", +DlgLnkNoAnchors : "(Nema dostupnih sidra na stranici)", +DlgLnkEMail : "E-Mail Adresa", +DlgLnkEMailSubject : "Subjekt poruke", +DlgLnkEMailBody : "Poruka", +DlgLnkUpload : "Å alji", +DlgLnkBtnUpload : "Å alji na server", + +DlgLnkTarget : "Prozor", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Novi prozor (_blank)", +DlgLnkTargetParent : "Glavni prozor (_parent)", +DlgLnkTargetSelf : "Isti prozor (_self)", +DlgLnkTargetTop : "Najgornji prozor (_top)", +DlgLnkTargetFrameName : "Target Frame Name", //MISSING +DlgLnkPopWinName : "Naziv popup prozora", +DlgLnkPopWinFeat : "Moguænosti popup prozora", +DlgLnkPopResize : "Promjenljive velièine", +DlgLnkPopLocation : "Traka za lokaciju", +DlgLnkPopMenu : "Izborna traka", +DlgLnkPopScroll : "Scroll traka", +DlgLnkPopStatus : "Statusna traka", +DlgLnkPopToolbar : "Traka sa alatima", +DlgLnkPopFullScrn : "Cijeli ekran (IE)", +DlgLnkPopDependent : "Ovisno (Netscape)", +DlgLnkPopWidth : "Å irina", +DlgLnkPopHeight : "Visina", +DlgLnkPopLeft : "Lijeva pozicija", +DlgLnkPopTop : "Gornja pozicija", + +DlnLnkMsgNoUrl : "Molimo ukucajte URL link", +DlnLnkMsgNoEMail : "Molimo ukucajte e-mail adresu", +DlnLnkMsgNoAnchor : "Molimo izaberite sidro", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING + +// Color Dialog +DlgColorTitle : "Izaberi boju", +DlgColorBtnClear : "Oèisti", +DlgColorHighlight : "Igled", +DlgColorSelected : "Selektovana", + +// Smiley Dialog +DlgSmileyTitle : "Ubaci smjeÅ¡ka", + +// Special Character Dialog +DlgSpecialCharTitle : "Izaberi specijalni karakter", + +// Table Dialog +DlgTableTitle : "Svojstva tabele", +DlgTableRows : "Redova", +DlgTableColumns : "Kolona", +DlgTableBorder : "Okvir", +DlgTableAlign : "Poravnanje", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Lijevo", +DlgTableAlignCenter : "Centar", +DlgTableAlignRight : "Desno", +DlgTableWidth : "Å irina", +DlgTableWidthPx : "piksela", +DlgTableWidthPc : "posto", +DlgTableHeight : "Visina", +DlgTableCellSpace : "Razmak æelija", +DlgTableCellPad : "Uvod æelija", +DlgTableCaption : "Naslov", +DlgTableSummary : "Summary", //MISSING +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Svojstva æelije", +DlgCellWidth : "Å irina", +DlgCellWidthPx : "piksela", +DlgCellWidthPc : "posto", +DlgCellHeight : "Visina", +DlgCellWordWrap : "Vrapuj tekst", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Da", +DlgCellWordWrapNo : "Ne", +DlgCellHorAlign : "Horizontalno poravnanje", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Lijevo", +DlgCellHorAlignCenter : "Centar", +DlgCellHorAlignRight: "Desno", +DlgCellVerAlign : "Vertikalno poravnanje", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Gore", +DlgCellVerAlignMiddle : "Sredina", +DlgCellVerAlignBottom : "Dno", +DlgCellVerAlignBaseline : "Bazno", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Spajanje æelija", +DlgCellCollSpan : "Spajanje kolona", +DlgCellBackColor : "Boja pozadine", +DlgCellBorderColor : "Boja okvira", +DlgCellBtnSelect : "Selektuj...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "Naði", +DlgFindFindBtn : "Naði", +DlgFindNotFoundMsg : "Traženi tekst nije pronaðen.", + +// Replace Dialog +DlgReplaceTitle : "Zamjeni", +DlgReplaceFindLbl : "Naði Å¡ta:", +DlgReplaceReplaceLbl : "Zamjeni sa:", +DlgReplaceCaseChk : "Uporeðuj velika/mala slova", +DlgReplaceReplaceBtn : "Zamjeni", +DlgReplaceReplAllBtn : "Zamjeni sve", +DlgReplaceWordChk : "Uporeðuj samo cijelu rijeè", + +// Paste Operations / Dialog +PasteErrorCut : "Sigurnosne postavke vaÅ¡eg pretraživaèa ne dozvoljavaju operacije automatskog rezanja. Molimo koristite kraticu na tastaturi (Ctrl+X).", +PasteErrorCopy : "Sigurnosne postavke VaÅ¡eg pretraživaèa ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tastaturi (Ctrl+C).", + +PasteAsText : "Zalijepi kao obièan tekst", +PasteFromWord : "Zalijepi iz Word-a", + +DlgPasteMsg2 : "Please paste inside the following box using the keyboard (Ctrl+V) and hit OK.", //MISSING +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "Ignore Font Face definitions", //MISSING +DlgPasteRemoveStyles : "Remove Styles definitions", //MISSING + +// Color Picker +ColorAutomatic : "Automatska", +ColorMoreColors : "ViÅ¡e boja...", + +// Document Properties +DocProps : "Document Properties", //MISSING + +// Anchor Dialog +DlgAnchorTitle : "Anchor Properties", //MISSING +DlgAnchorName : "Anchor Name", //MISSING +DlgAnchorErrorName : "Please type the anchor name", //MISSING + +// Speller Pages Dialog +DlgSpellNotInDic : "Not in dictionary", //MISSING +DlgSpellChangeTo : "Change to", //MISSING +DlgSpellBtnIgnore : "Ignore", //MISSING +DlgSpellBtnIgnoreAll : "Ignore All", //MISSING +DlgSpellBtnReplace : "Replace", //MISSING +DlgSpellBtnReplaceAll : "Replace All", //MISSING +DlgSpellBtnUndo : "Undo", //MISSING +DlgSpellNoSuggestions : "- No suggestions -", //MISSING +DlgSpellProgress : "Spell check in progress...", //MISSING +DlgSpellNoMispell : "Spell check complete: No misspellings found", //MISSING +DlgSpellNoChanges : "Spell check complete: No words changed", //MISSING +DlgSpellOneChange : "Spell check complete: One word changed", //MISSING +DlgSpellManyChanges : "Spell check complete: %1 words changed", //MISSING + +IeSpellDownload : "Spell checker not installed. Do you want to download it now?", //MISSING + +// Button Dialog +DlgButtonText : "Text (Value)", //MISSING +DlgButtonType : "Type", //MISSING +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Name", //MISSING +DlgCheckboxValue : "Value", //MISSING +DlgCheckboxSelected : "Selected", //MISSING + +// Form Dialog +DlgFormName : "Name", //MISSING +DlgFormAction : "Action", //MISSING +DlgFormMethod : "Method", //MISSING + +// Select Field Dialog +DlgSelectName : "Name", //MISSING +DlgSelectValue : "Value", //MISSING +DlgSelectSize : "Size", //MISSING +DlgSelectLines : "lines", //MISSING +DlgSelectChkMulti : "Allow multiple selections", //MISSING +DlgSelectOpAvail : "Available Options", //MISSING +DlgSelectOpText : "Text", //MISSING +DlgSelectOpValue : "Value", //MISSING +DlgSelectBtnAdd : "Add", //MISSING +DlgSelectBtnModify : "Modify", //MISSING +DlgSelectBtnUp : "Up", //MISSING +DlgSelectBtnDown : "Down", //MISSING +DlgSelectBtnSetValue : "Set as selected value", //MISSING +DlgSelectBtnDelete : "Delete", //MISSING + +// Textarea Dialog +DlgTextareaName : "Name", //MISSING +DlgTextareaCols : "Columns", //MISSING +DlgTextareaRows : "Rows", //MISSING + +// Text Field Dialog +DlgTextName : "Name", //MISSING +DlgTextValue : "Value", //MISSING +DlgTextCharWidth : "Character Width", //MISSING +DlgTextMaxChars : "Maximum Characters", //MISSING +DlgTextType : "Type", //MISSING +DlgTextTypeText : "Text", //MISSING +DlgTextTypePass : "Password", //MISSING + +// Hidden Field Dialog +DlgHiddenName : "Name", //MISSING +DlgHiddenValue : "Value", //MISSING + +// Bulleted List Dialog +BulletedListProp : "Bulleted List Properties", //MISSING +NumberedListProp : "Numbered List Properties", //MISSING +DlgLstStart : "Start", //MISSING +DlgLstType : "Type", //MISSING +DlgLstTypeCircle : "Circle", //MISSING +DlgLstTypeDisc : "Disc", //MISSING +DlgLstTypeSquare : "Square", //MISSING +DlgLstTypeNumbers : "Numbers (1, 2, 3)", //MISSING +DlgLstTypeLCase : "Lowercase Letters (a, b, c)", //MISSING +DlgLstTypeUCase : "Uppercase Letters (A, B, C)", //MISSING +DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", //MISSING +DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", //MISSING + +// Document Properties Dialog +DlgDocGeneralTab : "General", //MISSING +DlgDocBackTab : "Background", //MISSING +DlgDocColorsTab : "Colors and Margins", //MISSING +DlgDocMetaTab : "Meta Data", //MISSING + +DlgDocPageTitle : "Page Title", //MISSING +DlgDocLangDir : "Language Direction", //MISSING +DlgDocLangDirLTR : "Left to Right (LTR)", //MISSING +DlgDocLangDirRTL : "Right to Left (RTL)", //MISSING +DlgDocLangCode : "Language Code", //MISSING +DlgDocCharSet : "Character Set Encoding", //MISSING +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "Other Character Set Encoding", //MISSING + +DlgDocDocType : "Document Type Heading", //MISSING +DlgDocDocTypeOther : "Other Document Type Heading", //MISSING +DlgDocIncXHTML : "Include XHTML Declarations", //MISSING +DlgDocBgColor : "Background Color", //MISSING +DlgDocBgImage : "Background Image URL", //MISSING +DlgDocBgNoScroll : "Nonscrolling Background", //MISSING +DlgDocCText : "Text", //MISSING +DlgDocCLink : "Link", //MISSING +DlgDocCVisited : "Visited Link", //MISSING +DlgDocCActive : "Active Link", //MISSING +DlgDocMargins : "Page Margins", //MISSING +DlgDocMaTop : "Top", //MISSING +DlgDocMaLeft : "Left", //MISSING +DlgDocMaRight : "Right", //MISSING +DlgDocMaBottom : "Bottom", //MISSING +DlgDocMeIndex : "Document Indexing Keywords (comma separated)", //MISSING +DlgDocMeDescr : "Document Description", //MISSING +DlgDocMeAuthor : "Author", //MISSING +DlgDocMeCopy : "Copyright", //MISSING +DlgDocPreview : "Preview", //MISSING + +// Templates Dialog +Templates : "Templates", //MISSING +DlgTemplatesTitle : "Content Templates", //MISSING +DlgTemplatesSelMsg : "Please select the template to open in the editor
    (the actual contents will be lost):", //MISSING +DlgTemplatesLoading : "Loading templates list. Please wait...", //MISSING +DlgTemplatesNoTpl : "(No templates defined)", //MISSING +DlgTemplatesReplace : "Replace actual contents", //MISSING + +// About Dialog +DlgAboutAboutTab : "About", //MISSING +DlgAboutBrowserInfoTab : "Browser Info", //MISSING +DlgAboutLicenseTab : "License", //MISSING +DlgAboutVersion : "verzija", +DlgAboutInfo : "Za više informacija posjetite", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/ca.js b/www/js/FCKeditor/editor/lang/ca.js new file mode 100644 index 0000000..2530ca6 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/ca.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Catalan language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Redueix la barra d'eines", +ToolbarExpand : "Amplia la barra d'eines", + +// Toolbar Items and Context Menu +Save : "Desa", +NewPage : "Nova Pàgina", +Preview : "Visualització prèvia", +Cut : "Retalla", +Copy : "Copia", +Paste : "Enganxa", +PasteText : "Enganxa com a text no formatat", +PasteWord : "Enganxa des del Word", +Print : "Imprimeix", +SelectAll : "Selecciona-ho tot", +RemoveFormat : "Elimina Format", +InsertLinkLbl : "Enllaç", +InsertLink : "Insereix/Edita enllaç", +RemoveLink : "Elimina l'enllaç", +VisitLink : "Obre l'enllaç", +Anchor : "Insereix/Edita àncora", +AnchorDelete : "Elimina àncora", +InsertImageLbl : "Imatge", +InsertImage : "Insereix/Edita imatge", +InsertFlashLbl : "Flash", +InsertFlash : "Insereix/Edita Flash", +InsertTableLbl : "Taula", +InsertTable : "Insereix/Edita taula", +InsertLineLbl : "Línia", +InsertLine : "Insereix línia horitzontal", +InsertSpecialCharLbl: "Caràcter Especial", +InsertSpecialChar : "Insereix caràcter especial", +InsertSmileyLbl : "Icona", +InsertSmiley : "Insereix icona", +About : "Quant a l'FCKeditor", +Bold : "Negreta", +Italic : "Cursiva", +Underline : "Subratllat", +StrikeThrough : "Barrat", +Subscript : "Subíndex", +Superscript : "Superíndex", +LeftJustify : "Alinia a l'esquerra", +CenterJustify : "Centrat", +RightJustify : "Alinia a la dreta", +BlockJustify : "Justificat", +DecreaseIndent : "Redueix el sagnat", +IncreaseIndent : "Augmenta el sagnat", +Blockquote : "Bloc de cita", +CreateDiv : "Crea un contenidor Div", +EditDiv : "Edita el contenidor Div", +DeleteDiv : "Elimina el contenidor Div", +Undo : "Desfés", +Redo : "Refés", +NumberedListLbl : "Llista numerada", +NumberedList : "Numeració activada/desactivada", +BulletedListLbl : "Llista de pics", +BulletedList : "Pics activats/descativats", +ShowTableBorders : "Mostra les vores de les taules", +ShowDetails : "Mostra detalls", +Style : "Estil", +FontFormat : "Format", +Font : "Tipus de lletra", +FontSize : "Mida", +TextColor : "Color de Text", +BGColor : "Color de Fons", +Source : "Codi font", +Find : "Cerca", +Replace : "Reemplaça", +SpellCheck : "Revisa l'ortografia", +UniversalKeyboard : "Teclat universal", +PageBreakLbl : "Salt de pàgina", +PageBreak : "Insereix salt de pàgina", + +Form : "Formulari", +Checkbox : "Casella de verificació", +RadioButton : "Botó d'opció", +TextField : "Camp de text", +Textarea : "Àrea de text", +HiddenField : "Camp ocult", +Button : "Botó", +SelectionField : "Camp de selecció", +ImageButton : "Botó d'imatge", + +FitWindow : "Maximiza la mida de l'editor", +ShowBlocks : "Mostra els blocs", + +// Context Menu +EditLink : "Edita l'enllaç", +CellCM : "Cel·la", +RowCM : "Fila", +ColumnCM : "Columna", +InsertRowAfter : "Insereix fila darrera", +InsertRowBefore : "Insereix fila abans de", +DeleteRows : "Suprimeix una fila", +InsertColumnAfter : "Insereix columna darrera", +InsertColumnBefore : "Insereix columna abans de", +DeleteColumns : "Suprimeix una columna", +InsertCellAfter : "Insereix cel·la darrera", +InsertCellBefore : "Insereix cel·la abans de", +DeleteCells : "Suprimeix les cel·les", +MergeCells : "Fusiona les cel·les", +MergeRight : "Fusiona cap a la dreta", +MergeDown : "Fusiona cap avall", +HorizontalSplitCell : "Divideix la cel·la horitzontalment", +VerticalSplitCell : "Divideix la cel·la verticalment", +TableDelete : "Suprimeix la taula", +CellProperties : "Propietats de la cel·la", +TableProperties : "Propietats de la taula", +ImageProperties : "Propietats de la imatge", +FlashProperties : "Propietats del Flash", + +AnchorProp : "Propietats de l'àncora", +ButtonProp : "Propietats del botó", +CheckboxProp : "Propietats de la casella de verificació", +HiddenFieldProp : "Propietats del camp ocult", +RadioButtonProp : "Propietats del botó d'opció", +ImageButtonProp : "Propietats del botó d'imatge", +TextFieldProp : "Propietats del camp de text", +SelectionFieldProp : "Propietats del camp de selecció", +TextareaProp : "Propietats de l'àrea de text", +FormProp : "Propietats del formulari", + +FontFormats : "Normal;Formatejat;Adreça;Encapçalament 1;Encapçalament 2;Encapçalament 3;Encapçalament 4;Encapçalament 5;Encapçalament 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Processant XHTML. Si us plau esperi...", +Done : "Fet", +PasteWordConfirm : "El text que voleu enganxar sembla provenir de Word. Voleu netejar aquest text abans que sigui enganxat?", +NotCompatiblePaste : "Aquesta funció és disponible per a Internet Explorer versió 5.5 o superior. Voleu enganxar sense netejar?", +UnknownToolbarItem : "Element de la barra d'eines desconegut \"%1\"", +UnknownCommand : "Nom de comanda desconegut \"%1\"", +NotImplemented : "Mètode no implementat", +UnknownToolbarSet : "Conjunt de barra d'eines \"%1\" inexistent", +NoActiveX : "Les preferències del navegador poden limitar algunes funcions d'aquest editor. Cal habilitar l'opció \"Executa controls ActiveX i plug-ins\". Poden sorgir errors i poden faltar algunes funcions.", +BrowseServerBlocked : "El visualitzador de recursos no s'ha pogut obrir. Assegura't de que els bloquejos de finestres emergents estan desactivats.", +DialogBlocked : "No ha estat possible obrir una finestra de diàleg. Assegureu-vos que els bloquejos de finestres emergents estan desactivats.", +VisitLinkBlocked : "No ha estat possible obrir una nova finestra. Assegureu-vos que els bloquejos de finestres emergents estan desactivats.", + +// Dialogs +DlgBtnOK : "D'acord", +DlgBtnCancel : "Cancel·la", +DlgBtnClose : "Tanca", +DlgBtnBrowseServer : "Veure servidor", +DlgAdvancedTag : "Avançat", +DlgOpOther : "Altres", +DlgInfoTab : "Info", +DlgAlertUrl : "Si us plau, afegiu la URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Direcció de l'idioma", +DlgGenLangDirLtr : "D'esquerra a dreta (LTR)", +DlgGenLangDirRtl : "De dreta a esquerra (RTL)", +DlgGenLangCode : "Codi d'idioma", +DlgGenAccessKey : "Clau d'accés", +DlgGenName : "Nom", +DlgGenTabIndex : "Index de Tab", +DlgGenLongDescr : "Descripció llarga de la URL", +DlgGenClass : "Classes del full d'estil", +DlgGenTitle : "Títol consultiu", +DlgGenContType : "Tipus de contingut consultiu", +DlgGenLinkCharset : "Conjunt de caràcters font enllaçat", +DlgGenStyle : "Estil", + +// Image Dialog +DlgImgTitle : "Propietats de la imatge", +DlgImgInfoTab : "Informació de la imatge", +DlgImgBtnUpload : "Envia-la al servidor", +DlgImgURL : "URL", +DlgImgUpload : "Puja", +DlgImgAlt : "Text alternatiu", +DlgImgWidth : "Amplada", +DlgImgHeight : "Alçada", +DlgImgLockRatio : "Bloqueja les proporcions", +DlgBtnResetSize : "Restaura la mida", +DlgImgBorder : "Vora", +DlgImgHSpace : "Espaiat horit.", +DlgImgVSpace : "Espaiat vert.", +DlgImgAlign : "Alineació", +DlgImgAlignLeft : "Ajusta a l'esquerra", +DlgImgAlignAbsBottom: "Abs Bottom", +DlgImgAlignAbsMiddle: "Abs Middle", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Bottom", +DlgImgAlignMiddle : "Middle", +DlgImgAlignRight : "Ajusta a la dreta", +DlgImgAlignTextTop : "Text Top", +DlgImgAlignTop : "Top", +DlgImgPreview : "Vista prèvia", +DlgImgAlertUrl : "Si us plau, escriviu la URL de la imatge", +DlgImgLinkTab : "Enllaç", + +// Flash Dialog +DlgFlashTitle : "Propietats del Flash", +DlgFlashChkPlay : "Reprodució automàtica", +DlgFlashChkLoop : "Bucle", +DlgFlashChkMenu : "Habilita menú Flash", +DlgFlashScale : "Escala", +DlgFlashScaleAll : "Mostra-ho tot", +DlgFlashScaleNoBorder : "Sense vores", +DlgFlashScaleFit : "Mida exacta", + +// Link Dialog +DlgLnkWindowTitle : "Enllaç", +DlgLnkInfoTab : "Informació de l'enllaç", +DlgLnkTargetTab : "Destí", + +DlgLnkType : "Tipus d'enllaç", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Àncora en aquesta pàgina", +DlgLnkTypeEMail : "Correu electrònic", +DlgLnkProto : "Protocol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Selecciona una àncora", +DlgLnkAnchorByName : "Per nom d'àncora", +DlgLnkAnchorById : "Per Id d'element", +DlgLnkNoAnchors : "(No hi ha àncores disponibles en aquest document)", +DlgLnkEMail : "Adreça de correu electrònic", +DlgLnkEMailSubject : "Assumpte del missatge", +DlgLnkEMailBody : "Cos del missatge", +DlgLnkUpload : "Puja", +DlgLnkBtnUpload : "Envia al servidor", + +DlgLnkTarget : "Destí", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nova finestra (_blank)", +DlgLnkTargetParent : "Finestra pare (_parent)", +DlgLnkTargetSelf : "Mateixa finestra (_self)", +DlgLnkTargetTop : "Finestra Major (_top)", +DlgLnkTargetFrameName : "Nom del marc de destí", +DlgLnkPopWinName : "Nom finestra popup", +DlgLnkPopWinFeat : "Característiques finestra popup", +DlgLnkPopResize : "Redimensionable", +DlgLnkPopLocation : "Barra d'adreça", +DlgLnkPopMenu : "Barra de menú", +DlgLnkPopScroll : "Barres d'scroll", +DlgLnkPopStatus : "Barra d'estat", +DlgLnkPopToolbar : "Barra d'eines", +DlgLnkPopFullScrn : "Pantalla completa (IE)", +DlgLnkPopDependent : "Depenent (Netscape)", +DlgLnkPopWidth : "Amplada", +DlgLnkPopHeight : "Alçada", +DlgLnkPopLeft : "Posició esquerra", +DlgLnkPopTop : "Posició dalt", + +DlnLnkMsgNoUrl : "Si us plau, escrigui l'enllaç URL", +DlnLnkMsgNoEMail : "Si us plau, escrigui l'adreça correu electrònic", +DlnLnkMsgNoAnchor : "Si us plau, escrigui l'àncora", +DlnLnkMsgInvPopName : "El nom de la finestra emergent ha de començar amb una lletra i no pot tenir espais", + +// Color Dialog +DlgColorTitle : "Selecciona el color", +DlgColorBtnClear : "Neteja", +DlgColorHighlight : "Realça", +DlgColorSelected : "Selecciona", + +// Smiley Dialog +DlgSmileyTitle : "Insereix una icona", + +// Special Character Dialog +DlgSpecialCharTitle : "Selecciona el caràcter especial", + +// Table Dialog +DlgTableTitle : "Propietats de la taula", +DlgTableRows : "Files", +DlgTableColumns : "Columnes", +DlgTableBorder : "Mida vora", +DlgTableAlign : "Alineació", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Esquerra", +DlgTableAlignCenter : "Centre", +DlgTableAlignRight : "Dreta", +DlgTableWidth : "Amplada", +DlgTableWidthPx : "píxels", +DlgTableWidthPc : "percentatge", +DlgTableHeight : "Alçada", +DlgTableCellSpace : "Espaiat de cel·les", +DlgTableCellPad : "Encoixinament de cel·les", +DlgTableCaption : "Títol", +DlgTableSummary : "Resum", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Propietats de la cel·la", +DlgCellWidth : "Amplada", +DlgCellWidthPx : "píxels", +DlgCellWidthPc : "percentatge", +DlgCellHeight : "Alçada", +DlgCellWordWrap : "Ajust de paraula", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Si", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Alineació horitzontal", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Esquerra", +DlgCellHorAlignCenter : "Centre", +DlgCellHorAlignRight: "Dreta", +DlgCellVerAlign : "Alineació vertical", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Top", +DlgCellVerAlignMiddle : "Middle", +DlgCellVerAlignBottom : "Bottom", +DlgCellVerAlignBaseline : "Baseline", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Rows Span", +DlgCellCollSpan : "Columns Span", +DlgCellBackColor : "Color de fons", +DlgCellBorderColor : "Color de la vora", +DlgCellBtnSelect : "Seleccioneu...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Cerca i reemplaça", + +// Find Dialog +DlgFindTitle : "Cerca", +DlgFindFindBtn : "Cerca", +DlgFindNotFoundMsg : "El text especificat no s'ha trobat.", + +// Replace Dialog +DlgReplaceTitle : "Reemplaça", +DlgReplaceFindLbl : "Cerca:", +DlgReplaceReplaceLbl : "Remplaça amb:", +DlgReplaceCaseChk : "Distingeix majúscules/minúscules", +DlgReplaceReplaceBtn : "Reemplaça", +DlgReplaceReplAllBtn : "Reemplaça-ho tot", +DlgReplaceWordChk : "Només paraules completes", + +// Paste Operations / Dialog +PasteErrorCut : "La seguretat del vostre navegador no permet executar automàticament les operacions de retallar. Si us plau, utilitzeu el teclat (Ctrl+X).", +PasteErrorCopy : "La seguretat del vostre navegador no permet executar automàticament les operacions de copiar. Si us plau, utilitzeu el teclat (Ctrl+C).", + +PasteAsText : "Enganxa com a text no formatat", +PasteFromWord : "Enganxa com a Word", + +DlgPasteMsg2 : "Si us plau, enganxeu dins del següent camp utilitzant el teclat (Ctrl+V) i premeu OK.", +DlgPasteSec : "A causa de la configuració de seguretat del vostre navegador, l'editor no pot accedir al porta-retalls directament. Enganxeu-ho un altre cop en aquesta finestra.", +DlgPasteIgnoreFont : "Ignora definicions de font", +DlgPasteRemoveStyles : "Elimina definicions d'estil", + +// Color Picker +ColorAutomatic : "Automàtic", +ColorMoreColors : "Més colors...", + +// Document Properties +DocProps : "Propietats del document", + +// Anchor Dialog +DlgAnchorTitle : "Propietats de l'àncora", +DlgAnchorName : "Nom de l'àncora", +DlgAnchorErrorName : "Si us plau, escriviu el nom de l'ancora", + +// Speller Pages Dialog +DlgSpellNotInDic : "No és al diccionari", +DlgSpellChangeTo : "Reemplaça amb", +DlgSpellBtnIgnore : "Ignora", +DlgSpellBtnIgnoreAll : "Ignora-les totes", +DlgSpellBtnReplace : "Canvia", +DlgSpellBtnReplaceAll : "Canvia-les totes", +DlgSpellBtnUndo : "Desfés", +DlgSpellNoSuggestions : "Cap suggeriment", +DlgSpellProgress : "Verificació ortogràfica en curs...", +DlgSpellNoMispell : "Verificació ortogràfica acabada: no hi ha cap paraula mal escrita", +DlgSpellNoChanges : "Verificació ortogràfica: no s'ha canviat cap paraula", +DlgSpellOneChange : "Verificació ortogràfica: s'ha canviat una paraula", +DlgSpellManyChanges : "Verificació ortogràfica: s'han canviat %1 paraules", + +IeSpellDownload : "Verificació ortogràfica no instal·lada. Voleu descarregar-ho ara?", + +// Button Dialog +DlgButtonText : "Text (Valor)", +DlgButtonType : "Tipus", +DlgButtonTypeBtn : "Botó", +DlgButtonTypeSbm : "Transmet formulari", +DlgButtonTypeRst : "Reinicia formulari", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nom", +DlgCheckboxValue : "Valor", +DlgCheckboxSelected : "Seleccionat", + +// Form Dialog +DlgFormName : "Nom", +DlgFormAction : "Acció", +DlgFormMethod : "Mètode", + +// Select Field Dialog +DlgSelectName : "Nom", +DlgSelectValue : "Valor", +DlgSelectSize : "Mida", +DlgSelectLines : "Línies", +DlgSelectChkMulti : "Permet múltiples seleccions", +DlgSelectOpAvail : "Opcions disponibles", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Valor", +DlgSelectBtnAdd : "Afegeix", +DlgSelectBtnModify : "Modifica", +DlgSelectBtnUp : "Amunt", +DlgSelectBtnDown : "Avall", +DlgSelectBtnSetValue : "Selecciona per defecte", +DlgSelectBtnDelete : "Elimina", + +// Textarea Dialog +DlgTextareaName : "Nom", +DlgTextareaCols : "Columnes", +DlgTextareaRows : "Files", + +// Text Field Dialog +DlgTextName : "Nom", +DlgTextValue : "Valor", +DlgTextCharWidth : "Amplada", +DlgTextMaxChars : "Nombre màxim de caràcters", +DlgTextType : "Tipus", +DlgTextTypeText : "Text", +DlgTextTypePass : "Contrasenya", + +// Hidden Field Dialog +DlgHiddenName : "Nom", +DlgHiddenValue : "Valor", + +// Bulleted List Dialog +BulletedListProp : "Propietats de la llista de pics", +NumberedListProp : "Propietats de llista numerada", +DlgLstStart : "Inici", +DlgLstType : "Tipus", +DlgLstTypeCircle : "Cercle", +DlgLstTypeDisc : "Disc", +DlgLstTypeSquare : "Quadrat", +DlgLstTypeNumbers : "Números (1, 2, 3)", +DlgLstTypeLCase : "Lletres minúscules (a, b, c)", +DlgLstTypeUCase : "Lletres majúscules (A, B, C)", +DlgLstTypeSRoman : "Números romans en minúscules (i, ii, iii)", +DlgLstTypeLRoman : "Números romans en majúscules (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "General", +DlgDocBackTab : "Fons", +DlgDocColorsTab : "Colors i marges", +DlgDocMetaTab : "Metadades", + +DlgDocPageTitle : "Títol de la pàgina", +DlgDocLangDir : "Direcció idioma", +DlgDocLangDirLTR : "Esquerra a dreta (LTR)", +DlgDocLangDirRTL : "Dreta a esquerra (RTL)", +DlgDocLangCode : "Codi d'idioma", +DlgDocCharSet : "Codificació de conjunt de caràcters", +DlgDocCharSetCE : "Centreeuropeu", +DlgDocCharSetCT : "Xinès tradicional (Big5)", +DlgDocCharSetCR : "Ciríl·lic", +DlgDocCharSetGR : "Grec", +DlgDocCharSetJP : "Japonès", +DlgDocCharSetKR : "Coreà", +DlgDocCharSetTR : "Turc", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Europeu occidental", +DlgDocCharSetOther : "Una altra codificació de caràcters", + +DlgDocDocType : "Capçalera de tipus de document", +DlgDocDocTypeOther : "Un altra capçalera de tipus de document", +DlgDocIncXHTML : "Incloure declaracions XHTML", +DlgDocBgColor : "Color de fons", +DlgDocBgImage : "URL de la imatge de fons", +DlgDocBgNoScroll : "Fons fixe", +DlgDocCText : "Text", +DlgDocCLink : "Enllaç", +DlgDocCVisited : "Enllaç visitat", +DlgDocCActive : "Enllaç actiu", +DlgDocMargins : "Marges de pàgina", +DlgDocMaTop : "Cap", +DlgDocMaLeft : "Esquerra", +DlgDocMaRight : "Dreta", +DlgDocMaBottom : "Peu", +DlgDocMeIndex : "Mots clau per a indexació (separats per coma)", +DlgDocMeDescr : "Descripció del document", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Vista prèvia", + +// Templates Dialog +Templates : "Plantilles", +DlgTemplatesTitle : "Contingut plantilles", +DlgTemplatesSelMsg : "Si us plau, seleccioneu la plantilla per obrir a l'editor
    (el contingut actual no serà enregistrat):", +DlgTemplatesLoading : "Carregant la llista de plantilles. Si us plau, espereu...", +DlgTemplatesNoTpl : "(No hi ha plantilles definides)", +DlgTemplatesReplace : "Reemplaça el contingut actual", + +// About Dialog +DlgAboutAboutTab : "Quant a", +DlgAboutBrowserInfoTab : "Informació del navegador", +DlgAboutLicenseTab : "Llicència", +DlgAboutVersion : "versió", +DlgAboutInfo : "Per a més informació aneu a", + +// Div Dialog +DlgDivGeneralTab : "General", +DlgDivAdvancedTab : "Avançat", +DlgDivStyle : "Estil", +DlgDivInlineStyle : "Estil en línia", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/cs.js b/www/js/FCKeditor/editor/lang/cs.js new file mode 100644 index 0000000..52fb6b1 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/cs.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Czech language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Skrýt panel nástrojů", +ToolbarExpand : "Zobrazit panel nástrojů", + +// Toolbar Items and Context Menu +Save : "Uložit", +NewPage : "Nová stránka", +Preview : "Náhled", +Cut : "Vyjmout", +Copy : "Kopírovat", +Paste : "Vložit", +PasteText : "Vložit jako Äistý text", +PasteWord : "Vložit z Wordu", +Print : "Tisk", +SelectAll : "Vybrat vÅ¡e", +RemoveFormat : "Odstranit formátování", +InsertLinkLbl : "Odkaz", +InsertLink : "Vložit/zmÄ›nit odkaz", +RemoveLink : "Odstranit odkaz", +VisitLink : "Otevřít odkaz", +Anchor : "Vložít/zmÄ›nit záložku", +AnchorDelete : "Odstranit kotvu", +InsertImageLbl : "Obrázek", +InsertImage : "Vložit/zmÄ›nit obrázek", +InsertFlashLbl : "Flash", +InsertFlash : "Vložit/Upravit Flash", +InsertTableLbl : "Tabulka", +InsertTable : "Vložit/zmÄ›nit tabulku", +InsertLineLbl : "Linka", +InsertLine : "Vložit vodorovnou linku", +InsertSpecialCharLbl: "Speciální znaky", +InsertSpecialChar : "Vložit speciální znaky", +InsertSmileyLbl : "Smajlíky", +InsertSmiley : "Vložit smajlík", +About : "O aplikaci FCKeditor", +Bold : "TuÄné", +Italic : "Kurzíva", +Underline : "Podtržené", +StrikeThrough : "PÅ™eÅ¡krtnuté", +Subscript : "Dolní index", +Superscript : "Horní index", +LeftJustify : "Zarovnat vlevo", +CenterJustify : "Zarovnat na stÅ™ed", +RightJustify : "Zarovnat vpravo", +BlockJustify : "Zarovnat do bloku", +DecreaseIndent : "ZmenÅ¡it odsazení", +IncreaseIndent : "ZvÄ›tÅ¡it odsazení", +Blockquote : "Citace", +CreateDiv : "VytvoÅ™it Div kontejner", +EditDiv : "Upravit Div kontejner", +DeleteDiv : "Odstranit Div kontejner", +Undo : "ZpÄ›t", +Redo : "Znovu", +NumberedListLbl : "Číslování", +NumberedList : "Vložit/odstranit Äíslovaný seznam", +BulletedListLbl : "Odrážky", +BulletedList : "Vložit/odstranit odrážky", +ShowTableBorders : "Zobrazit okraje tabulek", +ShowDetails : "Zobrazit podrobnosti", +Style : "Styl", +FontFormat : "Formát", +Font : "Písmo", +FontSize : "Velikost", +TextColor : "Barva textu", +BGColor : "Barva pozadí", +Source : "Zdroj", +Find : "Hledat", +Replace : "Nahradit", +SpellCheck : "Zkontrolovat pravopis", +UniversalKeyboard : "Univerzální klávesnice", +PageBreakLbl : "Konec stránky", +PageBreak : "Vložit konec stránky", + +Form : "Formulář", +Checkbox : "ZaÅ¡krtávací políÄko", +RadioButton : "PÅ™epínaÄ", +TextField : "Textové pole", +Textarea : "Textová oblast", +HiddenField : "Skryté pole", +Button : "TlaÄítko", +SelectionField : "Seznam", +ImageButton : "Obrázkové tlaÄítko", + +FitWindow : "Maximalizovat velikost editoru", +ShowBlocks : "Ukázat bloky", + +// Context Menu +EditLink : "ZmÄ›nit odkaz", +CellCM : "Buňka", +RowCM : "Řádek", +ColumnCM : "Sloupec", +InsertRowAfter : "Vložit řádek za", +InsertRowBefore : "Vložit řádek pÅ™ed", +DeleteRows : "Smazat řádky", +InsertColumnAfter : "Vložit sloupec za", +InsertColumnBefore : "Vložit sloupec pÅ™ed", +DeleteColumns : "Smazat sloupec", +InsertCellAfter : "Vložit buňku za", +InsertCellBefore : "Vložit buňku pÅ™ed", +DeleteCells : "Smazat buňky", +MergeCells : "SlouÄit buňky", +MergeRight : "SlouÄit doprava", +MergeDown : "SlouÄit dolů", +HorizontalSplitCell : "RozdÄ›lit buňky vodorovnÄ›", +VerticalSplitCell : "RozdÄ›lit buňky svisle", +TableDelete : "Smazat tabulku", +CellProperties : "Vlastnosti buňky", +TableProperties : "Vlastnosti tabulky", +ImageProperties : "Vlastnosti obrázku", +FlashProperties : "Vlastnosti Flashe", + +AnchorProp : "Vlastnosti záložky", +ButtonProp : "Vlastnosti tlaÄítka", +CheckboxProp : "Vlastnosti zaÅ¡krtávacího políÄka", +HiddenFieldProp : "Vlastnosti skrytého pole", +RadioButtonProp : "Vlastnosti pÅ™epínaÄe", +ImageButtonProp : "Vlastností obrázkového tlaÄítka", +TextFieldProp : "Vlastnosti textového pole", +SelectionFieldProp : "Vlastnosti seznamu", +TextareaProp : "Vlastnosti textové oblasti", +FormProp : "Vlastnosti formuláře", + +FontFormats : "Normální;Naformátováno;Adresa;Nadpis 1;Nadpis 2;Nadpis 3;Nadpis 4;Nadpis 5;Nadpis 6;Normální (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Probíhá zpracování XHTML. Prosím Äekejte...", +Done : "Hotovo", +PasteWordConfirm : "Jak je vidÄ›t, vkládaný text je kopírován z Wordu. Chcete jej pÅ™ed vložením vyÄistit?", +NotCompatiblePaste : "Tento příkaz je dostupný pouze v Internet Exploreru verze 5.5 nebo vyšší. Chcete vložit text bez vyÄiÅ¡tÄ›ní?", +UnknownToolbarItem : "Neznámá položka panelu nástrojů \"%1\"", +UnknownCommand : "Neznámý příkaz \"%1\"", +NotImplemented : "Příkaz není implementován", +UnknownToolbarSet : "Panel nástrojů \"%1\" neexistuje", +NoActiveX : "Nastavení bezpeÄnosti VaÅ¡eho prohlížeÄe omezuje funkÄnost nÄ›kterých jeho možností. Je tÅ™eba zapnout volbu \"SpouÅ¡tÄ›t ovládáací prvky ActiveX a moduly plug-in\", jinak nebude možné využívat vÅ¡echny dosputné schopnosti editoru.", +BrowseServerBlocked : "Průzkumník zdrojů nelze otevřít. Prověřte, zda nemáte aktivováno blokování popup oken.", +DialogBlocked : "Nelze otevřít dialogové okno. Prověřte, zda nemáte aktivováno blokování popup oken.", +VisitLinkBlocked : "Není možné otevřít nové okno. Prověřte, zda vÅ¡echny nástroje pro blokování vyskakovacích oken jsou vypnuty.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Storno", +DlgBtnClose : "Zavřít", +DlgBtnBrowseServer : "Vybrat na serveru", +DlgAdvancedTag : "Rozšířené", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Prosím vložte URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Orientace jazyka", +DlgGenLangDirLtr : "Zleva do prava (LTR)", +DlgGenLangDirRtl : "Zprava do leva (RTL)", +DlgGenLangCode : "Kód jazyka", +DlgGenAccessKey : "Přístupový klíÄ", +DlgGenName : "Jméno", +DlgGenTabIndex : "PoÅ™adí prvku", +DlgGenLongDescr : "Dlouhý popis URL", +DlgGenClass : "Třída stylu", +DlgGenTitle : "Pomocný titulek", +DlgGenContType : "Pomocný typ obsahu", +DlgGenLinkCharset : "PÅ™iÅ™azená znaková sada", +DlgGenStyle : "Styl", + +// Image Dialog +DlgImgTitle : "Vlastnosti obrázku", +DlgImgInfoTab : "Informace o obrázku", +DlgImgBtnUpload : "Odeslat na server", +DlgImgURL : "URL", +DlgImgUpload : "Odeslat", +DlgImgAlt : "Alternativní text", +DlgImgWidth : "Šířka", +DlgImgHeight : "Výška", +DlgImgLockRatio : "Zámek", +DlgBtnResetSize : "Původní velikost", +DlgImgBorder : "Okraje", +DlgImgHSpace : "H-mezera", +DlgImgVSpace : "V-mezera", +DlgImgAlign : "Zarovnání", +DlgImgAlignLeft : "Vlevo", +DlgImgAlignAbsBottom: "Zcela dolů", +DlgImgAlignAbsMiddle: "DoprostÅ™ed", +DlgImgAlignBaseline : "Na úÄaří", +DlgImgAlignBottom : "Dolů", +DlgImgAlignMiddle : "Na stÅ™ed", +DlgImgAlignRight : "Vpravo", +DlgImgAlignTextTop : "Na horní okraj textu", +DlgImgAlignTop : "Nahoru", +DlgImgPreview : "Náhled", +DlgImgAlertUrl : "Zadejte prosím URL obrázku", +DlgImgLinkTab : "Odkaz", + +// Flash Dialog +DlgFlashTitle : "Vlastnosti Flashe", +DlgFlashChkPlay : "Automatické spuÅ¡tÄ›ní", +DlgFlashChkLoop : "Opakování", +DlgFlashChkMenu : "Nabídka Flash", +DlgFlashScale : "Zobrazit", +DlgFlashScaleAll : "Zobrazit vÅ¡e", +DlgFlashScaleNoBorder : "Bez okraje", +DlgFlashScaleFit : "PÅ™izpůsobit", + +// Link Dialog +DlgLnkWindowTitle : "Odkaz", +DlgLnkInfoTab : "Informace o odkazu", +DlgLnkTargetTab : "Cíl", + +DlgLnkType : "Typ odkazu", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Kotva v této stránce", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protokol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Vybrat kotvu", +DlgLnkAnchorByName : "Podle jména kotvy", +DlgLnkAnchorById : "Podle Id objektu", +DlgLnkNoAnchors : "(Ve stránce není definována žádná kotva!)", +DlgLnkEMail : "E-Mailová adresa", +DlgLnkEMailSubject : "PÅ™edmÄ›t zprávy", +DlgLnkEMailBody : "TÄ›lo zprávy", +DlgLnkUpload : "Odeslat", +DlgLnkBtnUpload : "Odeslat na Server", + +DlgLnkTarget : "Cíl", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nové okno (_blank)", +DlgLnkTargetParent : "RodiÄovské okno (_parent)", +DlgLnkTargetSelf : "Stejné okno (_self)", +DlgLnkTargetTop : "Hlavní okno (_top)", +DlgLnkTargetFrameName : "Název cílového rámu", +DlgLnkPopWinName : "Název vyskakovacího okna", +DlgLnkPopWinFeat : "Vlastnosti vyskakovacího okna", +DlgLnkPopResize : "MÄ›nitelná velikost", +DlgLnkPopLocation : "Panel umístÄ›ní", +DlgLnkPopMenu : "Panel nabídky", +DlgLnkPopScroll : "Posuvníky", +DlgLnkPopStatus : "Stavový řádek", +DlgLnkPopToolbar : "Panel nástrojů", +DlgLnkPopFullScrn : "Celá obrazovka (IE)", +DlgLnkPopDependent : "Závislost (Netscape)", +DlgLnkPopWidth : "Šířka", +DlgLnkPopHeight : "Výška", +DlgLnkPopLeft : "Levý okraj", +DlgLnkPopTop : "Horní okraj", + +DlnLnkMsgNoUrl : "Zadejte prosím URL odkazu", +DlnLnkMsgNoEMail : "Zadejte prosím e-mailovou adresu", +DlnLnkMsgNoAnchor : "Vyberte prosím kotvu", +DlnLnkMsgInvPopName : "Název vyskakovacího okna musí zaÄínat písmenem a nesmí obsahovat mezery", + +// Color Dialog +DlgColorTitle : "VýbÄ›r barvy", +DlgColorBtnClear : "Vymazat", +DlgColorHighlight : "ZvýraznÄ›ná", +DlgColorSelected : "Vybraná", + +// Smiley Dialog +DlgSmileyTitle : "Vkládání smajlíků", + +// Special Character Dialog +DlgSpecialCharTitle : "VýbÄ›r speciálního znaku", + +// Table Dialog +DlgTableTitle : "Vlastnosti tabulky", +DlgTableRows : "Řádky", +DlgTableColumns : "Sloupce", +DlgTableBorder : "OhraniÄení", +DlgTableAlign : "Zarovnání", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Vlevo", +DlgTableAlignCenter : "Na stÅ™ed", +DlgTableAlignRight : "Vpravo", +DlgTableWidth : "Šířka", +DlgTableWidthPx : "bodů", +DlgTableWidthPc : "procent", +DlgTableHeight : "Výška", +DlgTableCellSpace : "Vzdálenost bunÄ›k", +DlgTableCellPad : "Odsazení obsahu", +DlgTableCaption : "Popis", +DlgTableSummary : "Souhrn", +DlgTableHeaders : "Záhlaví", +DlgTableHeadersNone : "Žádné", +DlgTableHeadersColumn : "První sloupec", +DlgTableHeadersRow : "První řádek", +DlgTableHeadersBoth : "Oboje", + +// Table Cell Dialog +DlgCellTitle : "Vlastnosti buňky", +DlgCellWidth : "Šířka", +DlgCellWidthPx : "bodů", +DlgCellWidthPc : "procent", +DlgCellHeight : "Výška", +DlgCellWordWrap : "Zalamování", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Ano", +DlgCellWordWrapNo : "Ne", +DlgCellHorAlign : "Vodorovné zarovnání", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Vlevo", +DlgCellHorAlignCenter : "Na stÅ™ed", +DlgCellHorAlignRight: "Vpravo", +DlgCellVerAlign : "Svislé zarovnání", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Nahoru", +DlgCellVerAlignMiddle : "DoprostÅ™ed", +DlgCellVerAlignBottom : "Dolů", +DlgCellVerAlignBaseline : "Na úÄaří", +DlgCellType : "Typ buňky", +DlgCellTypeData : "Data", +DlgCellTypeHeader : "Zálaví", +DlgCellRowSpan : "SlouÄené řádky", +DlgCellCollSpan : "SlouÄené sloupce", +DlgCellBackColor : "Barva pozadí", +DlgCellBorderColor : "Barva ohraniÄení", +DlgCellBtnSelect : "VýbÄ›r...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Najít a nahradit", + +// Find Dialog +DlgFindTitle : "Hledat", +DlgFindFindBtn : "Hledat", +DlgFindNotFoundMsg : "Hledaný text nebyl nalezen.", + +// Replace Dialog +DlgReplaceTitle : "Nahradit", +DlgReplaceFindLbl : "Co hledat:", +DlgReplaceReplaceLbl : "Čím nahradit:", +DlgReplaceCaseChk : "RozliÅ¡ovat velikost písma", +DlgReplaceReplaceBtn : "Nahradit", +DlgReplaceReplAllBtn : "Nahradit vÅ¡e", +DlgReplaceWordChk : "Pouze celá slova", + +// Paste Operations / Dialog +PasteErrorCut : "BezpeÄnostní nastavení VaÅ¡eho prohlížeÄe nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjmÄ›te zvolený text do schránky pomocí klávesnice (Ctrl+X).", +PasteErrorCopy : "BezpeÄnostní nastavení VaÅ¡eho prohlížeÄe nedovolují editoru spustit funkci pro kopírování zvoleného textu do schránky. Prosím zkopírujte zvolený text do schránky pomocí klávesnice (Ctrl+C).", + +PasteAsText : "Vložit jako Äistý text", +PasteFromWord : "Vložit text z Wordu", + +DlgPasteMsg2 : "Do následujícího pole vložte požadovaný obsah pomocí klávesnice (Ctrl+V) a stisknÄ›te OK.", +DlgPasteSec : "Z důvodů nastavení bezpeÄnosti VaÅ¡eho prohlížeÄe nemůže editor pÅ™istupovat přímo do schránky. Obsah schránky prosím vložte znovu do tohoto okna.", +DlgPasteIgnoreFont : "Ignorovat písmo", +DlgPasteRemoveStyles : "Odstranit styly", + +// Color Picker +ColorAutomatic : "Automaticky", +ColorMoreColors : "Více barev...", + +// Document Properties +DocProps : "Vlastnosti dokumentu", + +// Anchor Dialog +DlgAnchorTitle : "Vlastnosti záložky", +DlgAnchorName : "Název záložky", +DlgAnchorErrorName : "Zadejte prosím název záložky", + +// Speller Pages Dialog +DlgSpellNotInDic : "Není ve slovníku", +DlgSpellChangeTo : "ZmÄ›nit na", +DlgSpellBtnIgnore : "PÅ™eskoÄit", +DlgSpellBtnIgnoreAll : "PÅ™eskakovat vÅ¡e", +DlgSpellBtnReplace : "ZamÄ›nit", +DlgSpellBtnReplaceAll : "Zaměňovat vÅ¡e", +DlgSpellBtnUndo : "ZpÄ›t", +DlgSpellNoSuggestions : "- žádné návrhy -", +DlgSpellProgress : "Probíhá kontrola pravopisu...", +DlgSpellNoMispell : "Kontrola pravopisu dokonÄena: Žádné pravopisné chyby nenalezeny", +DlgSpellNoChanges : "Kontrola pravopisu dokonÄena: Beze zmÄ›n", +DlgSpellOneChange : "Kontrola pravopisu dokonÄena: Jedno slovo zmÄ›nÄ›no", +DlgSpellManyChanges : "Kontrola pravopisu dokonÄena: %1 slov zmÄ›nÄ›no", + +IeSpellDownload : "Kontrola pravopisu není nainstalována. Chcete ji nyní stáhnout?", + +// Button Dialog +DlgButtonText : "Popisek", +DlgButtonType : "Typ", +DlgButtonTypeBtn : "TlaÄítko", +DlgButtonTypeSbm : "Odeslat", +DlgButtonTypeRst : "Obnovit", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Název", +DlgCheckboxValue : "Hodnota", +DlgCheckboxSelected : "ZaÅ¡krtnuto", + +// Form Dialog +DlgFormName : "Název", +DlgFormAction : "Akce", +DlgFormMethod : "Metoda", + +// Select Field Dialog +DlgSelectName : "Název", +DlgSelectValue : "Hodnota", +DlgSelectSize : "Velikost", +DlgSelectLines : "Řádků", +DlgSelectChkMulti : "Povolit mnohonásobné výbÄ›ry", +DlgSelectOpAvail : "Dostupná nastavení", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Hodnota", +DlgSelectBtnAdd : "PÅ™idat", +DlgSelectBtnModify : "ZmÄ›nit", +DlgSelectBtnUp : "Nahoru", +DlgSelectBtnDown : "Dolů", +DlgSelectBtnSetValue : "Nastavit jako vybranou hodnotu", +DlgSelectBtnDelete : "Smazat", + +// Textarea Dialog +DlgTextareaName : "Název", +DlgTextareaCols : "Sloupců", +DlgTextareaRows : "Řádků", + +// Text Field Dialog +DlgTextName : "Název", +DlgTextValue : "Hodnota", +DlgTextCharWidth : "Šířka ve znacích", +DlgTextMaxChars : "Maximální poÄet znaků", +DlgTextType : "Typ", +DlgTextTypeText : "Text", +DlgTextTypePass : "Heslo", + +// Hidden Field Dialog +DlgHiddenName : "Název", +DlgHiddenValue : "Hodnota", + +// Bulleted List Dialog +BulletedListProp : "Vlastnosti odrážek", +NumberedListProp : "Vlastnosti Äíslovaného seznamu", +DlgLstStart : "ZaÄátek", +DlgLstType : "Typ", +DlgLstTypeCircle : "Kružnice", +DlgLstTypeDisc : "Kruh", +DlgLstTypeSquare : "ÄŒtverec", +DlgLstTypeNumbers : "Čísla (1, 2, 3)", +DlgLstTypeLCase : "Malá písmena (a, b, c)", +DlgLstTypeUCase : "Velká písmena (A, B, C)", +DlgLstTypeSRoman : "Malé římská Äíslice (i, ii, iii)", +DlgLstTypeLRoman : "Velké římské Äíslice (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Obecné", +DlgDocBackTab : "Pozadí", +DlgDocColorsTab : "Barvy a okraje", +DlgDocMetaTab : "Metadata", + +DlgDocPageTitle : "Titulek stránky", +DlgDocLangDir : "SmÄ›r jazyku", +DlgDocLangDirLTR : "Zleva do prava ", +DlgDocLangDirRTL : "Zprava doleva", +DlgDocLangCode : "Kód jazyku", +DlgDocCharSet : "Znaková sada", +DlgDocCharSetCE : "StÅ™edoevropské jazyky", +DlgDocCharSetCT : "TradiÄní ÄínÅ¡tina (Big5)", +DlgDocCharSetCR : "Cyrilice", +DlgDocCharSetGR : "ŘeÄtina", +DlgDocCharSetJP : "JaponÅ¡tina", +DlgDocCharSetKR : "KorejÅ¡tina", +DlgDocCharSetTR : "TureÄtina", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Západoevropské jazyky", +DlgDocCharSetOther : "Další znaková sada", + +DlgDocDocType : "Typ dokumentu", +DlgDocDocTypeOther : "Jiný typ dokumetu", +DlgDocIncXHTML : "Zahrnou deklarace XHTML", +DlgDocBgColor : "Barva pozadí", +DlgDocBgImage : "URL obrázku na pozadí", +DlgDocBgNoScroll : "Nerolovatelné pozadí", +DlgDocCText : "Text", +DlgDocCLink : "Odkaz", +DlgDocCVisited : "NavÅ¡tívený odkaz", +DlgDocCActive : "Vybraný odkaz", +DlgDocMargins : "Okraje stránky", +DlgDocMaTop : "Horní", +DlgDocMaLeft : "Levý", +DlgDocMaRight : "Pravý", +DlgDocMaBottom : "Dolní", +DlgDocMeIndex : "KlíÄová slova (oddÄ›lená Äárkou)", +DlgDocMeDescr : "Popis dokumentu", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Autorská práva", +DlgDocPreview : "Náhled", + +// Templates Dialog +Templates : "Å ablony", +DlgTemplatesTitle : "Å ablony obsahu", +DlgTemplatesSelMsg : "Prosím zvolte Å¡ablonu pro otevÅ™ení v editoru
    (aktuální obsah editoru bude ztracen):", +DlgTemplatesLoading : "Nahrávám pÅ™eheld Å¡ablon. Prosím Äekejte...", +DlgTemplatesNoTpl : "(Není definována žádná Å¡ablona)", +DlgTemplatesReplace : "Nahradit aktuální obsah", + +// About Dialog +DlgAboutAboutTab : "O aplikaci", +DlgAboutBrowserInfoTab : "Informace o prohlížeÄi", +DlgAboutLicenseTab : "Licence", +DlgAboutVersion : "verze", +DlgAboutInfo : "Více informací získáte na", + +// Div Dialog +DlgDivGeneralTab : "Obecné", +DlgDivAdvancedTab : "Rozšířené", +DlgDivStyle : "Styl", +DlgDivInlineStyle : "Vložený styl", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/da.js b/www/js/FCKeditor/editor/lang/da.js new file mode 100644 index 0000000..7c64135 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/da.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Danish language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Skjul værktøjslinier", +ToolbarExpand : "Vis værktøjslinier", + +// Toolbar Items and Context Menu +Save : "Gem", +NewPage : "Ny side", +Preview : "Vis eksempel", +Cut : "Klip", +Copy : "Kopier", +Paste : "Indsæt", +PasteText : "Indsæt som ikke-formateret tekst", +PasteWord : "Indsæt fra Word", +Print : "Udskriv", +SelectAll : "Vælg alt", +RemoveFormat : "Fjern formatering", +InsertLinkLbl : "Hyperlink", +InsertLink : "Indsæt/rediger hyperlink", +RemoveLink : "Fjern hyperlink", +VisitLink : "Ã…bn hyperlink", +Anchor : "Indsæt/rediger bogmærke", +AnchorDelete : "Fjern bogmærke", +InsertImageLbl : "Indsæt billede", +InsertImage : "Indsæt/rediger billede", +InsertFlashLbl : "Flash", +InsertFlash : "Indsæt/rediger Flash", +InsertTableLbl : "Table", +InsertTable : "Indsæt/rediger tabel", +InsertLineLbl : "Linie", +InsertLine : "Indsæt vandret linie", +InsertSpecialCharLbl: "Symbol", +InsertSpecialChar : "Indsæt symbol", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Indsæt smiley", +About : "Om FCKeditor", +Bold : "Fed", +Italic : "Kursiv", +Underline : "Understreget", +StrikeThrough : "Overstreget", +Subscript : "Sænket skrift", +Superscript : "Hævet skrift", +LeftJustify : "Venstrestillet", +CenterJustify : "Centreret", +RightJustify : "Højrestillet", +BlockJustify : "Lige margener", +DecreaseIndent : "Formindsk indrykning", +IncreaseIndent : "Forøg indrykning", +Blockquote : "Blokcitat", +CreateDiv : "Opret div container", +EditDiv : "Rediger div container", +DeleteDiv : "Fjern div container", +Undo : "Fortryd", +Redo : "Annuller fortryd", +NumberedListLbl : "Talopstilling", +NumberedList : "Indsæt/fjern talopstilling", +BulletedListLbl : "Punktopstilling", +BulletedList : "Indsæt/fjern punktopstilling", +ShowTableBorders : "Vis tabelkanter", +ShowDetails : "Vis detaljer", +Style : "Typografi", +FontFormat : "Formatering", +Font : "Skrifttype", +FontSize : "Skriftstørrelse", +TextColor : "Tekstfarve", +BGColor : "Baggrundsfarve", +Source : "Kilde", +Find : "Søg", +Replace : "Erstat", +SpellCheck : "Stavekontrol", +UniversalKeyboard : "Universaltastatur", +PageBreakLbl : "Sidskift", +PageBreak : "Indsæt sideskift", + +Form : "Indsæt formular", +Checkbox : "Indsæt afkrydsningsfelt", +RadioButton : "Indsæt alternativknap", +TextField : "Indsæt tekstfelt", +Textarea : "Indsæt tekstboks", +HiddenField : "Indsæt skjult felt", +Button : "Indsæt knap", +SelectionField : "Indsæt liste", +ImageButton : "Indsæt billedknap", + +FitWindow : "Maksimer editor vinduet", +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Rediger hyperlink", +CellCM : "Celle", +RowCM : "Række", +ColumnCM : "Kolonne", +InsertRowAfter : "Indsæt række efter", +InsertRowBefore : "Indsæt række før", +DeleteRows : "Slet række", +InsertColumnAfter : "Indsæt kolonne efter", +InsertColumnBefore : "Indsæt kolonne før", +DeleteColumns : "Slet kolonne", +InsertCellAfter : "Indsæt celle efter", +InsertCellBefore : "Indsæt celle før", +DeleteCells : "Slet celle", +MergeCells : "Flet celler", +MergeRight : "Flet til højre", +MergeDown : "Flet nedad", +HorizontalSplitCell : "Del celle vandret", +VerticalSplitCell : "Del celle lodret", +TableDelete : "Slet tabel", +CellProperties : "Egenskaber for celle", +TableProperties : "Egenskaber for tabel", +ImageProperties : "Egenskaber for billede", +FlashProperties : "Egenskaber for Flash", + +AnchorProp : "Egenskaber for bogmærke", +ButtonProp : "Egenskaber for knap", +CheckboxProp : "Egenskaber for afkrydsningsfelt", +HiddenFieldProp : "Egenskaber for skjult felt", +RadioButtonProp : "Egenskaber for alternativknap", +ImageButtonProp : "Egenskaber for billedknap", +TextFieldProp : "Egenskaber for tekstfelt", +SelectionFieldProp : "Egenskaber for liste", +TextareaProp : "Egenskaber for tekstboks", +FormProp : "Egenskaber for formular", + +FontFormats : "Normal;Formateret;Adresse;Overskrift 1;Overskrift 2;Overskrift 3;Overskrift 4;Overskrift 5;Overskrift 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Behandler XHTML...", +Done : "Færdig", +PasteWordConfirm : "Den tekst du forsøger at indsætte ser ud til at komme fra Word.
    Vil du rense teksten før den indsættes?", +NotCompatiblePaste : "Denne kommando er tilgændelig i Internet Explorer 5.5 eller senere.
    Vil du indsætte teksten uden at rense den ?", +UnknownToolbarItem : "Ukendt værktøjslinjeobjekt \"%1\"!", +UnknownCommand : "Ukendt kommandonavn \"%1\"!", +NotImplemented : "Kommandoen er ikke implementeret!", +UnknownToolbarSet : "Værktøjslinjen \"%1\" eksisterer ikke!", +NoActiveX : "Din browsers sikkerhedsindstillinger begrænser nogle af editorens muligheder.
    Slå \"Kør ActiveX-objekter og plug-ins\" til, ellers vil du opleve fejl og manglende muligheder.", +BrowseServerBlocked : "Browseren kunne ikke åbne de nødvendige ressourcer!
    Slå pop-up blokering fra.", +DialogBlocked : "Dialogvinduet kunne ikke åbnes!
    Slå pop-up blokering fra.", +VisitLinkBlocked : "Det var ikke muligt at åbne et nyt vindue. Tjek, at ingen popup-blokkere er aktive.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Annuller", +DlgBtnClose : "Luk", +DlgBtnBrowseServer : "Gennemse...", +DlgAdvancedTag : "Avanceret", +DlgOpOther : "", +DlgInfoTab : "Generelt", +DlgAlertUrl : "Indtast URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Tekstretning", +DlgGenLangDirLtr : "Fra venstre mod højre (LTR)", +DlgGenLangDirRtl : "Fra højre mod venstre (RTL)", +DlgGenLangCode : "Sprogkode", +DlgGenAccessKey : "Genvejstast", +DlgGenName : "Navn", +DlgGenTabIndex : "Tabulator indeks", +DlgGenLongDescr : "Udvidet beskrivelse", +DlgGenClass : "Typografiark", +DlgGenTitle : "Titel", +DlgGenContType : "Indholdstype", +DlgGenLinkCharset : "Tegnsæt", +DlgGenStyle : "Typografi", + +// Image Dialog +DlgImgTitle : "Egenskaber for billede", +DlgImgInfoTab : "Generelt", +DlgImgBtnUpload : "Upload", +DlgImgURL : "URL", +DlgImgUpload : "Upload", +DlgImgAlt : "Alternativ tekst", +DlgImgWidth : "Bredde", +DlgImgHeight : "Højde", +DlgImgLockRatio : "Lås størrelsesforhold", +DlgBtnResetSize : "Nulstil størrelse", +DlgImgBorder : "Ramme", +DlgImgHSpace : "HMargen", +DlgImgVSpace : "VMargen", +DlgImgAlign : "Justering", +DlgImgAlignLeft : "Venstre", +DlgImgAlignAbsBottom: "Absolut nederst", +DlgImgAlignAbsMiddle: "Absolut centreret", +DlgImgAlignBaseline : "Grundlinje", +DlgImgAlignBottom : "Nederst", +DlgImgAlignMiddle : "Centreret", +DlgImgAlignRight : "Højre", +DlgImgAlignTextTop : "Toppen af teksten", +DlgImgAlignTop : "Øverst", +DlgImgPreview : "Vis eksempel", +DlgImgAlertUrl : "Indtast stien til billedet", +DlgImgLinkTab : "Hyperlink", + +// Flash Dialog +DlgFlashTitle : "Egenskaber for Flash", +DlgFlashChkPlay : "Automatisk afspilning", +DlgFlashChkLoop : "Gentagelse", +DlgFlashChkMenu : "Vis Flash menu", +DlgFlashScale : "Skalér", +DlgFlashScaleAll : "Vis alt", +DlgFlashScaleNoBorder : "Ingen ramme", +DlgFlashScaleFit : "Tilpas størrelse", + +// Link Dialog +DlgLnkWindowTitle : "Egenskaber for hyperlink", +DlgLnkInfoTab : "Generelt", +DlgLnkTargetTab : "Mål", + +DlgLnkType : "Hyperlink type", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Bogmærke på denne side", +DlgLnkTypeEMail : "E-mail", +DlgLnkProto : "Protokol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Vælg et anker", +DlgLnkAnchorByName : "Efter anker navn", +DlgLnkAnchorById : "Efter element Id", +DlgLnkNoAnchors : "(Ingen bogmærker dokumentet)", +DlgLnkEMail : "E-mailadresse", +DlgLnkEMailSubject : "Emne", +DlgLnkEMailBody : "Brødtekst", +DlgLnkUpload : "Upload", +DlgLnkBtnUpload : "Upload", + +DlgLnkTarget : "Mål", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nyt vindue (_blank)", +DlgLnkTargetParent : "Overordnet ramme (_parent)", +DlgLnkTargetSelf : "Samme vindue (_self)", +DlgLnkTargetTop : "Hele vinduet (_top)", +DlgLnkTargetFrameName : "Destinationsvinduets navn", +DlgLnkPopWinName : "Pop-up vinduets navn", +DlgLnkPopWinFeat : "Egenskaber for pop-up", +DlgLnkPopResize : "Skalering", +DlgLnkPopLocation : "Adresselinje", +DlgLnkPopMenu : "Menulinje", +DlgLnkPopScroll : "Scrollbars", +DlgLnkPopStatus : "Statuslinje", +DlgLnkPopToolbar : "Værktøjslinje", +DlgLnkPopFullScrn : "Fuld skærm (IE)", +DlgLnkPopDependent : "Koblet/dependent (Netscape)", +DlgLnkPopWidth : "Bredde", +DlgLnkPopHeight : "Højde", +DlgLnkPopLeft : "Position fra venstre", +DlgLnkPopTop : "Position fra toppen", + +DlnLnkMsgNoUrl : "Indtast hyperlink URL!", +DlnLnkMsgNoEMail : "Indtast e-mailaddresse!", +DlnLnkMsgNoAnchor : "Vælg bogmærke!", +DlnLnkMsgInvPopName : "Navnet på popup'en skal starte med et bogstav og må ikke indeholde mellemrum", + +// Color Dialog +DlgColorTitle : "Vælg farve", +DlgColorBtnClear : "Nulstil", +DlgColorHighlight : "Markeret", +DlgColorSelected : "Valgt", + +// Smiley Dialog +DlgSmileyTitle : "Vælg smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Vælg symbol", + +// Table Dialog +DlgTableTitle : "Egenskaber for tabel", +DlgTableRows : "Rækker", +DlgTableColumns : "Kolonner", +DlgTableBorder : "Rammebredde", +DlgTableAlign : "Justering", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Venstrestillet", +DlgTableAlignCenter : "Centreret", +DlgTableAlignRight : "Højrestillet", +DlgTableWidth : "Bredde", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "procent", +DlgTableHeight : "Højde", +DlgTableCellSpace : "Celleafstand", +DlgTableCellPad : "Cellemargen", +DlgTableCaption : "Titel", +DlgTableSummary : "Resume", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Egenskaber for celle", +DlgCellWidth : "Bredde", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "procent", +DlgCellHeight : "Højde", +DlgCellWordWrap : "Orddeling", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Ja", +DlgCellWordWrapNo : "Nej", +DlgCellHorAlign : "Vandret justering", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Venstrestillet", +DlgCellHorAlignCenter : "Centreret", +DlgCellHorAlignRight: "Højrestillet", +DlgCellVerAlign : "Lodret justering", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Øverst", +DlgCellVerAlignMiddle : "Centreret", +DlgCellVerAlignBottom : "Nederst", +DlgCellVerAlignBaseline : "Grundlinje", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Højde i antal rækker", +DlgCellCollSpan : "Bredde i antal kolonner", +DlgCellBackColor : "Baggrundsfarve", +DlgCellBorderColor : "Rammefarve", +DlgCellBtnSelect : "Vælg...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Søg og erstat", + +// Find Dialog +DlgFindTitle : "Find", +DlgFindFindBtn : "Find", +DlgFindNotFoundMsg : "Søgeteksten blev ikke fundet!", + +// Replace Dialog +DlgReplaceTitle : "Erstat", +DlgReplaceFindLbl : "Søg efter:", +DlgReplaceReplaceLbl : "Erstat med:", +DlgReplaceCaseChk : "Forskel på store og små bogstaver", +DlgReplaceReplaceBtn : "Erstat", +DlgReplaceReplAllBtn : "Erstat alle", +DlgReplaceWordChk : "Kun hele ord", + +// Paste Operations / Dialog +PasteErrorCut : "Din browsers sikkerhedsindstillinger tillader ikke editoren at klippe tekst automatisk!
    Brug i stedet tastaturet til at klippe teksten (Ctrl+X).", +PasteErrorCopy : "Din browsers sikkerhedsindstillinger tillader ikke editoren at kopiere tekst automatisk!
    Brug i stedet tastaturet til at kopiere teksten (Ctrl+C).", + +PasteAsText : "Indsæt som ikke-formateret tekst", +PasteFromWord : "Indsæt fra Word", + +DlgPasteMsg2 : "Indsæt i feltet herunder (Ctrl+V) og klik OK.", +DlgPasteSec : "På grund af browserens sikkerhedsindstillinger kan editoren ikke tilgå udklipsholderen direkte. Du skal indsætte udklipsholderens indhold i dette vindue igen.", +DlgPasteIgnoreFont : "Ignorer font definitioner", +DlgPasteRemoveStyles : "Ignorer typografi", + +// Color Picker +ColorAutomatic : "Automatisk", +ColorMoreColors : "Flere farver...", + +// Document Properties +DocProps : "Egenskaber for dokument", + +// Anchor Dialog +DlgAnchorTitle : "Egenskaber for bogmærke", +DlgAnchorName : "Bogmærke navn", +DlgAnchorErrorName : "Indtast bogmærke navn!", + +// Speller Pages Dialog +DlgSpellNotInDic : "Ikke i ordbogen", +DlgSpellChangeTo : "Forslag", +DlgSpellBtnIgnore : "Ignorer", +DlgSpellBtnIgnoreAll : "Ignorer alle", +DlgSpellBtnReplace : "Erstat", +DlgSpellBtnReplaceAll : "Erstat alle", +DlgSpellBtnUndo : "Tilbage", +DlgSpellNoSuggestions : "- ingen forslag -", +DlgSpellProgress : "Stavekontrolen arbejder...", +DlgSpellNoMispell : "Stavekontrol færdig: Ingen fejl fundet", +DlgSpellNoChanges : "Stavekontrol færdig: Ingen ord ændret", +DlgSpellOneChange : "Stavekontrol færdig: Et ord ændret", +DlgSpellManyChanges : "Stavekontrol færdig: %1 ord ændret", + +IeSpellDownload : "Stavekontrol ikke installeret.
    Vil du hente den nu?", + +// Button Dialog +DlgButtonText : "Tekst", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Knap", +DlgButtonTypeSbm : "Send", +DlgButtonTypeRst : "Nulstil", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Navn", +DlgCheckboxValue : "Værdi", +DlgCheckboxSelected : "Valgt", + +// Form Dialog +DlgFormName : "Navn", +DlgFormAction : "Handling", +DlgFormMethod : "Metod", + +// Select Field Dialog +DlgSelectName : "Navn", +DlgSelectValue : "Værdi", +DlgSelectSize : "Størrelse", +DlgSelectLines : "linier", +DlgSelectChkMulti : "Tillad flere valg", +DlgSelectOpAvail : "Valgmuligheder", +DlgSelectOpText : "Tekst", +DlgSelectOpValue : "Værdi", +DlgSelectBtnAdd : "Tilføj", +DlgSelectBtnModify : "Rediger", +DlgSelectBtnUp : "Op", +DlgSelectBtnDown : "Ned", +DlgSelectBtnSetValue : "Sæt som valgt", +DlgSelectBtnDelete : "Slet", + +// Textarea Dialog +DlgTextareaName : "Navn", +DlgTextareaCols : "Kolonner", +DlgTextareaRows : "Rækker", + +// Text Field Dialog +DlgTextName : "Navn", +DlgTextValue : "Værdi", +DlgTextCharWidth : "Bredde (tegn)", +DlgTextMaxChars : "Max antal tegn", +DlgTextType : "Type", +DlgTextTypeText : "Tekst", +DlgTextTypePass : "Adgangskode", + +// Hidden Field Dialog +DlgHiddenName : "Navn", +DlgHiddenValue : "Værdi", + +// Bulleted List Dialog +BulletedListProp : "Egenskaber for punktopstilling", +NumberedListProp : "Egenskaber for talopstilling", +DlgLstStart : "Start", +DlgLstType : "Type", +DlgLstTypeCircle : "Cirkel", +DlgLstTypeDisc : "Udfyldt cirkel", +DlgLstTypeSquare : "Firkant", +DlgLstTypeNumbers : "Nummereret (1, 2, 3)", +DlgLstTypeLCase : "Små bogstaver (a, b, c)", +DlgLstTypeUCase : "Store bogstaver (A, B, C)", +DlgLstTypeSRoman : "Små romertal (i, ii, iii)", +DlgLstTypeLRoman : "Store romertal (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Generelt", +DlgDocBackTab : "Baggrund", +DlgDocColorsTab : "Farver og margen", +DlgDocMetaTab : "Metadata", + +DlgDocPageTitle : "Sidetitel", +DlgDocLangDir : "Sprog", +DlgDocLangDirLTR : "Fra venstre mod højre (LTR)", +DlgDocLangDirRTL : "Fra højre mod venstre (RTL)", +DlgDocLangCode : "Landekode", +DlgDocCharSet : "Tegnsæt kode", +DlgDocCharSetCE : "Centraleuropæisk", +DlgDocCharSetCT : "Traditionel kinesisk (Big5)", +DlgDocCharSetCR : "Kyrillisk", +DlgDocCharSetGR : "Græsk", +DlgDocCharSetJP : "Japansk", +DlgDocCharSetKR : "Koreansk", +DlgDocCharSetTR : "Tyrkisk", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Vesteuropæisk", +DlgDocCharSetOther : "Anden tegnsæt kode", + +DlgDocDocType : "Dokumenttype kategori", +DlgDocDocTypeOther : "Anden dokumenttype kategori", +DlgDocIncXHTML : "Inkludere XHTML deklartion", +DlgDocBgColor : "Baggrundsfarve", +DlgDocBgImage : "Baggrundsbillede URL", +DlgDocBgNoScroll : "Fastlåst baggrund", +DlgDocCText : "Tekst", +DlgDocCLink : "Hyperlink", +DlgDocCVisited : "Besøgt hyperlink", +DlgDocCActive : "Aktivt hyperlink", +DlgDocMargins : "Sidemargen", +DlgDocMaTop : "Øverst", +DlgDocMaLeft : "Venstre", +DlgDocMaRight : "Højre", +DlgDocMaBottom : "Nederst", +DlgDocMeIndex : "Dokument index nøgleord (kommasepareret)", +DlgDocMeDescr : "Dokument beskrivelse", +DlgDocMeAuthor : "Forfatter", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Vis", + +// Templates Dialog +Templates : "Skabeloner", +DlgTemplatesTitle : "Indholdsskabeloner", +DlgTemplatesSelMsg : "Vælg den skabelon, som skal åbnes i editoren.
    (Nuværende indhold vil blive overskrevet!):", +DlgTemplatesLoading : "Henter liste over skabeloner...", +DlgTemplatesNoTpl : "(Der er ikke defineret nogen skabelon!)", +DlgTemplatesReplace : "Erstat det faktiske indhold", + +// About Dialog +DlgAboutAboutTab : "Om", +DlgAboutBrowserInfoTab : "Generelt", +DlgAboutLicenseTab : "Licens", +DlgAboutVersion : "version", +DlgAboutInfo : "For yderlig information gÃ¥ til", + +// Div Dialog +DlgDivGeneralTab : "Generelt", +DlgDivAdvancedTab : "Avanceret", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Inline style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/de.js b/www/js/FCKeditor/editor/lang/de.js new file mode 100644 index 0000000..f43941a --- /dev/null +++ b/www/js/FCKeditor/editor/lang/de.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * German language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Symbolleiste einklappen", +ToolbarExpand : "Symbolleiste ausklappen", + +// Toolbar Items and Context Menu +Save : "Speichern", +NewPage : "Neue Seite", +Preview : "Vorschau", +Cut : "Ausschneiden", +Copy : "Kopieren", +Paste : "Einfügen", +PasteText : "aus Textdatei einfügen", +PasteWord : "aus MS-Word einfügen", +Print : "Drucken", +SelectAll : "Alles auswählen", +RemoveFormat : "Formatierungen entfernen", +InsertLinkLbl : "Link", +InsertLink : "Link einfügen/editieren", +RemoveLink : "Link entfernen", +VisitLink : "Link aufrufen", +Anchor : "Anker einfügen/editieren", +AnchorDelete : "Anker entfernen", +InsertImageLbl : "Bild", +InsertImage : "Bild einfügen/editieren", +InsertFlashLbl : "Flash", +InsertFlash : "Flash einfügen/editieren", +InsertTableLbl : "Tabelle", +InsertTable : "Tabelle einfügen/editieren", +InsertLineLbl : "Linie", +InsertLine : "Horizontale Linie einfügen", +InsertSpecialCharLbl: "Sonderzeichen", +InsertSpecialChar : "Sonderzeichen einfügen/editieren", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Smiley einfügen", +About : "Ãœber FCKeditor", +Bold : "Fett", +Italic : "Kursiv", +Underline : "Unterstrichen", +StrikeThrough : "Durchgestrichen", +Subscript : "Tiefgestellt", +Superscript : "Hochgestellt", +LeftJustify : "Linksbündig", +CenterJustify : "Zentriert", +RightJustify : "Rechtsbündig", +BlockJustify : "Blocksatz", +DecreaseIndent : "Einzug verringern", +IncreaseIndent : "Einzug erhöhen", +Blockquote : "Zitatblock", +CreateDiv : "Erzeuge Div Block", +EditDiv : "Bearbeite Div Block", +DeleteDiv : "Entferne Div Block", +Undo : "Rückgängig", +Redo : "Wiederherstellen", +NumberedListLbl : "Nummerierte Liste", +NumberedList : "Nummerierte Liste einfügen/entfernen", +BulletedListLbl : "Liste", +BulletedList : "Liste einfügen/entfernen", +ShowTableBorders : "Zeige Tabellenrahmen", +ShowDetails : "Zeige Details", +Style : "Stil", +FontFormat : "Format", +Font : "Schriftart", +FontSize : "Größe", +TextColor : "Textfarbe", +BGColor : "Hintergrundfarbe", +Source : "Quellcode", +Find : "Suchen", +Replace : "Ersetzen", +SpellCheck : "Rechtschreibprüfung", +UniversalKeyboard : "Universal-Tastatur", +PageBreakLbl : "Seitenumbruch", +PageBreak : "Seitenumbruch einfügen", + +Form : "Formular", +Checkbox : "Checkbox", +RadioButton : "Radiobutton", +TextField : "Textfeld einzeilig", +Textarea : "Textfeld mehrzeilig", +HiddenField : "verstecktes Feld", +Button : "Klickbutton", +SelectionField : "Auswahlfeld", +ImageButton : "Bildbutton", + +FitWindow : "Editor maximieren", +ShowBlocks : "Blöcke anzeigen", + +// Context Menu +EditLink : "Link editieren", +CellCM : "Zelle", +RowCM : "Zeile", +ColumnCM : "Spalte", +InsertRowAfter : "Zeile unterhalb einfügen", +InsertRowBefore : "Zeile oberhalb einfügen", +DeleteRows : "Zeile entfernen", +InsertColumnAfter : "Spalte rechts danach einfügen", +InsertColumnBefore : "Spalte links davor einfügen", +DeleteColumns : "Spalte löschen", +InsertCellAfter : "Zelle danach einfügen", +InsertCellBefore : "Zelle davor einfügen", +DeleteCells : "Zelle löschen", +MergeCells : "Zellen verbinden", +MergeRight : "nach rechts verbinden", +MergeDown : "nach unten verbinden", +HorizontalSplitCell : "Zelle horizontal teilen", +VerticalSplitCell : "Zelle vertikal teilen", +TableDelete : "Tabelle löschen", +CellProperties : "Zellen-Eigenschaften", +TableProperties : "Tabellen-Eigenschaften", +ImageProperties : "Bild-Eigenschaften", +FlashProperties : "Flash-Eigenschaften", + +AnchorProp : "Anker-Eigenschaften", +ButtonProp : "Button-Eigenschaften", +CheckboxProp : "Checkbox-Eigenschaften", +HiddenFieldProp : "Verstecktes Feld-Eigenschaften", +RadioButtonProp : "Optionsfeld-Eigenschaften", +ImageButtonProp : "Bildbutton-Eigenschaften", +TextFieldProp : "Textfeld (einzeilig) Eigenschaften", +SelectionFieldProp : "Auswahlfeld-Eigenschaften", +TextareaProp : "Textfeld (mehrzeilig) Eigenschaften", +FormProp : "Formular-Eigenschaften", + +FontFormats : "Normal;Formatiert;Addresse;Ãœberschrift 1;Ãœberschrift 2;Ãœberschrift 3;Ãœberschrift 4;Ãœberschrift 5;Ãœberschrift 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Bearbeite XHTML. Bitte warten...", +Done : "Fertig", +PasteWordConfirm : "Der Text, den Sie einfügen möchten, scheint aus MS-Word kopiert zu sein. Möchten Sie ihn zuvor bereinigen lassen?", +NotCompatiblePaste : "Diese Funktion steht nur im Internet Explorer ab Version 5.5 zur Verfügung. Möchten Sie den Text unbereinigt einfügen?", +UnknownToolbarItem : "Unbekanntes Menüleisten-Objekt \"%1\"", +UnknownCommand : "Unbekannter Befehl \"%1\"", +NotImplemented : "Befehl nicht implementiert", +UnknownToolbarSet : "Menüleiste \"%1\" existiert nicht", +NoActiveX : "Die Sicherheitseinstellungen Ihres Browsers beschränken evtl. einige Funktionen des Editors. Aktivieren Sie die Option \"ActiveX-Steuerelemente und Plugins ausführen\" in den Sicherheitseinstellungen, um diese Funktionen nutzen zu können", +BrowseServerBlocked : "Ein Auswahlfenster konnte nicht geöffnet werden. Stellen Sie sicher, das alle Popup-Blocker ausgeschaltet sind.", +DialogBlocked : "Das Dialog-Fenster konnte nicht geöffnet werden. Stellen Sie sicher, das alle Popup-Blocker ausgeschaltet sind.", +VisitLinkBlocked : "Es war leider nicht möglich ein neues Fenster zu öffnen. Bitte versichern Sie sich das der Popup-Blocker ausgeschaltet ist.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Abbrechen", +DlgBtnClose : "Schließen", +DlgBtnBrowseServer : "Server durchsuchen", +DlgAdvancedTag : "Erweitert", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Bitte tragen Sie die URL ein", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "ID", +DlgGenLangDir : "Schreibrichtung", +DlgGenLangDirLtr : "Links nach Rechts (LTR)", +DlgGenLangDirRtl : "Rechts nach Links (RTL)", +DlgGenLangCode : "Sprachenkürzel", +DlgGenAccessKey : "Zugriffstaste", +DlgGenName : "Name", +DlgGenTabIndex : "Tab-Index", +DlgGenLongDescr : "Langform URL", +DlgGenClass : "Stylesheet Klasse", +DlgGenTitle : "Titel Beschreibung", +DlgGenContType : "Inhaltstyp", +DlgGenLinkCharset : "Ziel-Zeichensatz", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Bild-Eigenschaften", +DlgImgInfoTab : "Bild-Info", +DlgImgBtnUpload : "Zum Server senden", +DlgImgURL : "Bildauswahl", +DlgImgUpload : "Upload", +DlgImgAlt : "Alternativer Text", +DlgImgWidth : "Breite", +DlgImgHeight : "Höhe", +DlgImgLockRatio : "Größenverhältniss beibehalten", +DlgBtnResetSize : "Größe zurücksetzen", +DlgImgBorder : "Rahmen", +DlgImgHSpace : "Horizontal-Abstand", +DlgImgVSpace : "Vertikal-Abstand", +DlgImgAlign : "Ausrichtung", +DlgImgAlignLeft : "Links", +DlgImgAlignAbsBottom: "Abs Unten", +DlgImgAlignAbsMiddle: "Abs Mitte", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Unten", +DlgImgAlignMiddle : "Mitte", +DlgImgAlignRight : "Rechts", +DlgImgAlignTextTop : "Text Oben", +DlgImgAlignTop : "Oben", +DlgImgPreview : "Vorschau", +DlgImgAlertUrl : "Bitte geben Sie die Bild-URL an", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash-Eigenschaften", +DlgFlashChkPlay : "autom. Abspielen", +DlgFlashChkLoop : "Endlosschleife", +DlgFlashChkMenu : "Flash-Menü aktivieren", +DlgFlashScale : "Skalierung", +DlgFlashScaleAll : "Alles anzeigen", +DlgFlashScaleNoBorder : "ohne Rand", +DlgFlashScaleFit : "Passgenau", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link-Info", +DlgLnkTargetTab : "Zielseite", + +DlgLnkType : "Link-Typ", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Anker in dieser Seite", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protokoll", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Anker auswählen", +DlgLnkAnchorByName : "nach Anker Name", +DlgLnkAnchorById : "nach Element Id", +DlgLnkNoAnchors : "(keine Anker im Dokument vorhanden)", +DlgLnkEMail : "E-Mail Addresse", +DlgLnkEMailSubject : "Betreffzeile", +DlgLnkEMailBody : "Nachrichtentext", +DlgLnkUpload : "Upload", +DlgLnkBtnUpload : "Zum Server senden", + +DlgLnkTarget : "Zielseite", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Neues Fenster (_blank)", +DlgLnkTargetParent : "Oberes Fenster (_parent)", +DlgLnkTargetSelf : "Gleiches Fenster (_self)", +DlgLnkTargetTop : "Oberstes Fenster (_top)", +DlgLnkTargetFrameName : "Ziel-Fenster-Name", +DlgLnkPopWinName : "Pop-up Fenster-Name", +DlgLnkPopWinFeat : "Pop-up Fenster-Eigenschaften", +DlgLnkPopResize : "Vergrößerbar", +DlgLnkPopLocation : "Adress-Leiste", +DlgLnkPopMenu : "Menü-Leiste", +DlgLnkPopScroll : "Rollbalken", +DlgLnkPopStatus : "Statusleiste", +DlgLnkPopToolbar : "Werkzeugleiste", +DlgLnkPopFullScrn : "Vollbild (IE)", +DlgLnkPopDependent : "Abhängig (Netscape)", +DlgLnkPopWidth : "Breite", +DlgLnkPopHeight : "Höhe", +DlgLnkPopLeft : "Linke Position", +DlgLnkPopTop : "Obere Position", + +DlnLnkMsgNoUrl : "Bitte geben Sie die Link-URL an", +DlnLnkMsgNoEMail : "Bitte geben Sie e-Mail Adresse an", +DlnLnkMsgNoAnchor : "Bitte wählen Sie einen Anker aus", +DlnLnkMsgInvPopName : "Der Name des Popups muss mit einem Buchstaben beginnen und darf keine Leerzeichen enthalten", + +// Color Dialog +DlgColorTitle : "Farbauswahl", +DlgColorBtnClear : "Keine Farbe", +DlgColorHighlight : "Vorschau", +DlgColorSelected : "Ausgewählt", + +// Smiley Dialog +DlgSmileyTitle : "Smiley auswählen", + +// Special Character Dialog +DlgSpecialCharTitle : "Sonderzeichen auswählen", + +// Table Dialog +DlgTableTitle : "Tabellen-Eigenschaften", +DlgTableRows : "Zeile", +DlgTableColumns : "Spalte", +DlgTableBorder : "Rahmen", +DlgTableAlign : "Ausrichtung", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Links", +DlgTableAlignCenter : "Zentriert", +DlgTableAlignRight : "Rechts", +DlgTableWidth : "Breite", +DlgTableWidthPx : "Pixel", +DlgTableWidthPc : "%", +DlgTableHeight : "Höhe", +DlgTableCellSpace : "Zellenabstand außen", +DlgTableCellPad : "Zellenabstand innen", +DlgTableCaption : "Ãœberschrift", +DlgTableSummary : "Inhaltsübersicht", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Zellen-Eigenschaften", +DlgCellWidth : "Breite", +DlgCellWidthPx : "Pixel", +DlgCellWidthPc : "%", +DlgCellHeight : "Höhe", +DlgCellWordWrap : "Umbruch", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Ja", +DlgCellWordWrapNo : "Nein", +DlgCellHorAlign : "Horizontale Ausrichtung", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Links", +DlgCellHorAlignCenter : "Zentriert", +DlgCellHorAlignRight: "Rechts", +DlgCellVerAlign : "Vertikale Ausrichtung", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Oben", +DlgCellVerAlignMiddle : "Mitte", +DlgCellVerAlignBottom : "Unten", +DlgCellVerAlignBaseline : "Grundlinie", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Zeilen zusammenfassen", +DlgCellCollSpan : "Spalten zusammenfassen", +DlgCellBackColor : "Hintergrundfarbe", +DlgCellBorderColor : "Rahmenfarbe", +DlgCellBtnSelect : "Auswahl...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Suchen und Ersetzen", + +// Find Dialog +DlgFindTitle : "Finden", +DlgFindFindBtn : "Finden", +DlgFindNotFoundMsg : "Der gesuchte Text wurde nicht gefunden.", + +// Replace Dialog +DlgReplaceTitle : "Ersetzen", +DlgReplaceFindLbl : "Suche nach:", +DlgReplaceReplaceLbl : "Ersetze mit:", +DlgReplaceCaseChk : "Groß-Kleinschreibung beachten", +DlgReplaceReplaceBtn : "Ersetzen", +DlgReplaceReplAllBtn : "Alle Ersetzen", +DlgReplaceWordChk : "Nur ganze Worte suchen", + +// Paste Operations / Dialog +PasteErrorCut : "Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).", +PasteErrorCopy : "Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).", + +PasteAsText : "Als Text einfügen", +PasteFromWord : "Aus Word einfügen", + +DlgPasteMsg2 : "Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit Strg+V) ein und bestätigen Sie mit OK.", +DlgPasteSec : "Aufgrund von Sicherheitsbeschränkungen Ihres Browsers kann der Editor nicht direkt auf die Zwischenablage zugreifen. Bitte fügen Sie den Inhalt erneut in diesem Fenster ein.", +DlgPasteIgnoreFont : "Ignoriere Schriftart-Definitionen", +DlgPasteRemoveStyles : "Entferne Style-Definitionen", + +// Color Picker +ColorAutomatic : "Automatisch", +ColorMoreColors : "Weitere Farben...", + +// Document Properties +DocProps : "Dokument-Eigenschaften", + +// Anchor Dialog +DlgAnchorTitle : "Anker-Eigenschaften", +DlgAnchorName : "Anker Name", +DlgAnchorErrorName : "Bitte geben Sie den Namen des Ankers ein", + +// Speller Pages Dialog +DlgSpellNotInDic : "Nicht im Wörterbuch", +DlgSpellChangeTo : "Ändern in", +DlgSpellBtnIgnore : "Ignorieren", +DlgSpellBtnIgnoreAll : "Alle Ignorieren", +DlgSpellBtnReplace : "Ersetzen", +DlgSpellBtnReplaceAll : "Alle Ersetzen", +DlgSpellBtnUndo : "Rückgängig", +DlgSpellNoSuggestions : " - keine Vorschläge - ", +DlgSpellProgress : "Rechtschreibprüfung läuft...", +DlgSpellNoMispell : "Rechtschreibprüfung abgeschlossen - keine Fehler gefunden", +DlgSpellNoChanges : "Rechtschreibprüfung abgeschlossen - keine Worte geändert", +DlgSpellOneChange : "Rechtschreibprüfung abgeschlossen - ein Wort geändert", +DlgSpellManyChanges : "Rechtschreibprüfung abgeschlossen - %1 Wörter geändert", + +IeSpellDownload : "Rechtschreibprüfung nicht installiert. Möchten Sie sie jetzt herunterladen?", + +// Button Dialog +DlgButtonText : "Text (Wert)", +DlgButtonType : "Typ", +DlgButtonTypeBtn : "Button", +DlgButtonTypeSbm : "Absenden", +DlgButtonTypeRst : "Zurücksetzen", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Name", +DlgCheckboxValue : "Wert", +DlgCheckboxSelected : "ausgewählt", + +// Form Dialog +DlgFormName : "Name", +DlgFormAction : "Action", +DlgFormMethod : "Method", + +// Select Field Dialog +DlgSelectName : "Name", +DlgSelectValue : "Wert", +DlgSelectSize : "Größe", +DlgSelectLines : "Linien", +DlgSelectChkMulti : "Erlaube Mehrfachauswahl", +DlgSelectOpAvail : "Mögliche Optionen", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Wert", +DlgSelectBtnAdd : "Hinzufügen", +DlgSelectBtnModify : "Ändern", +DlgSelectBtnUp : "Hoch", +DlgSelectBtnDown : "Runter", +DlgSelectBtnSetValue : "Setze als Standardwert", +DlgSelectBtnDelete : "Entfernen", + +// Textarea Dialog +DlgTextareaName : "Name", +DlgTextareaCols : "Spalten", +DlgTextareaRows : "Reihen", + +// Text Field Dialog +DlgTextName : "Name", +DlgTextValue : "Wert", +DlgTextCharWidth : "Zeichenbreite", +DlgTextMaxChars : "Max. Zeichen", +DlgTextType : "Typ", +DlgTextTypeText : "Text", +DlgTextTypePass : "Passwort", + +// Hidden Field Dialog +DlgHiddenName : "Name", +DlgHiddenValue : "Wert", + +// Bulleted List Dialog +BulletedListProp : "Listen-Eigenschaften", +NumberedListProp : "Nummerierte Listen-Eigenschaften", +DlgLstStart : "Start", +DlgLstType : "Typ", +DlgLstTypeCircle : "Ring", +DlgLstTypeDisc : "Kreis", +DlgLstTypeSquare : "Quadrat", +DlgLstTypeNumbers : "Nummern (1, 2, 3)", +DlgLstTypeLCase : "Kleinbuchstaben (a, b, c)", +DlgLstTypeUCase : "Großbuchstaben (A, B, C)", +DlgLstTypeSRoman : "Kleine römische Zahlen (i, ii, iii)", +DlgLstTypeLRoman : "Große römische Zahlen (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Allgemein", +DlgDocBackTab : "Hintergrund", +DlgDocColorsTab : "Farben und Abstände", +DlgDocMetaTab : "Metadaten", + +DlgDocPageTitle : "Seitentitel", +DlgDocLangDir : "Schriftrichtung", +DlgDocLangDirLTR : "Links nach Rechts", +DlgDocLangDirRTL : "Rechts nach Links", +DlgDocLangCode : "Sprachkürzel", +DlgDocCharSet : "Zeichenkodierung", +DlgDocCharSetCE : "Zentraleuropäisch", +DlgDocCharSetCT : "traditionell Chinesisch (Big5)", +DlgDocCharSetCR : "Kyrillisch", +DlgDocCharSetGR : "Griechisch", +DlgDocCharSetJP : "Japanisch", +DlgDocCharSetKR : "Koreanisch", +DlgDocCharSetTR : "Türkisch", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Westeuropäisch", +DlgDocCharSetOther : "Andere Zeichenkodierung", + +DlgDocDocType : "Dokumententyp", +DlgDocDocTypeOther : "Anderer Dokumententyp", +DlgDocIncXHTML : "Beziehe XHTML Deklarationen ein", +DlgDocBgColor : "Hintergrundfarbe", +DlgDocBgImage : "Hintergrundbild URL", +DlgDocBgNoScroll : "feststehender Hintergrund", +DlgDocCText : "Text", +DlgDocCLink : "Link", +DlgDocCVisited : "Besuchter Link", +DlgDocCActive : "Aktiver Link", +DlgDocMargins : "Seitenränder", +DlgDocMaTop : "Oben", +DlgDocMaLeft : "Links", +DlgDocMaRight : "Rechts", +DlgDocMaBottom : "Unten", +DlgDocMeIndex : "Schlüsselwörter (durch Komma getrennt)", +DlgDocMeDescr : "Dokument-Beschreibung", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Vorschau", + +// Templates Dialog +Templates : "Vorlagen", +DlgTemplatesTitle : "Vorlagen", +DlgTemplatesSelMsg : "Klicken Sie auf eine Vorlage, um sie im Editor zu öffnen (der aktuelle Inhalt wird dabei gelöscht!):", +DlgTemplatesLoading : "Liste der Vorlagen wird geladen. Bitte warten...", +DlgTemplatesNoTpl : "(keine Vorlagen definiert)", +DlgTemplatesReplace : "Aktuellen Inhalt ersetzen", + +// About Dialog +DlgAboutAboutTab : "Ãœber", +DlgAboutBrowserInfoTab : "Browser-Info", +DlgAboutLicenseTab : "Lizenz", +DlgAboutVersion : "Version", +DlgAboutInfo : "Für weitere Informationen siehe", + +// Div Dialog +DlgDivGeneralTab : "Allgemein", +DlgDivAdvancedTab : "Erweitert", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Inline Style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/el.js b/www/js/FCKeditor/editor/lang/el.js new file mode 100644 index 0000000..1ab8d05 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/el.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Greek language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "ΑπόκÏυψη ΜπάÏας ΕÏγαλείων", +ToolbarExpand : "Εμφάνιση ΜπάÏας ΕÏγαλείων", + +// Toolbar Items and Context Menu +Save : "Αποθήκευση", +NewPage : "Îέα Σελίδα", +Preview : "ΠÏοεπισκόπιση", +Cut : "Αποκοπή", +Copy : "ΑντιγÏαφή", +Paste : "Επικόλληση", +PasteText : "Επικόλληση (απλό κείμενο)", +PasteWord : "Επικόλληση από το Word", +Print : "ΕκτÏπωση", +SelectAll : "Επιλογή όλων", +RemoveFormat : "ΑφαίÏεση ΜοÏφοποίησης", +InsertLinkLbl : "ΣÏνδεσμος (Link)", +InsertLink : "Εισαγωγή/Μεταβολή Συνδέσμου (Link)", +RemoveLink : "ΑφαίÏεση Συνδέσμου (Link)", +VisitLink : "Open Link", //MISSING +Anchor : "Εισαγωγή/επεξεÏγασία Anchor", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "Εικόνα", +InsertImage : "Εισαγωγή/Μεταβολή Εικόνας", +InsertFlashLbl : "Εισαγωγή Flash", +InsertFlash : "Εισαγωγή/επεξεÏγασία Flash", +InsertTableLbl : "Πίνακας", +InsertTable : "Εισαγωγή/Μεταβολή Πίνακα", +InsertLineLbl : "ΓÏαμμή", +InsertLine : "Εισαγωγή ΟÏιζόντιας ΓÏαμμής", +InsertSpecialCharLbl: "Ειδικό ΣÏμβολο", +InsertSpecialChar : "Εισαγωγή Î•Î¹Î´Î¹ÎºÎ¿Ï Î£Ï…Î¼Î²ÏŒÎ»Î¿Ï…", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Εισαγωγή Smiley", +About : "ΠεÏί του FCKeditor", +Bold : "Έντονα", +Italic : "Πλάγια", +Underline : "ΥπογÏάμμιση", +StrikeThrough : "ΔιαγÏάμμιση", +Subscript : "Δείκτης", +Superscript : "Εκθέτης", +LeftJustify : "Στοίχιση ΑÏιστεÏά", +CenterJustify : "Στοίχιση στο ΚέντÏο", +RightJustify : "Στοίχιση Δεξιά", +BlockJustify : "ΠλήÏης Στοίχιση (Block)", +DecreaseIndent : "Μείωση Εσοχής", +IncreaseIndent : "ΑÏξηση Εσοχής", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "ΑναίÏεση", +Redo : "ΕπαναφοÏά", +NumberedListLbl : "Λίστα με ΑÏιθμοÏÏ‚", +NumberedList : "Εισαγωγή/ΔιαγÏαφή Λίστας με ΑÏιθμοÏÏ‚", +BulletedListLbl : "Λίστα με Bullets", +BulletedList : "Εισαγωγή/ΔιαγÏαφή Λίστας με Bullets", +ShowTableBorders : "ΠÏοβολή ΟÏίων Πίνακα", +ShowDetails : "ΠÏοβολή ΛεπτομεÏειών", +Style : "Στυλ", +FontFormat : "ΜοÏφή ΓÏαμματοσειÏάς", +Font : "ΓÏαμματοσειÏά", +FontSize : "Μέγεθος", +TextColor : "ΧÏώμα ΓÏαμμάτων", +BGColor : "ΧÏώμα ΥποβάθÏου", +Source : "HTML κώδικας", +Find : "Αναζήτηση", +Replace : "Αντικατάσταση", +SpellCheck : "ΟÏθογÏαφικός έλεγχος", +UniversalKeyboard : "Διεθνής πληκτÏολόγιο", +PageBreakLbl : "Τέλος σελίδας", +PageBreak : "Εισαγωγή τέλους σελίδας", + +Form : "ΦόÏμα", +Checkbox : "Κουτί επιλογής", +RadioButton : "Κουμπί Radio", +TextField : "Πεδίο κειμένου", +Textarea : "ΠεÏιοχή κειμένου", +HiddenField : "ΚÏυφό πεδίο", +Button : "Κουμπί", +SelectionField : "Πεδίο επιλογής", +ImageButton : "Κουμπί εικόνας", + +FitWindow : "Μεγιστοποίηση Ï€ÏογÏάμματος", +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Μεταβολή Συνδέσμου (Link)", +CellCM : "Κελί", +RowCM : "ΣειÏά", +ColumnCM : "Στήλη", +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "ΔιαγÏαφή ΓÏαμμών", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "ΔιαγÏαφή Κολωνών", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "ΔιαγÏαφή Κελιών", +MergeCells : "Ενοποίηση Κελιών", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "ΔιαγÏαφή πίνακα", +CellProperties : "Ιδιότητες ΚελιοÏ", +TableProperties : "Ιδιότητες Πίνακα", +ImageProperties : "Ιδιότητες Εικόνας", +FlashProperties : "Ιδιότητες Flash", + +AnchorProp : "Ιδιότητες άγκυÏας", +ButtonProp : "Ιδιότητες κουμπιοÏ", +CheckboxProp : "Ιδιότητες ÎºÎ¿Ï…Î¼Ï€Î¹Î¿Ï ÎµÏ€Î¹Î»Î¿Î³Î®Ï‚", +HiddenFieldProp : "Ιδιότητες κÏÏ…Ï†Î¿Ï Ï€ÎµÎ´Î¯Î¿Ï…", +RadioButtonProp : "Ιδιότητες ÎºÎ¿Ï…Î¼Ï€Î¹Î¿Ï radio", +ImageButtonProp : "Ιδιότητες ÎºÎ¿Ï…Î¼Ï€Î¹Î¿Ï ÎµÎ¹ÎºÏŒÎ½Î±Ï‚", +TextFieldProp : "Ιδιότητες πεδίου κειμένου", +SelectionFieldProp : "Ιδιότητες πεδίου επιλογής", +TextareaProp : "Ιδιότητες πεÏιοχής κειμένου", +FormProp : "Ιδιότητες φόÏμας", + +FontFormats : "Κανονικό;ΜοÏφοποιημένο;ΔιεÏθυνση;Επικεφαλίδα 1;Επικεφαλίδα 2;Επικεφαλίδα 3;Επικεφαλίδα 4;Επικεφαλίδα 5;Επικεφαλίδα 6", + +// Alerts and Messages +ProcessingXHTML : "ΕπεξεÏγασία XHTML. ΠαÏακαλώ πεÏιμένετε...", +Done : "Έτοιμο", +PasteWordConfirm : "Το κείμενο που θέλετε να επικολήσετε, φαίνεται πως Ï€ÏοέÏχεται από το Word. Θέλετε να καθαÏιστεί Ï€Ïιν επικοληθεί;", +NotCompatiblePaste : "Αυτή η επιλογή είναι διαθέσιμη στον Internet Explorer έκδοση 5.5+. Θέλετε να γίνει η επικόλληση χωÏίς καθαÏισμό;", +UnknownToolbarItem : "Άγνωστο αντικείμενο της μπάÏας εÏγαλείων \"%1\"", +UnknownCommand : "Άγνωστή εντολή \"%1\"", +NotImplemented : "Η εντολή δεν έχει ενεÏγοποιηθεί", +UnknownToolbarSet : "Η μπάÏα εÏγαλείων \"%1\" δεν υπάÏχει", +NoActiveX : "Οι Ïυθμίσεις ασφαλείας του browser σας μποÏεί να πεÏιοÏίσουν κάποιες Ïυθμίσεις του Ï€ÏογÏάμματος. ΧÏειάζεται να ενεÏγοποιήσετε την επιλογή \"Run ActiveX controls and plug-ins\". Ίσως παÏουσιαστοÏν λάθη και παÏατηÏήσετε ελειπείς λειτουÏγίες.", +BrowseServerBlocked : "Οι πόÏοι του browser σας δεν είναι Ï€Ïοσπελάσιμοι. ΣιγουÏευτείτε ότι δεν υπάÏχουν ενεÏγοί popup blockers.", +DialogBlocked : "Δεν ήταν δυνατό να ανοίξει το παÏάθυÏο διαλόγου. ΣιγουÏευτείτε ότι δεν υπάÏχουν ενεÏγοί popup blockers.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "ΑκÏÏωση", +DlgBtnClose : "Κλείσιμο", +DlgBtnBrowseServer : "ΕξεÏεÏνηση διακομιστή", +DlgAdvancedTag : "Για Ï€ÏοχωÏημένους", +DlgOpOther : "<Άλλα>", +DlgInfoTab : "ΠληÏοφοÏίες", +DlgAlertUrl : "ΠαÏακαλώ εισάγετε URL", + +// General Dialogs Labels +DlgGenNotSet : "<χωÏίς>", +DlgGenId : "Id", +DlgGenLangDir : "ΚατεÏθυνση κειμένου", +DlgGenLangDirLtr : "ΑÏιστεÏά Ï€Ïος Δεξιά (LTR)", +DlgGenLangDirRtl : "Δεξιά Ï€Ïος ΑÏιστεÏά (RTL)", +DlgGenLangCode : "Κωδικός Γλώσσας", +DlgGenAccessKey : "Συντόμευση (Access Key)", +DlgGenName : "Όνομα", +DlgGenTabIndex : "Tab Index", +DlgGenLongDescr : "Αναλυτική πεÏιγÏαφή URL", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "Συμβουλευτικός τίτλος", +DlgGenContType : "Συμβουλευτικός τίτλος πεÏιεχομένου", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "ΣτÏλ", + +// Image Dialog +DlgImgTitle : "Ιδιότητες Εικόνας", +DlgImgInfoTab : "ΠληÏοφοÏίες Εικόνας", +DlgImgBtnUpload : "Αποστολή στον Διακομιστή", +DlgImgURL : "URL", +DlgImgUpload : "Αποστολή", +DlgImgAlt : "Εναλλακτικό Κείμενο (ALT)", +DlgImgWidth : "Πλάτος", +DlgImgHeight : "Ύψος", +DlgImgLockRatio : "Κλείδωμα Αναλογίας", +DlgBtnResetSize : "ΕπαναφοÏά ΑÏÏ‡Î¹ÎºÎ¿Ï ÎœÎµÎ³Î­Î¸Î¿Ï…Ï‚", +DlgImgBorder : "ΠεÏιθώÏιο", +DlgImgHSpace : "ΟÏιζόντιος ΧώÏος (HSpace)", +DlgImgVSpace : "Κάθετος ΧώÏος (VSpace)", +DlgImgAlign : "ΕυθυγÏάμμιση (Align)", +DlgImgAlignLeft : "ΑÏιστεÏά", +DlgImgAlignAbsBottom: "Απόλυτα Κάτω (Abs Bottom)", +DlgImgAlignAbsMiddle: "Απόλυτα στη Μέση (Abs Middle)", +DlgImgAlignBaseline : "ΓÏαμμή Βάσης (Baseline)", +DlgImgAlignBottom : "Κάτω (Bottom)", +DlgImgAlignMiddle : "Μέση (Middle)", +DlgImgAlignRight : "Δεξιά (Right)", +DlgImgAlignTextTop : "ΚοÏυφή Κειμένου (Text Top)", +DlgImgAlignTop : "Πάνω (Top)", +DlgImgPreview : "ΠÏοεπισκόπιση", +DlgImgAlertUrl : "Εισάγετε την τοποθεσία (URL) της εικόνας", +DlgImgLinkTab : "ΣÏνδεσμος", + +// Flash Dialog +DlgFlashTitle : "Ιδιότητες flash", +DlgFlashChkPlay : "Αυτόματη έναÏξη", +DlgFlashChkLoop : "Επανάληψη", +DlgFlashChkMenu : "ΕνεÏγοποίηση Flash Menu", +DlgFlashScale : "Κλίμακα", +DlgFlashScaleAll : "Εμφάνιση όλων", +DlgFlashScaleNoBorder : "ΧωÏίς ÏŒÏια", +DlgFlashScaleFit : "ΑκÏιβής εφαÏμογή", + +// Link Dialog +DlgLnkWindowTitle : "ΣÏνδεσμος (Link)", +DlgLnkInfoTab : "Link", +DlgLnkTargetTab : "ΠαÏάθυÏο Στόχος (Target)", + +DlgLnkType : "ΤÏπος συνδέσμου (Link)", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "ΆγκυÏα σε αυτή τη σελίδα", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "ΠÏοτόκολο", +DlgLnkProtoOther : "<άλλο>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Επιλέξτε μια άγκυÏα", +DlgLnkAnchorByName : "Βάσει του Ονόματος (Name) της άγκυÏας", +DlgLnkAnchorById : "Βάσει του Element Id", +DlgLnkNoAnchors : "(Δεν υπάÏχουν άγκυÏες στο κείμενο)", +DlgLnkEMail : "ΔιεÏθυνση ΗλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Î¤Î±Ï‡Ï…Î´Ïομείου", +DlgLnkEMailSubject : "Θέμα ΜηνÏματος", +DlgLnkEMailBody : "Κείμενο ΜηνÏματος", +DlgLnkUpload : "Αποστολή", +DlgLnkBtnUpload : "Αποστολή στον Διακομιστή", + +DlgLnkTarget : "ΠαÏάθυÏο Στόχος (Target)", +DlgLnkTargetFrame : "<πλαίσιο>", +DlgLnkTargetPopup : "<παÏάθυÏο popup>", +DlgLnkTargetBlank : "Îέο ΠαÏάθυÏο (_blank)", +DlgLnkTargetParent : "Γονικό ΠαÏάθυÏο (_parent)", +DlgLnkTargetSelf : "Ίδιο ΠαÏάθυÏο (_self)", +DlgLnkTargetTop : "Ανώτατο ΠαÏάθυÏο (_top)", +DlgLnkTargetFrameName : "Όνομα πλαισίου στόχου", +DlgLnkPopWinName : "Όνομα Popup Window", +DlgLnkPopWinFeat : "Επιλογές Popup Window", +DlgLnkPopResize : "Με αλλαγή Μεγέθους", +DlgLnkPopLocation : "ΜπάÏα Τοποθεσίας", +DlgLnkPopMenu : "ΜπάÏα Menu", +DlgLnkPopScroll : "ΜπάÏες ΚÏλισης", +DlgLnkPopStatus : "ΜπάÏα Status", +DlgLnkPopToolbar : "ΜπάÏα ΕÏγαλείων", +DlgLnkPopFullScrn : "ΟλόκληÏη η Οθόνη (IE)", +DlgLnkPopDependent : "Dependent (Netscape)", +DlgLnkPopWidth : "Πλάτος", +DlgLnkPopHeight : "Ύψος", +DlgLnkPopLeft : "Τοποθεσία ΑÏιστεÏής ΆκÏης", +DlgLnkPopTop : "Τοποθεσία Πάνω ΆκÏης", + +DlnLnkMsgNoUrl : "Εισάγετε την τοποθεσία (URL) του υπεÏσυνδέσμου (Link)", +DlnLnkMsgNoEMail : "Εισάγετε την διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου", +DlnLnkMsgNoAnchor : "Επιλέξτε ένα Anchor", +DlnLnkMsgInvPopName : "Το όνομα του popup Ï€Ïέπει να αÏχίζει με χαÏακτήÏα της αλφαβήτου και να μην πεÏιέχει κενά", + +// Color Dialog +DlgColorTitle : "Επιλογή χÏώματος", +DlgColorBtnClear : "ΚαθαÏισμός", +DlgColorHighlight : "ΠÏοεπισκόπιση", +DlgColorSelected : "Επιλεγμένο", + +// Smiley Dialog +DlgSmileyTitle : "Επιλέξτε ένα Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Επιλέξτε ένα Ειδικό ΣÏμβολο", + +// Table Dialog +DlgTableTitle : "Ιδιότητες Πίνακα", +DlgTableRows : "ΓÏαμμές", +DlgTableColumns : "Κολώνες", +DlgTableBorder : "Μέγεθος ΠεÏιθωÏίου", +DlgTableAlign : "Στοίχιση", +DlgTableAlignNotSet : "<χωÏίς>", +DlgTableAlignLeft : "ΑÏιστεÏά", +DlgTableAlignCenter : "ΚέντÏο", +DlgTableAlignRight : "Δεξιά", +DlgTableWidth : "Πλάτος", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "\%", +DlgTableHeight : "Ύψος", +DlgTableCellSpace : "Απόσταση κελιών", +DlgTableCellPad : "Γέμισμα κελιών", +DlgTableCaption : "ΥπέÏτιτλος", +DlgTableSummary : "ΠεÏίληψη", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Ιδιότητες ΚελιοÏ", +DlgCellWidth : "Πλάτος", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "\%", +DlgCellHeight : "Ύψος", +DlgCellWordWrap : "Με αλλαγή γÏαμμής", +DlgCellWordWrapNotSet : "<χωÏίς>", +DlgCellWordWrapYes : "Îαι", +DlgCellWordWrapNo : "Όχι", +DlgCellHorAlign : "ΟÏιζόντια Στοίχιση", +DlgCellHorAlignNotSet : "<χωÏίς>", +DlgCellHorAlignLeft : "ΑÏιστεÏά", +DlgCellHorAlignCenter : "ΚέντÏο", +DlgCellHorAlignRight: "Δεξιά", +DlgCellVerAlign : "Κάθετη Στοίχιση", +DlgCellVerAlignNotSet : "<χωÏίς>", +DlgCellVerAlignTop : "Πάνω (Top)", +DlgCellVerAlignMiddle : "Μέση (Middle)", +DlgCellVerAlignBottom : "Κάτω (Bottom)", +DlgCellVerAlignBaseline : "ΓÏαμμή Βάσης (Baseline)", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "ΑÏιθμός ΓÏαμμών (Rows Span)", +DlgCellCollSpan : "ΑÏιθμός Κολωνών (Columns Span)", +DlgCellBackColor : "ΧÏώμα ΥποβάθÏου", +DlgCellBorderColor : "ΧÏώμα ΠεÏιθωÏίου", +DlgCellBtnSelect : "Επιλογή...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "Αναζήτηση", +DlgFindFindBtn : "Αναζήτηση", +DlgFindNotFoundMsg : "Το κείμενο δεν βÏέθηκε.", + +// Replace Dialog +DlgReplaceTitle : "Αντικατάσταση", +DlgReplaceFindLbl : "Αναζήτηση:", +DlgReplaceReplaceLbl : "Αντικατάσταση με:", +DlgReplaceCaseChk : "Έλεγχος πεζών/κεφαλαίων", +DlgReplaceReplaceBtn : "Αντικατάσταση", +DlgReplaceReplAllBtn : "Αντικατάσταση Όλων", +DlgReplaceWordChk : "ΕÏÏεση πλήÏους λέξης", + +// Paste Operations / Dialog +PasteErrorCut : "Οι Ïυθμίσεις ασφαλείας του φυλλομετÏητή σας δεν επιτÏέπουν την επιλεγμένη εÏγασία αποκοπής. ΧÏησιμοποιείστε το πληκτÏολόγιο (Ctrl+X).", +PasteErrorCopy : "Οι Ïυθμίσεις ασφαλείας του φυλλομετÏητή σας δεν επιτÏέπουν την επιλεγμένη εÏγασία αντιγÏαφής. ΧÏησιμοποιείστε το πληκτÏολόγιο (Ctrl+C).", + +PasteAsText : "Επικόλληση ως Απλό Κείμενο", +PasteFromWord : "Επικόλληση από το Word", + +DlgPasteMsg2 : "ΠαÏακαλώ επικολήστε στο ακόλουθο κουτί χÏησιμοποιόντας το πληκτÏολόγιο (Ctrl+V) και πατήστε OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "Αγνόηση Ï€ÏοδιαγÏαφών γÏαμματοσειÏάς", +DlgPasteRemoveStyles : "ΑφαίÏεση Ï€ÏοδιαγÏαφών στÏλ", + +// Color Picker +ColorAutomatic : "Αυτόματο", +ColorMoreColors : "ΠεÏισσότεÏα χÏώματα...", + +// Document Properties +DocProps : "Ιδιότητες εγγÏάφου", + +// Anchor Dialog +DlgAnchorTitle : "Ιδιότητες άγκυÏας", +DlgAnchorName : "Όνομα άγκυÏας", +DlgAnchorErrorName : "ΠαÏακαλοÏμε εισάγετε όνομα άγκυÏας", + +// Speller Pages Dialog +DlgSpellNotInDic : "Δεν υπάÏχει στο λεξικό", +DlgSpellChangeTo : "Αλλαγή σε", +DlgSpellBtnIgnore : "Αγνόηση", +DlgSpellBtnIgnoreAll : "Αγνόηση όλων", +DlgSpellBtnReplace : "Αντικατάσταση", +DlgSpellBtnReplaceAll : "Αντικατάσταση όλων", +DlgSpellBtnUndo : "ΑναίÏεση", +DlgSpellNoSuggestions : "- Δεν υπάÏχουν Ï€Ïοτάσεις -", +DlgSpellProgress : "ΟÏθογÏαφικός έλεγχος σε εξέλιξη...", +DlgSpellNoMispell : "Ο οÏθογÏαφικός έλεγχος ολοκληÏώθηκε: Δεν βÏέθηκαν λάθη", +DlgSpellNoChanges : "Ο οÏθογÏαφικός έλεγχος ολοκληÏώθηκε: Δεν άλλαξαν λέξεις", +DlgSpellOneChange : "Ο οÏθογÏαφικός έλεγχος ολοκληÏώθηκε: Μια λέξη άλλαξε", +DlgSpellManyChanges : "Ο οÏθογÏαφικός έλεγχος ολοκληÏώθηκε: %1 λέξεις άλλαξαν", + +IeSpellDownload : "Δεν υπάÏχει εγκατεστημένος οÏθογÏάφος. Θέλετε να τον κατεβάσετε Ï„ÏŽÏα;", + +// Button Dialog +DlgButtonText : "Κείμενο (Τιμή)", +DlgButtonType : "ΤÏπος", +DlgButtonTypeBtn : "Κουμπί", +DlgButtonTypeSbm : "ΚαταχώÏηση", +DlgButtonTypeRst : "ΕπαναφοÏά", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Όνομα", +DlgCheckboxValue : "Τιμή", +DlgCheckboxSelected : "Επιλεγμένο", + +// Form Dialog +DlgFormName : "Όνομα", +DlgFormAction : "ΔÏάση", +DlgFormMethod : "Μάθοδος", + +// Select Field Dialog +DlgSelectName : "Όνομα", +DlgSelectValue : "Τιμή", +DlgSelectSize : "Μέγεθος", +DlgSelectLines : "γÏαμμές", +DlgSelectChkMulti : "Πολλαπλές επιλογές", +DlgSelectOpAvail : "Διαθέσιμες επιλογές", +DlgSelectOpText : "Κείμενο", +DlgSelectOpValue : "Τιμή", +DlgSelectBtnAdd : "ΠÏοσθήκη", +DlgSelectBtnModify : "Αλλαγή", +DlgSelectBtnUp : "Πάνω", +DlgSelectBtnDown : "Κάτω", +DlgSelectBtnSetValue : "ΠÏοεπιλεγμένη επιλογή", +DlgSelectBtnDelete : "ΔιαγÏαφή", + +// Textarea Dialog +DlgTextareaName : "Όνομα", +DlgTextareaCols : "Στήλες", +DlgTextareaRows : "ΣειÏές", + +// Text Field Dialog +DlgTextName : "Όνομα", +DlgTextValue : "Τιμή", +DlgTextCharWidth : "Μήκος χαÏακτήÏων", +DlgTextMaxChars : "Μέγιστοι χαÏακτήÏες", +DlgTextType : "ΤÏπος", +DlgTextTypeText : "Κείμενο", +DlgTextTypePass : "Κωδικός", + +// Hidden Field Dialog +DlgHiddenName : "Όνομα", +DlgHiddenValue : "Τιμή", + +// Bulleted List Dialog +BulletedListProp : "Ιδιότητες λίστας Bulleted", +NumberedListProp : "Ιδιότητες αÏιθμημένης λίστας ", +DlgLstStart : "ΑÏχή", +DlgLstType : "ΤÏπος", +DlgLstTypeCircle : "ΚÏκλος", +DlgLstTypeDisc : "Δίσκος", +DlgLstTypeSquare : "ΤετÏάγωνο", +DlgLstTypeNumbers : "ΑÏιθμοί (1, 2, 3)", +DlgLstTypeLCase : "Πεζά γÏάμματα (a, b, c)", +DlgLstTypeUCase : "Κεφαλαία γÏάμματα (A, B, C)", +DlgLstTypeSRoman : "ΜικÏά λατινικά αÏιθμητικά (i, ii, iii)", +DlgLstTypeLRoman : "Μεγάλα λατινικά αÏιθμητικά (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Γενικά", +DlgDocBackTab : "Φόντο", +DlgDocColorsTab : "ΧÏώματα και πεÏιθώÏια", +DlgDocMetaTab : "Δεδομένα Meta", + +DlgDocPageTitle : "Τίτλος σελίδας", +DlgDocLangDir : "ΚατεÏθυνση γÏαφής", +DlgDocLangDirLTR : "αÏιστεÏά Ï€Ïος δεξιά (LTR)", +DlgDocLangDirRTL : "δεξιά Ï€Ïος αÏιστεÏά (RTL)", +DlgDocLangCode : "Κωδικός γλώσσας", +DlgDocCharSet : "Κωδικοποίηση χαÏακτήÏων", +DlgDocCharSetCE : "ΚεντÏικής ΕυÏώπης", +DlgDocCharSetCT : "ΠαÏαδοσιακά κινέζικα (Big5)", +DlgDocCharSetCR : "ΚυÏιλλική", +DlgDocCharSetGR : "Ελληνική", +DlgDocCharSetJP : "Ιαπωνική", +DlgDocCharSetKR : "ΚοÏεάτικη", +DlgDocCharSetTR : "ΤουÏκική", +DlgDocCharSetUN : "Διεθνής (UTF-8)", +DlgDocCharSetWE : "Δυτικής ΕυÏώπης", +DlgDocCharSetOther : "Άλλη κωδικοποίηση χαÏακτήÏων", + +DlgDocDocType : "Επικεφαλίδα Ï„Ïπου εγγÏάφου", +DlgDocDocTypeOther : "Άλλη επικεφαλίδα Ï„Ïπου εγγÏάφου", +DlgDocIncXHTML : "Îα συμπεÏιληφθοÏν οι δηλώσεις XHTML", +DlgDocBgColor : "ΧÏώμα φόντου", +DlgDocBgImage : "ΔιεÏθυνση εικόνας φόντου", +DlgDocBgNoScroll : "Φόντο χωÏίς κÏλιση", +DlgDocCText : "Κείμενο", +DlgDocCLink : "ΣÏνδεσμος", +DlgDocCVisited : "ΣÏνδεσμος που έχει επισκευθεί", +DlgDocCActive : "ΕνεÏγός σÏνδεσμος", +DlgDocMargins : "ΠεÏιθώÏια σελίδας", +DlgDocMaTop : "ΚοÏυφή", +DlgDocMaLeft : "ΑÏιστεÏά", +DlgDocMaRight : "Δεξιά", +DlgDocMaBottom : "Κάτω", +DlgDocMeIndex : "Λέξεις κλειδιά δείκτες εγγÏάφου (διαχωÏισμός με κόμμα)", +DlgDocMeDescr : "ΠεÏιγÏαφή εγγÏάφου", +DlgDocMeAuthor : "ΣυγγÏαφέας", +DlgDocMeCopy : "Πνευματικά δικαιώματα", +DlgDocPreview : "ΠÏοεπισκόπηση", + +// Templates Dialog +Templates : "ΠÏότυπα", +DlgTemplatesTitle : "ΠÏότυπα πεÏιεχομένου", +DlgTemplatesSelMsg : "ΠαÏακαλώ επιλέξτε Ï€Ïότυπο για εισαγωγή στο Ï€ÏόγÏαμμα
    (τα υπάÏχοντα πεÏιεχόμενα θα χαθοÏν):", +DlgTemplatesLoading : "ΦόÏτωση καταλόγου Ï€ÏοτÏπων. ΠαÏακαλώ πεÏιμένετε...", +DlgTemplatesNoTpl : "(Δεν έχουν καθοÏιστεί Ï€Ïότυπα)", +DlgTemplatesReplace : "Αντικατάσταση υπάÏχοντων πεÏιεχομένων", + +// About Dialog +DlgAboutAboutTab : "Σχετικά", +DlgAboutBrowserInfoTab : "ΠληÏοφοÏίες Browser", +DlgAboutLicenseTab : "Άδεια", +DlgAboutVersion : "έκδοση", +DlgAboutInfo : "Για πεÏισσότεÏες πληÏοφοÏίες", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/en-au.js b/www/js/FCKeditor/editor/lang/en-au.js new file mode 100644 index 0000000..40cb29c --- /dev/null +++ b/www/js/FCKeditor/editor/lang/en-au.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * English (Australia) language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Collapse Toolbar", +ToolbarExpand : "Expand Toolbar", + +// Toolbar Items and Context Menu +Save : "Save", +NewPage : "New Page", +Preview : "Preview", +Cut : "Cut", +Copy : "Copy", +Paste : "Paste", +PasteText : "Paste as plain text", +PasteWord : "Paste from Word", +Print : "Print", +SelectAll : "Select All", +RemoveFormat : "Remove Format", +InsertLinkLbl : "Link", +InsertLink : "Insert/Edit Link", +RemoveLink : "Remove Link", +VisitLink : "Open Link", +Anchor : "Insert/Edit Anchor", +AnchorDelete : "Remove Anchor", +InsertImageLbl : "Image", +InsertImage : "Insert/Edit Image", +InsertFlashLbl : "Flash", +InsertFlash : "Insert/Edit Flash", +InsertTableLbl : "Table", +InsertTable : "Insert/Edit Table", +InsertLineLbl : "Line", +InsertLine : "Insert Horizontal Line", +InsertSpecialCharLbl: "Special Character", +InsertSpecialChar : "Insert Special Character", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Insert Smiley", +About : "About FCKeditor", +Bold : "Bold", +Italic : "Italic", +Underline : "Underline", +StrikeThrough : "Strike Through", +Subscript : "Subscript", +Superscript : "Superscript", +LeftJustify : "Left Justify", +CenterJustify : "Centre Justify", +RightJustify : "Right Justify", +BlockJustify : "Block Justify", +DecreaseIndent : "Decrease Indent", +IncreaseIndent : "Increase Indent", +Blockquote : "Blockquote", +CreateDiv : "Create Div Container", +EditDiv : "Edit Div Container", +DeleteDiv : "Remove Div Container", +Undo : "Undo", +Redo : "Redo", +NumberedListLbl : "Numbered List", +NumberedList : "Insert/Remove Numbered List", +BulletedListLbl : "Bulleted List", +BulletedList : "Insert/Remove Bulleted List", +ShowTableBorders : "Show Table Borders", +ShowDetails : "Show Details", +Style : "Style", +FontFormat : "Format", +Font : "Font", +FontSize : "Size", +TextColor : "Text Colour", +BGColor : "Background Colour", +Source : "Source", +Find : "Find", +Replace : "Replace", +SpellCheck : "Check Spelling", +UniversalKeyboard : "Universal Keyboard", +PageBreakLbl : "Page Break", +PageBreak : "Insert Page Break", + +Form : "Form", +Checkbox : "Checkbox", +RadioButton : "Radio Button", +TextField : "Text Field", +Textarea : "Textarea", +HiddenField : "Hidden Field", +Button : "Button", +SelectionField : "Selection Field", +ImageButton : "Image Button", + +FitWindow : "Maximize the editor size", +ShowBlocks : "Show Blocks", + +// Context Menu +EditLink : "Edit Link", +CellCM : "Cell", +RowCM : "Row", +ColumnCM : "Column", +InsertRowAfter : "Insert Row After", +InsertRowBefore : "Insert Row Before", +DeleteRows : "Delete Rows", +InsertColumnAfter : "Insert Column After", +InsertColumnBefore : "Insert Column Before", +DeleteColumns : "Delete Columns", +InsertCellAfter : "Insert Cell After", +InsertCellBefore : "Insert Cell Before", +DeleteCells : "Delete Cells", +MergeCells : "Merge Cells", +MergeRight : "Merge Right", +MergeDown : "Merge Down", +HorizontalSplitCell : "Split Cell Horizontally", +VerticalSplitCell : "Split Cell Vertically", +TableDelete : "Delete Table", +CellProperties : "Cell Properties", +TableProperties : "Table Properties", +ImageProperties : "Image Properties", +FlashProperties : "Flash Properties", + +AnchorProp : "Anchor Properties", +ButtonProp : "Button Properties", +CheckboxProp : "Checkbox Properties", +HiddenFieldProp : "Hidden Field Properties", +RadioButtonProp : "Radio Button Properties", +ImageButtonProp : "Image Button Properties", +TextFieldProp : "Text Field Properties", +SelectionFieldProp : "Selection Field Properties", +TextareaProp : "Textarea Properties", +FormProp : "Form Properties", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Processing XHTML. Please wait...", +Done : "Done", +PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?", +NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?", +UnknownToolbarItem : "Unknown toolbar item \"%1\"", +UnknownCommand : "Unknown command name \"%1\"", +NotImplemented : "Command not implemented", +UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Cancel", +DlgBtnClose : "Close", +DlgBtnBrowseServer : "Browse Server", +DlgAdvancedTag : "Advanced", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Please insert the URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Language Direction", +DlgGenLangDirLtr : "Left to Right (LTR)", +DlgGenLangDirRtl : "Right to Left (RTL)", +DlgGenLangCode : "Language Code", +DlgGenAccessKey : "Access Key", +DlgGenName : "Name", +DlgGenTabIndex : "Tab Index", +DlgGenLongDescr : "Long Description URL", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "Advisory Title", +DlgGenContType : "Advisory Content Type", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Image Properties", +DlgImgInfoTab : "Image Info", +DlgImgBtnUpload : "Send it to the Server", +DlgImgURL : "URL", +DlgImgUpload : "Upload", +DlgImgAlt : "Alternative Text", +DlgImgWidth : "Width", +DlgImgHeight : "Height", +DlgImgLockRatio : "Lock Ratio", +DlgBtnResetSize : "Reset Size", +DlgImgBorder : "Border", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Align", +DlgImgAlignLeft : "Left", +DlgImgAlignAbsBottom: "Abs Bottom", +DlgImgAlignAbsMiddle: "Abs Middle", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Bottom", +DlgImgAlignMiddle : "Middle", +DlgImgAlignRight : "Right", +DlgImgAlignTextTop : "Text Top", +DlgImgAlignTop : "Top", +DlgImgPreview : "Preview", +DlgImgAlertUrl : "Please type the image URL", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash Properties", +DlgFlashChkPlay : "Auto Play", +DlgFlashChkLoop : "Loop", +DlgFlashChkMenu : "Enable Flash Menu", +DlgFlashScale : "Scale", +DlgFlashScaleAll : "Show all", +DlgFlashScaleNoBorder : "No Border", +DlgFlashScaleFit : "Exact Fit", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link Info", +DlgLnkTargetTab : "Target", + +DlgLnkType : "Link Type", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Link to anchor in the text", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Select an Anchor", +DlgLnkAnchorByName : "By Anchor Name", +DlgLnkAnchorById : "By Element Id", +DlgLnkNoAnchors : "(No anchors available in the document)", +DlgLnkEMail : "E-Mail Address", +DlgLnkEMailSubject : "Message Subject", +DlgLnkEMailBody : "Message Body", +DlgLnkUpload : "Upload", +DlgLnkBtnUpload : "Send it to the Server", + +DlgLnkTarget : "Target", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "New Window (_blank)", +DlgLnkTargetParent : "Parent Window (_parent)", +DlgLnkTargetSelf : "Same Window (_self)", +DlgLnkTargetTop : "Topmost Window (_top)", +DlgLnkTargetFrameName : "Target Frame Name", +DlgLnkPopWinName : "Popup Window Name", +DlgLnkPopWinFeat : "Popup Window Features", +DlgLnkPopResize : "Resizable", +DlgLnkPopLocation : "Location Bar", +DlgLnkPopMenu : "Menu Bar", +DlgLnkPopScroll : "Scroll Bars", +DlgLnkPopStatus : "Status Bar", +DlgLnkPopToolbar : "Toolbar", +DlgLnkPopFullScrn : "Full Screen (IE)", +DlgLnkPopDependent : "Dependent (Netscape)", +DlgLnkPopWidth : "Width", +DlgLnkPopHeight : "Height", +DlgLnkPopLeft : "Left Position", +DlgLnkPopTop : "Top Position", + +DlnLnkMsgNoUrl : "Please type the link URL", +DlnLnkMsgNoEMail : "Please type the e-mail address", +DlnLnkMsgNoAnchor : "Please select an anchor", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", + +// Color Dialog +DlgColorTitle : "Select Colour", +DlgColorBtnClear : "Clear", +DlgColorHighlight : "Highlight", +DlgColorSelected : "Selected", + +// Smiley Dialog +DlgSmileyTitle : "Insert a Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Select Special Character", + +// Table Dialog +DlgTableTitle : "Table Properties", +DlgTableRows : "Rows", +DlgTableColumns : "Columns", +DlgTableBorder : "Border size", +DlgTableAlign : "Alignment", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Left", +DlgTableAlignCenter : "Centre", +DlgTableAlignRight : "Right", +DlgTableWidth : "Width", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "percent", +DlgTableHeight : "Height", +DlgTableCellSpace : "Cell spacing", +DlgTableCellPad : "Cell padding", +DlgTableCaption : "Caption", +DlgTableSummary : "Summary", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Cell Properties", +DlgCellWidth : "Width", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "percent", +DlgCellHeight : "Height", +DlgCellWordWrap : "Word Wrap", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Yes", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Horizontal Alignment", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Left", +DlgCellHorAlignCenter : "Centre", +DlgCellHorAlignRight: "Right", +DlgCellVerAlign : "Vertical Alignment", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Top", +DlgCellVerAlignMiddle : "Middle", +DlgCellVerAlignBottom : "Bottom", +DlgCellVerAlignBaseline : "Baseline", +DlgCellType : "Cell Type", +DlgCellTypeData : "Data", +DlgCellTypeHeader : "Header", +DlgCellRowSpan : "Rows Span", +DlgCellCollSpan : "Columns Span", +DlgCellBackColor : "Background Colour", +DlgCellBorderColor : "Border Colour", +DlgCellBtnSelect : "Select...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", + +// Find Dialog +DlgFindTitle : "Find", +DlgFindFindBtn : "Find", +DlgFindNotFoundMsg : "The specified text was not found.", + +// Replace Dialog +DlgReplaceTitle : "Replace", +DlgReplaceFindLbl : "Find what:", +DlgReplaceReplaceLbl : "Replace with:", +DlgReplaceCaseChk : "Match case", +DlgReplaceReplaceBtn : "Replace", +DlgReplaceReplAllBtn : "Replace All", +DlgReplaceWordChk : "Match whole word", + +// Paste Operations / Dialog +PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).", +PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).", + +PasteAsText : "Paste as Plain Text", +PasteFromWord : "Paste from Word", + +DlgPasteMsg2 : "Please paste inside the following box using the keyboard (Ctrl+V) and hit OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", +DlgPasteIgnoreFont : "Ignore Font Face definitions", +DlgPasteRemoveStyles : "Remove Styles definitions", + +// Color Picker +ColorAutomatic : "Automatic", +ColorMoreColors : "More Colours...", + +// Document Properties +DocProps : "Document Properties", + +// Anchor Dialog +DlgAnchorTitle : "Anchor Properties", +DlgAnchorName : "Anchor Name", +DlgAnchorErrorName : "Please type the anchor name", + +// Speller Pages Dialog +DlgSpellNotInDic : "Not in dictionary", +DlgSpellChangeTo : "Change to", +DlgSpellBtnIgnore : "Ignore", +DlgSpellBtnIgnoreAll : "Ignore All", +DlgSpellBtnReplace : "Replace", +DlgSpellBtnReplaceAll : "Replace All", +DlgSpellBtnUndo : "Undo", +DlgSpellNoSuggestions : "- No suggestions -", +DlgSpellProgress : "Spell check in progress...", +DlgSpellNoMispell : "Spell check complete: No misspellings found", +DlgSpellNoChanges : "Spell check complete: No words changed", +DlgSpellOneChange : "Spell check complete: One word changed", +DlgSpellManyChanges : "Spell check complete: %1 words changed", + +IeSpellDownload : "Spell checker not installed. Do you want to download it now?", + +// Button Dialog +DlgButtonText : "Text (Value)", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Button", +DlgButtonTypeSbm : "Submit", +DlgButtonTypeRst : "Reset", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Name", +DlgCheckboxValue : "Value", +DlgCheckboxSelected : "Selected", + +// Form Dialog +DlgFormName : "Name", +DlgFormAction : "Action", +DlgFormMethod : "Method", + +// Select Field Dialog +DlgSelectName : "Name", +DlgSelectValue : "Value", +DlgSelectSize : "Size", +DlgSelectLines : "lines", +DlgSelectChkMulti : "Allow multiple selections", +DlgSelectOpAvail : "Available Options", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Value", +DlgSelectBtnAdd : "Add", +DlgSelectBtnModify : "Modify", +DlgSelectBtnUp : "Up", +DlgSelectBtnDown : "Down", +DlgSelectBtnSetValue : "Set as selected value", +DlgSelectBtnDelete : "Delete", + +// Textarea Dialog +DlgTextareaName : "Name", +DlgTextareaCols : "Columns", +DlgTextareaRows : "Rows", + +// Text Field Dialog +DlgTextName : "Name", +DlgTextValue : "Value", +DlgTextCharWidth : "Character Width", +DlgTextMaxChars : "Maximum Characters", +DlgTextType : "Type", +DlgTextTypeText : "Text", +DlgTextTypePass : "Password", + +// Hidden Field Dialog +DlgHiddenName : "Name", +DlgHiddenValue : "Value", + +// Bulleted List Dialog +BulletedListProp : "Bulleted List Properties", +NumberedListProp : "Numbered List Properties", +DlgLstStart : "Start", +DlgLstType : "Type", +DlgLstTypeCircle : "Circle", +DlgLstTypeDisc : "Disc", +DlgLstTypeSquare : "Square", +DlgLstTypeNumbers : "Numbers (1, 2, 3)", +DlgLstTypeLCase : "Lowercase Letters (a, b, c)", +DlgLstTypeUCase : "Uppercase Letters (A, B, C)", +DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", +DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "General", +DlgDocBackTab : "Background", +DlgDocColorsTab : "Colours and Margins", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Page Title", +DlgDocLangDir : "Language Direction", +DlgDocLangDirLTR : "Left to Right (LTR)", +DlgDocLangDirRTL : "Right to Left (RTL)", +DlgDocLangCode : "Language Code", +DlgDocCharSet : "Character Set Encoding", +DlgDocCharSetCE : "Central European", +DlgDocCharSetCT : "Chinese Traditional (Big5)", +DlgDocCharSetCR : "Cyrillic", +DlgDocCharSetGR : "Greek", +DlgDocCharSetJP : "Japanese", +DlgDocCharSetKR : "Korean", +DlgDocCharSetTR : "Turkish", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Western European", +DlgDocCharSetOther : "Other Character Set Encoding", + +DlgDocDocType : "Document Type Heading", +DlgDocDocTypeOther : "Other Document Type Heading", +DlgDocIncXHTML : "Include XHTML Declarations", +DlgDocBgColor : "Background Colour", +DlgDocBgImage : "Background Image URL", +DlgDocBgNoScroll : "Nonscrolling Background", +DlgDocCText : "Text", +DlgDocCLink : "Link", +DlgDocCVisited : "Visited Link", +DlgDocCActive : "Active Link", +DlgDocMargins : "Page Margins", +DlgDocMaTop : "Top", +DlgDocMaLeft : "Left", +DlgDocMaRight : "Right", +DlgDocMaBottom : "Bottom", +DlgDocMeIndex : "Document Indexing Keywords (comma separated)", +DlgDocMeDescr : "Document Description", +DlgDocMeAuthor : "Author", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Preview", + +// Templates Dialog +Templates : "Templates", +DlgTemplatesTitle : "Content Templates", +DlgTemplatesSelMsg : "Please select the template to open in the editor
    (the actual contents will be lost):", +DlgTemplatesLoading : "Loading templates list. Please wait...", +DlgTemplatesNoTpl : "(No templates defined)", +DlgTemplatesReplace : "Replace actual contents", + +// About Dialog +DlgAboutAboutTab : "About", +DlgAboutBrowserInfoTab : "Browser Info", +DlgAboutLicenseTab : "License", +DlgAboutVersion : "version", +DlgAboutInfo : "For further information go to", + +// Div Dialog +DlgDivGeneralTab : "General", +DlgDivAdvancedTab : "Advanced", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Inline Style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/en-ca.js b/www/js/FCKeditor/editor/lang/en-ca.js new file mode 100644 index 0000000..9ffc80f --- /dev/null +++ b/www/js/FCKeditor/editor/lang/en-ca.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * English (Canadian) language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Collapse Toolbar", +ToolbarExpand : "Expand Toolbar", + +// Toolbar Items and Context Menu +Save : "Save", +NewPage : "New Page", +Preview : "Preview", +Cut : "Cut", +Copy : "Copy", +Paste : "Paste", +PasteText : "Paste as plain text", +PasteWord : "Paste from Word", +Print : "Print", +SelectAll : "Select All", +RemoveFormat : "Remove Format", +InsertLinkLbl : "Link", +InsertLink : "Insert/Edit Link", +RemoveLink : "Remove Link", +VisitLink : "Open Link", +Anchor : "Insert/Edit Anchor", +AnchorDelete : "Remove Anchor", +InsertImageLbl : "Image", +InsertImage : "Insert/Edit Image", +InsertFlashLbl : "Flash", +InsertFlash : "Insert/Edit Flash", +InsertTableLbl : "Table", +InsertTable : "Insert/Edit Table", +InsertLineLbl : "Line", +InsertLine : "Insert Horizontal Line", +InsertSpecialCharLbl: "Special Character", +InsertSpecialChar : "Insert Special Character", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Insert Smiley", +About : "About FCKeditor", +Bold : "Bold", +Italic : "Italic", +Underline : "Underline", +StrikeThrough : "Strike Through", +Subscript : "Subscript", +Superscript : "Superscript", +LeftJustify : "Left Justify", +CenterJustify : "Centre Justify", +RightJustify : "Right Justify", +BlockJustify : "Block Justify", +DecreaseIndent : "Decrease Indent", +IncreaseIndent : "Increase Indent", +Blockquote : "Blockquote", +CreateDiv : "Create Div Container", +EditDiv : "Edit Div Container", +DeleteDiv : "Remove Div Container", +Undo : "Undo", +Redo : "Redo", +NumberedListLbl : "Numbered List", +NumberedList : "Insert/Remove Numbered List", +BulletedListLbl : "Bulleted List", +BulletedList : "Insert/Remove Bulleted List", +ShowTableBorders : "Show Table Borders", +ShowDetails : "Show Details", +Style : "Style", +FontFormat : "Format", +Font : "Font", +FontSize : "Size", +TextColor : "Text Colour", +BGColor : "Background Colour", +Source : "Source", +Find : "Find", +Replace : "Replace", +SpellCheck : "Check Spelling", +UniversalKeyboard : "Universal Keyboard", +PageBreakLbl : "Page Break", +PageBreak : "Insert Page Break", + +Form : "Form", +Checkbox : "Checkbox", +RadioButton : "Radio Button", +TextField : "Text Field", +Textarea : "Textarea", +HiddenField : "Hidden Field", +Button : "Button", +SelectionField : "Selection Field", +ImageButton : "Image Button", + +FitWindow : "Maximize the editor size", +ShowBlocks : "Show Blocks", + +// Context Menu +EditLink : "Edit Link", +CellCM : "Cell", +RowCM : "Row", +ColumnCM : "Column", +InsertRowAfter : "Insert Row After", +InsertRowBefore : "Insert Row Before", +DeleteRows : "Delete Rows", +InsertColumnAfter : "Insert Column After", +InsertColumnBefore : "Insert Column Before", +DeleteColumns : "Delete Columns", +InsertCellAfter : "Insert Cell After", +InsertCellBefore : "Insert Cell Before", +DeleteCells : "Delete Cells", +MergeCells : "Merge Cells", +MergeRight : "Merge Right", +MergeDown : "Merge Down", +HorizontalSplitCell : "Split Cell Horizontally", +VerticalSplitCell : "Split Cell Vertically", +TableDelete : "Delete Table", +CellProperties : "Cell Properties", +TableProperties : "Table Properties", +ImageProperties : "Image Properties", +FlashProperties : "Flash Properties", + +AnchorProp : "Anchor Properties", +ButtonProp : "Button Properties", +CheckboxProp : "Checkbox Properties", +HiddenFieldProp : "Hidden Field Properties", +RadioButtonProp : "Radio Button Properties", +ImageButtonProp : "Image Button Properties", +TextFieldProp : "Text Field Properties", +SelectionFieldProp : "Selection Field Properties", +TextareaProp : "Textarea Properties", +FormProp : "Form Properties", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Processing XHTML. Please wait...", +Done : "Done", +PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?", +NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?", +UnknownToolbarItem : "Unknown toolbar item \"%1\"", +UnknownCommand : "Unknown command name \"%1\"", +NotImplemented : "Command not implemented", +UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Cancel", +DlgBtnClose : "Close", +DlgBtnBrowseServer : "Browse Server", +DlgAdvancedTag : "Advanced", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Please insert the URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Language Direction", +DlgGenLangDirLtr : "Left to Right (LTR)", +DlgGenLangDirRtl : "Right to Left (RTL)", +DlgGenLangCode : "Language Code", +DlgGenAccessKey : "Access Key", +DlgGenName : "Name", +DlgGenTabIndex : "Tab Index", +DlgGenLongDescr : "Long Description URL", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "Advisory Title", +DlgGenContType : "Advisory Content Type", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Image Properties", +DlgImgInfoTab : "Image Info", +DlgImgBtnUpload : "Send it to the Server", +DlgImgURL : "URL", +DlgImgUpload : "Upload", +DlgImgAlt : "Alternative Text", +DlgImgWidth : "Width", +DlgImgHeight : "Height", +DlgImgLockRatio : "Lock Ratio", +DlgBtnResetSize : "Reset Size", +DlgImgBorder : "Border", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Align", +DlgImgAlignLeft : "Left", +DlgImgAlignAbsBottom: "Abs Bottom", +DlgImgAlignAbsMiddle: "Abs Middle", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Bottom", +DlgImgAlignMiddle : "Middle", +DlgImgAlignRight : "Right", +DlgImgAlignTextTop : "Text Top", +DlgImgAlignTop : "Top", +DlgImgPreview : "Preview", +DlgImgAlertUrl : "Please type the image URL", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash Properties", +DlgFlashChkPlay : "Auto Play", +DlgFlashChkLoop : "Loop", +DlgFlashChkMenu : "Enable Flash Menu", +DlgFlashScale : "Scale", +DlgFlashScaleAll : "Show all", +DlgFlashScaleNoBorder : "No Border", +DlgFlashScaleFit : "Exact Fit", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link Info", +DlgLnkTargetTab : "Target", + +DlgLnkType : "Link Type", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Link to anchor in the text", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Select an Anchor", +DlgLnkAnchorByName : "By Anchor Name", +DlgLnkAnchorById : "By Element Id", +DlgLnkNoAnchors : "(No anchors available in the document)", +DlgLnkEMail : "E-Mail Address", +DlgLnkEMailSubject : "Message Subject", +DlgLnkEMailBody : "Message Body", +DlgLnkUpload : "Upload", +DlgLnkBtnUpload : "Send it to the Server", + +DlgLnkTarget : "Target", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "New Window (_blank)", +DlgLnkTargetParent : "Parent Window (_parent)", +DlgLnkTargetSelf : "Same Window (_self)", +DlgLnkTargetTop : "Topmost Window (_top)", +DlgLnkTargetFrameName : "Target Frame Name", +DlgLnkPopWinName : "Popup Window Name", +DlgLnkPopWinFeat : "Popup Window Features", +DlgLnkPopResize : "Resizable", +DlgLnkPopLocation : "Location Bar", +DlgLnkPopMenu : "Menu Bar", +DlgLnkPopScroll : "Scroll Bars", +DlgLnkPopStatus : "Status Bar", +DlgLnkPopToolbar : "Toolbar", +DlgLnkPopFullScrn : "Full Screen (IE)", +DlgLnkPopDependent : "Dependent (Netscape)", +DlgLnkPopWidth : "Width", +DlgLnkPopHeight : "Height", +DlgLnkPopLeft : "Left Position", +DlgLnkPopTop : "Top Position", + +DlnLnkMsgNoUrl : "Please type the link URL", +DlnLnkMsgNoEMail : "Please type the e-mail address", +DlnLnkMsgNoAnchor : "Please select an anchor", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", + +// Color Dialog +DlgColorTitle : "Select Colour", +DlgColorBtnClear : "Clear", +DlgColorHighlight : "Highlight", +DlgColorSelected : "Selected", + +// Smiley Dialog +DlgSmileyTitle : "Insert a Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Select Special Character", + +// Table Dialog +DlgTableTitle : "Table Properties", +DlgTableRows : "Rows", +DlgTableColumns : "Columns", +DlgTableBorder : "Border size", +DlgTableAlign : "Alignment", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Left", +DlgTableAlignCenter : "Centre", +DlgTableAlignRight : "Right", +DlgTableWidth : "Width", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "percent", +DlgTableHeight : "Height", +DlgTableCellSpace : "Cell spacing", +DlgTableCellPad : "Cell padding", +DlgTableCaption : "Caption", +DlgTableSummary : "Summary", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Cell Properties", +DlgCellWidth : "Width", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "percent", +DlgCellHeight : "Height", +DlgCellWordWrap : "Word Wrap", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Yes", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Horizontal Alignment", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Left", +DlgCellHorAlignCenter : "Centre", +DlgCellHorAlignRight: "Right", +DlgCellVerAlign : "Vertical Alignment", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Top", +DlgCellVerAlignMiddle : "Middle", +DlgCellVerAlignBottom : "Bottom", +DlgCellVerAlignBaseline : "Baseline", +DlgCellType : "Cell Type", +DlgCellTypeData : "Data", +DlgCellTypeHeader : "Header", +DlgCellRowSpan : "Rows Span", +DlgCellCollSpan : "Columns Span", +DlgCellBackColor : "Background Colour", +DlgCellBorderColor : "Border Colour", +DlgCellBtnSelect : "Select...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", + +// Find Dialog +DlgFindTitle : "Find", +DlgFindFindBtn : "Find", +DlgFindNotFoundMsg : "The specified text was not found.", + +// Replace Dialog +DlgReplaceTitle : "Replace", +DlgReplaceFindLbl : "Find what:", +DlgReplaceReplaceLbl : "Replace with:", +DlgReplaceCaseChk : "Match case", +DlgReplaceReplaceBtn : "Replace", +DlgReplaceReplAllBtn : "Replace All", +DlgReplaceWordChk : "Match whole word", + +// Paste Operations / Dialog +PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).", +PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).", + +PasteAsText : "Paste as Plain Text", +PasteFromWord : "Paste from Word", + +DlgPasteMsg2 : "Please paste inside the following box using the keyboard (Ctrl+V) and hit OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", +DlgPasteIgnoreFont : "Ignore Font Face definitions", +DlgPasteRemoveStyles : "Remove Styles definitions", + +// Color Picker +ColorAutomatic : "Automatic", +ColorMoreColors : "More Colours...", + +// Document Properties +DocProps : "Document Properties", + +// Anchor Dialog +DlgAnchorTitle : "Anchor Properties", +DlgAnchorName : "Anchor Name", +DlgAnchorErrorName : "Please type the anchor name", + +// Speller Pages Dialog +DlgSpellNotInDic : "Not in dictionary", +DlgSpellChangeTo : "Change to", +DlgSpellBtnIgnore : "Ignore", +DlgSpellBtnIgnoreAll : "Ignore All", +DlgSpellBtnReplace : "Replace", +DlgSpellBtnReplaceAll : "Replace All", +DlgSpellBtnUndo : "Undo", +DlgSpellNoSuggestions : "- No suggestions -", +DlgSpellProgress : "Spell check in progress...", +DlgSpellNoMispell : "Spell check complete: No misspellings found", +DlgSpellNoChanges : "Spell check complete: No words changed", +DlgSpellOneChange : "Spell check complete: One word changed", +DlgSpellManyChanges : "Spell check complete: %1 words changed", + +IeSpellDownload : "Spell checker not installed. Do you want to download it now?", + +// Button Dialog +DlgButtonText : "Text (Value)", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Button", +DlgButtonTypeSbm : "Submit", +DlgButtonTypeRst : "Reset", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Name", +DlgCheckboxValue : "Value", +DlgCheckboxSelected : "Selected", + +// Form Dialog +DlgFormName : "Name", +DlgFormAction : "Action", +DlgFormMethod : "Method", + +// Select Field Dialog +DlgSelectName : "Name", +DlgSelectValue : "Value", +DlgSelectSize : "Size", +DlgSelectLines : "lines", +DlgSelectChkMulti : "Allow multiple selections", +DlgSelectOpAvail : "Available Options", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Value", +DlgSelectBtnAdd : "Add", +DlgSelectBtnModify : "Modify", +DlgSelectBtnUp : "Up", +DlgSelectBtnDown : "Down", +DlgSelectBtnSetValue : "Set as selected value", +DlgSelectBtnDelete : "Delete", + +// Textarea Dialog +DlgTextareaName : "Name", +DlgTextareaCols : "Columns", +DlgTextareaRows : "Rows", + +// Text Field Dialog +DlgTextName : "Name", +DlgTextValue : "Value", +DlgTextCharWidth : "Character Width", +DlgTextMaxChars : "Maximum Characters", +DlgTextType : "Type", +DlgTextTypeText : "Text", +DlgTextTypePass : "Password", + +// Hidden Field Dialog +DlgHiddenName : "Name", +DlgHiddenValue : "Value", + +// Bulleted List Dialog +BulletedListProp : "Bulleted List Properties", +NumberedListProp : "Numbered List Properties", +DlgLstStart : "Start", +DlgLstType : "Type", +DlgLstTypeCircle : "Circle", +DlgLstTypeDisc : "Disc", +DlgLstTypeSquare : "Square", +DlgLstTypeNumbers : "Numbers (1, 2, 3)", +DlgLstTypeLCase : "Lowercase Letters (a, b, c)", +DlgLstTypeUCase : "Uppercase Letters (A, B, C)", +DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", +DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "General", +DlgDocBackTab : "Background", +DlgDocColorsTab : "Colours and Margins", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Page Title", +DlgDocLangDir : "Language Direction", +DlgDocLangDirLTR : "Left to Right (LTR)", +DlgDocLangDirRTL : "Right to Left (RTL)", +DlgDocLangCode : "Language Code", +DlgDocCharSet : "Character Set Encoding", +DlgDocCharSetCE : "Central European", +DlgDocCharSetCT : "Chinese Traditional (Big5)", +DlgDocCharSetCR : "Cyrillic", +DlgDocCharSetGR : "Greek", +DlgDocCharSetJP : "Japanese", +DlgDocCharSetKR : "Korean", +DlgDocCharSetTR : "Turkish", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Western European", +DlgDocCharSetOther : "Other Character Set Encoding", + +DlgDocDocType : "Document Type Heading", +DlgDocDocTypeOther : "Other Document Type Heading", +DlgDocIncXHTML : "Include XHTML Declarations", +DlgDocBgColor : "Background Colour", +DlgDocBgImage : "Background Image URL", +DlgDocBgNoScroll : "Nonscrolling Background", +DlgDocCText : "Text", +DlgDocCLink : "Link", +DlgDocCVisited : "Visited Link", +DlgDocCActive : "Active Link", +DlgDocMargins : "Page Margins", +DlgDocMaTop : "Top", +DlgDocMaLeft : "Left", +DlgDocMaRight : "Right", +DlgDocMaBottom : "Bottom", +DlgDocMeIndex : "Document Indexing Keywords (comma separated)", +DlgDocMeDescr : "Document Description", +DlgDocMeAuthor : "Author", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Preview", + +// Templates Dialog +Templates : "Templates", +DlgTemplatesTitle : "Content Templates", +DlgTemplatesSelMsg : "Please select the template to open in the editor
    (the actual contents will be lost):", +DlgTemplatesLoading : "Loading templates list. Please wait...", +DlgTemplatesNoTpl : "(No templates defined)", +DlgTemplatesReplace : "Replace actual contents", + +// About Dialog +DlgAboutAboutTab : "About", +DlgAboutBrowserInfoTab : "Browser Info", +DlgAboutLicenseTab : "License", +DlgAboutVersion : "version", +DlgAboutInfo : "For further information go to", + +// Div Dialog +DlgDivGeneralTab : "General", +DlgDivAdvancedTab : "Advanced", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Inline Style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/en-uk.js b/www/js/FCKeditor/editor/lang/en-uk.js new file mode 100644 index 0000000..316427c --- /dev/null +++ b/www/js/FCKeditor/editor/lang/en-uk.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * English (United Kingdom) language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Collapse Toolbar", +ToolbarExpand : "Expand Toolbar", + +// Toolbar Items and Context Menu +Save : "Save", +NewPage : "New Page", +Preview : "Preview", +Cut : "Cut", +Copy : "Copy", +Paste : "Paste", +PasteText : "Paste as plain text", +PasteWord : "Paste from Word", +Print : "Print", +SelectAll : "Select All", +RemoveFormat : "Remove Format", +InsertLinkLbl : "Link", +InsertLink : "Insert/Edit Link", +RemoveLink : "Remove Link", +VisitLink : "Open Link", +Anchor : "Insert/Edit Anchor", +AnchorDelete : "Remove Anchor", +InsertImageLbl : "Image", +InsertImage : "Insert/Edit Image", +InsertFlashLbl : "Flash", +InsertFlash : "Insert/Edit Flash", +InsertTableLbl : "Table", +InsertTable : "Insert/Edit Table", +InsertLineLbl : "Line", +InsertLine : "Insert Horizontal Line", +InsertSpecialCharLbl: "Special Character", +InsertSpecialChar : "Insert Special Character", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Insert Smiley", +About : "About FCKeditor", +Bold : "Bold", +Italic : "Italic", +Underline : "Underline", +StrikeThrough : "Strike Through", +Subscript : "Subscript", +Superscript : "Superscript", +LeftJustify : "Left Justify", +CenterJustify : "Centre Justify", +RightJustify : "Right Justify", +BlockJustify : "Block Justify", +DecreaseIndent : "Decrease Indent", +IncreaseIndent : "Increase Indent", +Blockquote : "Blockquote", +CreateDiv : "Create Div Container", +EditDiv : "Edit Div Container", +DeleteDiv : "Remove Div Container", +Undo : "Undo", +Redo : "Redo", +NumberedListLbl : "Numbered List", +NumberedList : "Insert/Remove Numbered List", +BulletedListLbl : "Bulleted List", +BulletedList : "Insert/Remove Bulleted List", +ShowTableBorders : "Show Table Borders", +ShowDetails : "Show Details", +Style : "Style", +FontFormat : "Format", +Font : "Font", +FontSize : "Size", +TextColor : "Text Colour", +BGColor : "Background Colour", +Source : "Source", +Find : "Find", +Replace : "Replace", +SpellCheck : "Check Spelling", +UniversalKeyboard : "Universal Keyboard", +PageBreakLbl : "Page Break", +PageBreak : "Insert Page Break", + +Form : "Form", +Checkbox : "Checkbox", +RadioButton : "Radio Button", +TextField : "Text Field", +Textarea : "Textarea", +HiddenField : "Hidden Field", +Button : "Button", +SelectionField : "Selection Field", +ImageButton : "Image Button", + +FitWindow : "Maximize the editor size", +ShowBlocks : "Show Blocks", + +// Context Menu +EditLink : "Edit Link", +CellCM : "Cell", +RowCM : "Row", +ColumnCM : "Column", +InsertRowAfter : "Insert Row After", +InsertRowBefore : "Insert Row Before", +DeleteRows : "Delete Rows", +InsertColumnAfter : "Insert Column After", +InsertColumnBefore : "Insert Column Before", +DeleteColumns : "Delete Columns", +InsertCellAfter : "Insert Cell After", +InsertCellBefore : "Insert Cell Before", +DeleteCells : "Delete Cells", +MergeCells : "Merge Cells", +MergeRight : "Merge Right", +MergeDown : "Merge Down", +HorizontalSplitCell : "Split Cell Horizontally", +VerticalSplitCell : "Split Cell Vertically", +TableDelete : "Delete Table", +CellProperties : "Cell Properties", +TableProperties : "Table Properties", +ImageProperties : "Image Properties", +FlashProperties : "Flash Properties", + +AnchorProp : "Anchor Properties", +ButtonProp : "Button Properties", +CheckboxProp : "Checkbox Properties", +HiddenFieldProp : "Hidden Field Properties", +RadioButtonProp : "Radio Button Properties", +ImageButtonProp : "Image Button Properties", +TextFieldProp : "Text Field Properties", +SelectionFieldProp : "Selection Field Properties", +TextareaProp : "Textarea Properties", +FormProp : "Form Properties", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Processing XHTML. Please wait...", +Done : "Done", +PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?", +NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?", +UnknownToolbarItem : "Unknown toolbar item \"%1\"", +UnknownCommand : "Unknown command name \"%1\"", +NotImplemented : "Command not implemented", +UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Cancel", +DlgBtnClose : "Close", +DlgBtnBrowseServer : "Browse Server", +DlgAdvancedTag : "Advanced", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Please insert the URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Language Direction", +DlgGenLangDirLtr : "Left to Right (LTR)", +DlgGenLangDirRtl : "Right to Left (RTL)", +DlgGenLangCode : "Language Code", +DlgGenAccessKey : "Access Key", +DlgGenName : "Name", +DlgGenTabIndex : "Tab Index", +DlgGenLongDescr : "Long Description URL", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "Advisory Title", +DlgGenContType : "Advisory Content Type", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Image Properties", +DlgImgInfoTab : "Image Info", +DlgImgBtnUpload : "Send it to the Server", +DlgImgURL : "URL", +DlgImgUpload : "Upload", +DlgImgAlt : "Alternative Text", +DlgImgWidth : "Width", +DlgImgHeight : "Height", +DlgImgLockRatio : "Lock Ratio", +DlgBtnResetSize : "Reset Size", +DlgImgBorder : "Border", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Align", +DlgImgAlignLeft : "Left", +DlgImgAlignAbsBottom: "Abs Bottom", +DlgImgAlignAbsMiddle: "Abs Middle", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Bottom", +DlgImgAlignMiddle : "Middle", +DlgImgAlignRight : "Right", +DlgImgAlignTextTop : "Text Top", +DlgImgAlignTop : "Top", +DlgImgPreview : "Preview", +DlgImgAlertUrl : "Please type the image URL", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash Properties", +DlgFlashChkPlay : "Auto Play", +DlgFlashChkLoop : "Loop", +DlgFlashChkMenu : "Enable Flash Menu", +DlgFlashScale : "Scale", +DlgFlashScaleAll : "Show all", +DlgFlashScaleNoBorder : "No Border", +DlgFlashScaleFit : "Exact Fit", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link Info", +DlgLnkTargetTab : "Target", + +DlgLnkType : "Link Type", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Link to anchor in the text", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Select an Anchor", +DlgLnkAnchorByName : "By Anchor Name", +DlgLnkAnchorById : "By Element Id", +DlgLnkNoAnchors : "(No anchors available in the document)", +DlgLnkEMail : "E-Mail Address", +DlgLnkEMailSubject : "Message Subject", +DlgLnkEMailBody : "Message Body", +DlgLnkUpload : "Upload", +DlgLnkBtnUpload : "Send it to the Server", + +DlgLnkTarget : "Target", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "New Window (_blank)", +DlgLnkTargetParent : "Parent Window (_parent)", +DlgLnkTargetSelf : "Same Window (_self)", +DlgLnkTargetTop : "Topmost Window (_top)", +DlgLnkTargetFrameName : "Target Frame Name", +DlgLnkPopWinName : "Popup Window Name", +DlgLnkPopWinFeat : "Popup Window Features", +DlgLnkPopResize : "Resizable", +DlgLnkPopLocation : "Location Bar", +DlgLnkPopMenu : "Menu Bar", +DlgLnkPopScroll : "Scroll Bars", +DlgLnkPopStatus : "Status Bar", +DlgLnkPopToolbar : "Toolbar", +DlgLnkPopFullScrn : "Full Screen (IE)", +DlgLnkPopDependent : "Dependent (Netscape)", +DlgLnkPopWidth : "Width", +DlgLnkPopHeight : "Height", +DlgLnkPopLeft : "Left Position", +DlgLnkPopTop : "Top Position", + +DlnLnkMsgNoUrl : "Please type the link URL", +DlnLnkMsgNoEMail : "Please type the e-mail address", +DlnLnkMsgNoAnchor : "Please select an anchor", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", + +// Color Dialog +DlgColorTitle : "Select Colour", +DlgColorBtnClear : "Clear", +DlgColorHighlight : "Highlight", +DlgColorSelected : "Selected", + +// Smiley Dialog +DlgSmileyTitle : "Insert a Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Select Special Character", + +// Table Dialog +DlgTableTitle : "Table Properties", +DlgTableRows : "Rows", +DlgTableColumns : "Columns", +DlgTableBorder : "Border size", +DlgTableAlign : "Alignment", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Left", +DlgTableAlignCenter : "Centre", +DlgTableAlignRight : "Right", +DlgTableWidth : "Width", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "percent", +DlgTableHeight : "Height", +DlgTableCellSpace : "Cell spacing", +DlgTableCellPad : "Cell padding", +DlgTableCaption : "Caption", +DlgTableSummary : "Summary", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Cell Properties", +DlgCellWidth : "Width", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "percent", +DlgCellHeight : "Height", +DlgCellWordWrap : "Word Wrap", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Yes", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Horizontal Alignment", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Left", +DlgCellHorAlignCenter : "Centre", +DlgCellHorAlignRight: "Right", +DlgCellVerAlign : "Vertical Alignment", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Top", +DlgCellVerAlignMiddle : "Middle", +DlgCellVerAlignBottom : "Bottom", +DlgCellVerAlignBaseline : "Baseline", +DlgCellType : "Cell Type", +DlgCellTypeData : "Data", +DlgCellTypeHeader : "Header", +DlgCellRowSpan : "Rows Span", +DlgCellCollSpan : "Columns Span", +DlgCellBackColor : "Background Colour", +DlgCellBorderColor : "Border Colour", +DlgCellBtnSelect : "Select...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", + +// Find Dialog +DlgFindTitle : "Find", +DlgFindFindBtn : "Find", +DlgFindNotFoundMsg : "The specified text was not found.", + +// Replace Dialog +DlgReplaceTitle : "Replace", +DlgReplaceFindLbl : "Find what:", +DlgReplaceReplaceLbl : "Replace with:", +DlgReplaceCaseChk : "Match case", +DlgReplaceReplaceBtn : "Replace", +DlgReplaceReplAllBtn : "Replace All", +DlgReplaceWordChk : "Match whole word", + +// Paste Operations / Dialog +PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).", +PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).", + +PasteAsText : "Paste as Plain Text", +PasteFromWord : "Paste from Word", + +DlgPasteMsg2 : "Please paste inside the following box using the keyboard (Ctrl+V) and hit OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", +DlgPasteIgnoreFont : "Ignore Font Face definitions", +DlgPasteRemoveStyles : "Remove Styles definitions", + +// Color Picker +ColorAutomatic : "Automatic", +ColorMoreColors : "More Colours...", + +// Document Properties +DocProps : "Document Properties", + +// Anchor Dialog +DlgAnchorTitle : "Anchor Properties", +DlgAnchorName : "Anchor Name", +DlgAnchorErrorName : "Please type the anchor name", + +// Speller Pages Dialog +DlgSpellNotInDic : "Not in dictionary", +DlgSpellChangeTo : "Change to", +DlgSpellBtnIgnore : "Ignore", +DlgSpellBtnIgnoreAll : "Ignore All", +DlgSpellBtnReplace : "Replace", +DlgSpellBtnReplaceAll : "Replace All", +DlgSpellBtnUndo : "Undo", +DlgSpellNoSuggestions : "- No suggestions -", +DlgSpellProgress : "Spell check in progress...", +DlgSpellNoMispell : "Spell check complete: No misspellings found", +DlgSpellNoChanges : "Spell check complete: No words changed", +DlgSpellOneChange : "Spell check complete: One word changed", +DlgSpellManyChanges : "Spell check complete: %1 words changed", + +IeSpellDownload : "Spell checker not installed. Do you want to download it now?", + +// Button Dialog +DlgButtonText : "Text (Value)", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Button", +DlgButtonTypeSbm : "Submit", +DlgButtonTypeRst : "Reset", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Name", +DlgCheckboxValue : "Value", +DlgCheckboxSelected : "Selected", + +// Form Dialog +DlgFormName : "Name", +DlgFormAction : "Action", +DlgFormMethod : "Method", + +// Select Field Dialog +DlgSelectName : "Name", +DlgSelectValue : "Value", +DlgSelectSize : "Size", +DlgSelectLines : "lines", +DlgSelectChkMulti : "Allow multiple selections", +DlgSelectOpAvail : "Available Options", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Value", +DlgSelectBtnAdd : "Add", +DlgSelectBtnModify : "Modify", +DlgSelectBtnUp : "Up", +DlgSelectBtnDown : "Down", +DlgSelectBtnSetValue : "Set as selected value", +DlgSelectBtnDelete : "Delete", + +// Textarea Dialog +DlgTextareaName : "Name", +DlgTextareaCols : "Columns", +DlgTextareaRows : "Rows", + +// Text Field Dialog +DlgTextName : "Name", +DlgTextValue : "Value", +DlgTextCharWidth : "Character Width", +DlgTextMaxChars : "Maximum Characters", +DlgTextType : "Type", +DlgTextTypeText : "Text", +DlgTextTypePass : "Password", + +// Hidden Field Dialog +DlgHiddenName : "Name", +DlgHiddenValue : "Value", + +// Bulleted List Dialog +BulletedListProp : "Bulleted List Properties", +NumberedListProp : "Numbered List Properties", +DlgLstStart : "Start", +DlgLstType : "Type", +DlgLstTypeCircle : "Circle", +DlgLstTypeDisc : "Disc", +DlgLstTypeSquare : "Square", +DlgLstTypeNumbers : "Numbers (1, 2, 3)", +DlgLstTypeLCase : "Lowercase Letters (a, b, c)", +DlgLstTypeUCase : "Uppercase Letters (A, B, C)", +DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", +DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "General", +DlgDocBackTab : "Background", +DlgDocColorsTab : "Colours and Margins", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Page Title", +DlgDocLangDir : "Language Direction", +DlgDocLangDirLTR : "Left to Right (LTR)", +DlgDocLangDirRTL : "Right to Left (RTL)", +DlgDocLangCode : "Language Code", +DlgDocCharSet : "Character Set Encoding", +DlgDocCharSetCE : "Central European", +DlgDocCharSetCT : "Chinese Traditional (Big5)", +DlgDocCharSetCR : "Cyrillic", +DlgDocCharSetGR : "Greek", +DlgDocCharSetJP : "Japanese", +DlgDocCharSetKR : "Korean", +DlgDocCharSetTR : "Turkish", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Western European", +DlgDocCharSetOther : "Other Character Set Encoding", + +DlgDocDocType : "Document Type Heading", +DlgDocDocTypeOther : "Other Document Type Heading", +DlgDocIncXHTML : "Include XHTML Declarations", +DlgDocBgColor : "Background Colour", +DlgDocBgImage : "Background Image URL", +DlgDocBgNoScroll : "Nonscrolling Background", +DlgDocCText : "Text", +DlgDocCLink : "Link", +DlgDocCVisited : "Visited Link", +DlgDocCActive : "Active Link", +DlgDocMargins : "Page Margins", +DlgDocMaTop : "Top", +DlgDocMaLeft : "Left", +DlgDocMaRight : "Right", +DlgDocMaBottom : "Bottom", +DlgDocMeIndex : "Document Indexing Keywords (comma separated)", +DlgDocMeDescr : "Document Description", +DlgDocMeAuthor : "Author", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Preview", + +// Templates Dialog +Templates : "Templates", +DlgTemplatesTitle : "Content Templates", +DlgTemplatesSelMsg : "Please select the template to open in the editor
    (the actual contents will be lost):", +DlgTemplatesLoading : "Loading templates list. Please wait...", +DlgTemplatesNoTpl : "(No templates defined)", +DlgTemplatesReplace : "Replace actual contents", + +// About Dialog +DlgAboutAboutTab : "About", +DlgAboutBrowserInfoTab : "Browser Info", +DlgAboutLicenseTab : "License", +DlgAboutVersion : "version", +DlgAboutInfo : "For further information go to", + +// Div Dialog +DlgDivGeneralTab : "General", +DlgDivAdvancedTab : "Advanced", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Inline Style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/en.js b/www/js/FCKeditor/editor/lang/en.js new file mode 100644 index 0000000..d0ccf90 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/en.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * English language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Collapse Toolbar", +ToolbarExpand : "Expand Toolbar", + +// Toolbar Items and Context Menu +Save : "Save", +NewPage : "New Page", +Preview : "Preview", +Cut : "Cut", +Copy : "Copy", +Paste : "Paste", +PasteText : "Paste as plain text", +PasteWord : "Paste from Word", +Print : "Print", +SelectAll : "Select All", +RemoveFormat : "Remove Format", +InsertLinkLbl : "Link", +InsertLink : "Insert/Edit Link", +RemoveLink : "Remove Link", +VisitLink : "Open Link", +Anchor : "Insert/Edit Anchor", +AnchorDelete : "Remove Anchor", +InsertImageLbl : "Image", +InsertImage : "Insert/Edit Image", +InsertFlashLbl : "Flash", +InsertFlash : "Insert/Edit Flash", +InsertTableLbl : "Table", +InsertTable : "Insert/Edit Table", +InsertLineLbl : "Line", +InsertLine : "Insert Horizontal Line", +InsertSpecialCharLbl: "Special Character", +InsertSpecialChar : "Insert Special Character", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Insert Smiley", +About : "About FCKeditor", +Bold : "Bold", +Italic : "Italic", +Underline : "Underline", +StrikeThrough : "Strike Through", +Subscript : "Subscript", +Superscript : "Superscript", +LeftJustify : "Left Justify", +CenterJustify : "Center Justify", +RightJustify : "Right Justify", +BlockJustify : "Block Justify", +DecreaseIndent : "Decrease Indent", +IncreaseIndent : "Increase Indent", +Blockquote : "Blockquote", +CreateDiv : "Create Div Container", +EditDiv : "Edit Div Container", +DeleteDiv : "Remove Div Container", +Undo : "Undo", +Redo : "Redo", +NumberedListLbl : "Numbered List", +NumberedList : "Insert/Remove Numbered List", +BulletedListLbl : "Bulleted List", +BulletedList : "Insert/Remove Bulleted List", +ShowTableBorders : "Show Table Borders", +ShowDetails : "Show Details", +Style : "Style", +FontFormat : "Format", +Font : "Font", +FontSize : "Size", +TextColor : "Text Color", +BGColor : "Background Color", +Source : "Source", +Find : "Find", +Replace : "Replace", +SpellCheck : "Check Spelling", +UniversalKeyboard : "Universal Keyboard", +PageBreakLbl : "Page Break", +PageBreak : "Insert Page Break", + +Form : "Form", +Checkbox : "Checkbox", +RadioButton : "Radio Button", +TextField : "Text Field", +Textarea : "Textarea", +HiddenField : "Hidden Field", +Button : "Button", +SelectionField : "Selection Field", +ImageButton : "Image Button", + +FitWindow : "Maximize the editor size", +ShowBlocks : "Show Blocks", + +// Context Menu +EditLink : "Edit Link", +CellCM : "Cell", +RowCM : "Row", +ColumnCM : "Column", +InsertRowAfter : "Insert Row After", +InsertRowBefore : "Insert Row Before", +DeleteRows : "Delete Rows", +InsertColumnAfter : "Insert Column After", +InsertColumnBefore : "Insert Column Before", +DeleteColumns : "Delete Columns", +InsertCellAfter : "Insert Cell After", +InsertCellBefore : "Insert Cell Before", +DeleteCells : "Delete Cells", +MergeCells : "Merge Cells", +MergeRight : "Merge Right", +MergeDown : "Merge Down", +HorizontalSplitCell : "Split Cell Horizontally", +VerticalSplitCell : "Split Cell Vertically", +TableDelete : "Delete Table", +CellProperties : "Cell Properties", +TableProperties : "Table Properties", +ImageProperties : "Image Properties", +FlashProperties : "Flash Properties", + +AnchorProp : "Anchor Properties", +ButtonProp : "Button Properties", +CheckboxProp : "Checkbox Properties", +HiddenFieldProp : "Hidden Field Properties", +RadioButtonProp : "Radio Button Properties", +ImageButtonProp : "Image Button Properties", +TextFieldProp : "Text Field Properties", +SelectionFieldProp : "Selection Field Properties", +TextareaProp : "Textarea Properties", +FormProp : "Form Properties", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Processing XHTML. Please wait...", +Done : "Done", +PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?", +NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?", +UnknownToolbarItem : "Unknown toolbar item \"%1\"", +UnknownCommand : "Unknown command name \"%1\"", +NotImplemented : "Command not implemented", +UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Cancel", +DlgBtnClose : "Close", +DlgBtnBrowseServer : "Browse Server", +DlgAdvancedTag : "Advanced", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Please insert the URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Language Direction", +DlgGenLangDirLtr : "Left to Right (LTR)", +DlgGenLangDirRtl : "Right to Left (RTL)", +DlgGenLangCode : "Language Code", +DlgGenAccessKey : "Access Key", +DlgGenName : "Name", +DlgGenTabIndex : "Tab Index", +DlgGenLongDescr : "Long Description URL", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "Advisory Title", +DlgGenContType : "Advisory Content Type", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Image Properties", +DlgImgInfoTab : "Image Info", +DlgImgBtnUpload : "Send it to the Server", +DlgImgURL : "URL", +DlgImgUpload : "Upload", +DlgImgAlt : "Alternative Text", +DlgImgWidth : "Width", +DlgImgHeight : "Height", +DlgImgLockRatio : "Lock Ratio", +DlgBtnResetSize : "Reset Size", +DlgImgBorder : "Border", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Align", +DlgImgAlignLeft : "Left", +DlgImgAlignAbsBottom: "Abs Bottom", +DlgImgAlignAbsMiddle: "Abs Middle", +DlgImgAlignBaseline : "Baseline", +DlgImgAlignBottom : "Bottom", +DlgImgAlignMiddle : "Middle", +DlgImgAlignRight : "Right", +DlgImgAlignTextTop : "Text Top", +DlgImgAlignTop : "Top", +DlgImgPreview : "Preview", +DlgImgAlertUrl : "Please type the image URL", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash Properties", +DlgFlashChkPlay : "Auto Play", +DlgFlashChkLoop : "Loop", +DlgFlashChkMenu : "Enable Flash Menu", +DlgFlashScale : "Scale", +DlgFlashScaleAll : "Show all", +DlgFlashScaleNoBorder : "No Border", +DlgFlashScaleFit : "Exact Fit", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link Info", +DlgLnkTargetTab : "Target", + +DlgLnkType : "Link Type", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Link to anchor in the text", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Select an Anchor", +DlgLnkAnchorByName : "By Anchor Name", +DlgLnkAnchorById : "By Element Id", +DlgLnkNoAnchors : "(No anchors available in the document)", +DlgLnkEMail : "E-Mail Address", +DlgLnkEMailSubject : "Message Subject", +DlgLnkEMailBody : "Message Body", +DlgLnkUpload : "Upload", +DlgLnkBtnUpload : "Send it to the Server", + +DlgLnkTarget : "Target", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "New Window (_blank)", +DlgLnkTargetParent : "Parent Window (_parent)", +DlgLnkTargetSelf : "Same Window (_self)", +DlgLnkTargetTop : "Topmost Window (_top)", +DlgLnkTargetFrameName : "Target Frame Name", +DlgLnkPopWinName : "Popup Window Name", +DlgLnkPopWinFeat : "Popup Window Features", +DlgLnkPopResize : "Resizable", +DlgLnkPopLocation : "Location Bar", +DlgLnkPopMenu : "Menu Bar", +DlgLnkPopScroll : "Scroll Bars", +DlgLnkPopStatus : "Status Bar", +DlgLnkPopToolbar : "Toolbar", +DlgLnkPopFullScrn : "Full Screen (IE)", +DlgLnkPopDependent : "Dependent (Netscape)", +DlgLnkPopWidth : "Width", +DlgLnkPopHeight : "Height", +DlgLnkPopLeft : "Left Position", +DlgLnkPopTop : "Top Position", + +DlnLnkMsgNoUrl : "Please type the link URL", +DlnLnkMsgNoEMail : "Please type the e-mail address", +DlnLnkMsgNoAnchor : "Please select an anchor", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", + +// Color Dialog +DlgColorTitle : "Select Color", +DlgColorBtnClear : "Clear", +DlgColorHighlight : "Highlight", +DlgColorSelected : "Selected", + +// Smiley Dialog +DlgSmileyTitle : "Insert a Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Select Special Character", + +// Table Dialog +DlgTableTitle : "Table Properties", +DlgTableRows : "Rows", +DlgTableColumns : "Columns", +DlgTableBorder : "Border size", +DlgTableAlign : "Alignment", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Left", +DlgTableAlignCenter : "Center", +DlgTableAlignRight : "Right", +DlgTableWidth : "Width", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "percent", +DlgTableHeight : "Height", +DlgTableCellSpace : "Cell spacing", +DlgTableCellPad : "Cell padding", +DlgTableCaption : "Caption", +DlgTableSummary : "Summary", +DlgTableHeaders : "Headers", +DlgTableHeadersNone : "None", +DlgTableHeadersColumn : "First column", +DlgTableHeadersRow : "First Row", +DlgTableHeadersBoth : "Both", + +// Table Cell Dialog +DlgCellTitle : "Cell Properties", +DlgCellWidth : "Width", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "percent", +DlgCellHeight : "Height", +DlgCellWordWrap : "Word Wrap", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Yes", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Horizontal Alignment", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Left", +DlgCellHorAlignCenter : "Center", +DlgCellHorAlignRight: "Right", +DlgCellVerAlign : "Vertical Alignment", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Top", +DlgCellVerAlignMiddle : "Middle", +DlgCellVerAlignBottom : "Bottom", +DlgCellVerAlignBaseline : "Baseline", +DlgCellType : "Cell Type", +DlgCellTypeData : "Data", +DlgCellTypeHeader : "Header", +DlgCellRowSpan : "Rows Span", +DlgCellCollSpan : "Columns Span", +DlgCellBackColor : "Background Color", +DlgCellBorderColor : "Border Color", +DlgCellBtnSelect : "Select...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", + +// Find Dialog +DlgFindTitle : "Find", +DlgFindFindBtn : "Find", +DlgFindNotFoundMsg : "The specified text was not found.", + +// Replace Dialog +DlgReplaceTitle : "Replace", +DlgReplaceFindLbl : "Find what:", +DlgReplaceReplaceLbl : "Replace with:", +DlgReplaceCaseChk : "Match case", +DlgReplaceReplaceBtn : "Replace", +DlgReplaceReplAllBtn : "Replace All", +DlgReplaceWordChk : "Match whole word", + +// Paste Operations / Dialog +PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).", +PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).", + +PasteAsText : "Paste as Plain Text", +PasteFromWord : "Paste from Word", + +DlgPasteMsg2 : "Please paste inside the following box using the keyboard (Ctrl+V) and hit OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", +DlgPasteIgnoreFont : "Ignore Font Face definitions", +DlgPasteRemoveStyles : "Remove Styles definitions", + +// Color Picker +ColorAutomatic : "Automatic", +ColorMoreColors : "More Colors...", + +// Document Properties +DocProps : "Document Properties", + +// Anchor Dialog +DlgAnchorTitle : "Anchor Properties", +DlgAnchorName : "Anchor Name", +DlgAnchorErrorName : "Please type the anchor name", + +// Speller Pages Dialog +DlgSpellNotInDic : "Not in dictionary", +DlgSpellChangeTo : "Change to", +DlgSpellBtnIgnore : "Ignore", +DlgSpellBtnIgnoreAll : "Ignore All", +DlgSpellBtnReplace : "Replace", +DlgSpellBtnReplaceAll : "Replace All", +DlgSpellBtnUndo : "Undo", +DlgSpellNoSuggestions : "- No suggestions -", +DlgSpellProgress : "Spell check in progress...", +DlgSpellNoMispell : "Spell check complete: No misspellings found", +DlgSpellNoChanges : "Spell check complete: No words changed", +DlgSpellOneChange : "Spell check complete: One word changed", +DlgSpellManyChanges : "Spell check complete: %1 words changed", + +IeSpellDownload : "Spell checker not installed. Do you want to download it now?", + +// Button Dialog +DlgButtonText : "Text (Value)", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Button", +DlgButtonTypeSbm : "Submit", +DlgButtonTypeRst : "Reset", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Name", +DlgCheckboxValue : "Value", +DlgCheckboxSelected : "Selected", + +// Form Dialog +DlgFormName : "Name", +DlgFormAction : "Action", +DlgFormMethod : "Method", + +// Select Field Dialog +DlgSelectName : "Name", +DlgSelectValue : "Value", +DlgSelectSize : "Size", +DlgSelectLines : "lines", +DlgSelectChkMulti : "Allow multiple selections", +DlgSelectOpAvail : "Available Options", +DlgSelectOpText : "Text", +DlgSelectOpValue : "Value", +DlgSelectBtnAdd : "Add", +DlgSelectBtnModify : "Modify", +DlgSelectBtnUp : "Up", +DlgSelectBtnDown : "Down", +DlgSelectBtnSetValue : "Set as selected value", +DlgSelectBtnDelete : "Delete", + +// Textarea Dialog +DlgTextareaName : "Name", +DlgTextareaCols : "Columns", +DlgTextareaRows : "Rows", + +// Text Field Dialog +DlgTextName : "Name", +DlgTextValue : "Value", +DlgTextCharWidth : "Character Width", +DlgTextMaxChars : "Maximum Characters", +DlgTextType : "Type", +DlgTextTypeText : "Text", +DlgTextTypePass : "Password", + +// Hidden Field Dialog +DlgHiddenName : "Name", +DlgHiddenValue : "Value", + +// Bulleted List Dialog +BulletedListProp : "Bulleted List Properties", +NumberedListProp : "Numbered List Properties", +DlgLstStart : "Start", +DlgLstType : "Type", +DlgLstTypeCircle : "Circle", +DlgLstTypeDisc : "Disc", +DlgLstTypeSquare : "Square", +DlgLstTypeNumbers : "Numbers (1, 2, 3)", +DlgLstTypeLCase : "Lowercase Letters (a, b, c)", +DlgLstTypeUCase : "Uppercase Letters (A, B, C)", +DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", +DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "General", +DlgDocBackTab : "Background", +DlgDocColorsTab : "Colors and Margins", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Page Title", +DlgDocLangDir : "Language Direction", +DlgDocLangDirLTR : "Left to Right (LTR)", +DlgDocLangDirRTL : "Right to Left (RTL)", +DlgDocLangCode : "Language Code", +DlgDocCharSet : "Character Set Encoding", +DlgDocCharSetCE : "Central European", +DlgDocCharSetCT : "Chinese Traditional (Big5)", +DlgDocCharSetCR : "Cyrillic", +DlgDocCharSetGR : "Greek", +DlgDocCharSetJP : "Japanese", +DlgDocCharSetKR : "Korean", +DlgDocCharSetTR : "Turkish", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Western European", +DlgDocCharSetOther : "Other Character Set Encoding", + +DlgDocDocType : "Document Type Heading", +DlgDocDocTypeOther : "Other Document Type Heading", +DlgDocIncXHTML : "Include XHTML Declarations", +DlgDocBgColor : "Background Color", +DlgDocBgImage : "Background Image URL", +DlgDocBgNoScroll : "Nonscrolling Background", +DlgDocCText : "Text", +DlgDocCLink : "Link", +DlgDocCVisited : "Visited Link", +DlgDocCActive : "Active Link", +DlgDocMargins : "Page Margins", +DlgDocMaTop : "Top", +DlgDocMaLeft : "Left", +DlgDocMaRight : "Right", +DlgDocMaBottom : "Bottom", +DlgDocMeIndex : "Document Indexing Keywords (comma separated)", +DlgDocMeDescr : "Document Description", +DlgDocMeAuthor : "Author", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Preview", + +// Templates Dialog +Templates : "Templates", +DlgTemplatesTitle : "Content Templates", +DlgTemplatesSelMsg : "Please select the template to open in the editor
    (the actual contents will be lost):", +DlgTemplatesLoading : "Loading templates list. Please wait...", +DlgTemplatesNoTpl : "(No templates defined)", +DlgTemplatesReplace : "Replace actual contents", + +// About Dialog +DlgAboutAboutTab : "About", +DlgAboutBrowserInfoTab : "Browser Info", +DlgAboutLicenseTab : "License", +DlgAboutVersion : "version", +DlgAboutInfo : "For further information go to", + +// Div Dialog +DlgDivGeneralTab : "General", +DlgDivAdvancedTab : "Advanced", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Inline Style", + +ScaytTitle : "SCAYT", +ScaytTitleOptions : "Options", +ScaytTitleLangs : "Languages", +ScaytTitleAbout : "About" +}; diff --git a/www/js/FCKeditor/editor/lang/eo.js b/www/js/FCKeditor/editor/lang/eo.js new file mode 100644 index 0000000..9334981 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/eo.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Esperanto language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "KaÅi Ilobreton", +ToolbarExpand : "Vidigi Ilojn", + +// Toolbar Items and Context Menu +Save : "Sekurigi", +NewPage : "Nova PaÄo", +Preview : "Vidigi Aspekton", +Cut : "Eltondi", +Copy : "Kopii", +Paste : "Interglui", +PasteText : "Interglui kiel Tekston", +PasteWord : "Interglui el Word", +Print : "Presi", +SelectAll : "Elekti ĉion", +RemoveFormat : "Forigi Formaton", +InsertLinkLbl : "Ligilo", +InsertLink : "Enmeti/ÅœanÄi Ligilon", +RemoveLink : "Forigi Ligilon", +VisitLink : "Open Link", //MISSING +Anchor : "Enmeti/ÅœanÄi Ankron", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "Bildo", +InsertImage : "Enmeti/ÅœanÄi Bildon", +InsertFlashLbl : "Flash", //MISSING +InsertFlash : "Insert/Edit Flash", //MISSING +InsertTableLbl : "Tabelo", +InsertTable : "Enmeti/ÅœanÄi Tabelon", +InsertLineLbl : "Horizonta Linio", +InsertLine : "Enmeti Horizonta Linio", +InsertSpecialCharLbl: "Speciala Signo", +InsertSpecialChar : "Enmeti Specialan Signon", +InsertSmileyLbl : "Mienvinjeto", +InsertSmiley : "Enmeti Mienvinjeton", +About : "Pri FCKeditor", +Bold : "Grasa", +Italic : "Kursiva", +Underline : "Substreko", +StrikeThrough : "Trastreko", +Subscript : "Subskribo", +Superscript : "Superskribo", +LeftJustify : "Maldekstrigi", +CenterJustify : "Centrigi", +RightJustify : "Dekstrigi", +BlockJustify : "Äœisrandigi AmbaÅ­flanke", +DecreaseIndent : "Malpligrandigi KrommarÄenon", +IncreaseIndent : "Pligrandigi KrommarÄenon", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Malfari", +Redo : "Refari", +NumberedListLbl : "Numera Listo", +NumberedList : "Enmeti/Forigi Numeran Liston", +BulletedListLbl : "Bula Listo", +BulletedList : "Enmeti/Forigi Bulan Liston", +ShowTableBorders : "Vidigi Borderojn de Tabelo", +ShowDetails : "Vidigi Detalojn", +Style : "Stilo", +FontFormat : "Formato", +Font : "Tiparo", +FontSize : "Grando", +TextColor : "Teksta Koloro", +BGColor : "Fona Koloro", +Source : "Fonto", +Find : "Serĉi", +Replace : "AnstataÅ­igi", +SpellCheck : "Literumada Kontrolilo", +UniversalKeyboard : "Universala Klavaro", +PageBreakLbl : "Page Break", //MISSING +PageBreak : "Insert Page Break", //MISSING + +Form : "Formularo", +Checkbox : "Markobutono", +RadioButton : "Radiobutono", +TextField : "Teksta kampo", +Textarea : "Teksta Areo", +HiddenField : "KaÅita Kampo", +Button : "Butono", +SelectionField : "Elekta Kampo", +ImageButton : "Bildbutono", + +FitWindow : "Maximize the editor size", //MISSING +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Modifier Ligilon", +CellCM : "Cell", //MISSING +RowCM : "Row", //MISSING +ColumnCM : "Column", //MISSING +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "Forigi Liniojn", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "Forigi Kolumnojn", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "Forigi Ĉelojn", +MergeCells : "Kunfandi Ĉelojn", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "Delete Table", //MISSING +CellProperties : "Atributoj de Ĉelo", +TableProperties : "Atributoj de Tabelo", +ImageProperties : "Atributoj de Bildo", +FlashProperties : "Flash Properties", //MISSING + +AnchorProp : "Ankraj Atributoj", +ButtonProp : "Butonaj Atributoj", +CheckboxProp : "Markobutonaj Atributoj", +HiddenFieldProp : "Atributoj de KaÅita Kampo", +RadioButtonProp : "Radiobutonaj Atributoj", +ImageButtonProp : "Bildbutonaj Atributoj", +TextFieldProp : "Atributoj de Teksta Kampo", +SelectionFieldProp : "Atributoj de Elekta Kampo", +TextareaProp : "Atributoj de Teksta Areo", +FormProp : "Formularaj Atributoj", + +FontFormats : "Normala;Formatita;Adreso;Titolo 1;Titolo 2;Titolo 3;Titolo 4;Titolo 5;Titolo 6;Paragrafo (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Traktado de XHTML. Bonvolu pacienci...", +Done : "Finita", +PasteWordConfirm : "La algluota teksto Åajnas esti Word-devena. Ĉu vi volas purigi Äin antaÅ­ ol interglui?", +NotCompatiblePaste : "Tiu ĉi komando bezonas almenaÅ­ Internet Explorer 5.5. Ĉu vi volas daÅ­rigi sen purigado?", +UnknownToolbarItem : "Ilobretero nekonata \"%1\"", +UnknownCommand : "Komandonomo nekonata \"%1\"", +NotImplemented : "Komando ne ankoraÅ­ realigita", +UnknownToolbarSet : "La ilobreto \"%1\" ne ekzistas", +NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING +DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "Akcepti", +DlgBtnCancel : "Rezigni", +DlgBtnClose : "Fermi", +DlgBtnBrowseServer : "Foliumi en la Servilo", +DlgAdvancedTag : "Speciala", +DlgOpOther : "", +DlgInfoTab : "Info", //MISSING +DlgAlertUrl : "Please insert the URL", //MISSING + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Skribdirekto", +DlgGenLangDirLtr : "De maldekstro dekstren (LTR)", +DlgGenLangDirRtl : "De dekstro maldekstren (RTL)", +DlgGenLangCode : "Lingva Kodo", +DlgGenAccessKey : "Fulmoklavo", +DlgGenName : "Nomo", +DlgGenTabIndex : "Taba Ordo", +DlgGenLongDescr : "URL de Longa Priskribo", +DlgGenClass : "Klasoj de Stilfolioj", +DlgGenTitle : "Indika Titolo", +DlgGenContType : "Indika Enhavotipo", +DlgGenLinkCharset : "Signaro de la Ligita Rimedo", +DlgGenStyle : "Stilo", + +// Image Dialog +DlgImgTitle : "Atributoj de Bildo", +DlgImgInfoTab : "Informoj pri Bildo", +DlgImgBtnUpload : "Sendu al Servilo", +DlgImgURL : "URL", +DlgImgUpload : "AlÅuti", +DlgImgAlt : "AnstataÅ­iga Teksto", +DlgImgWidth : "LarÄo", +DlgImgHeight : "Alto", +DlgImgLockRatio : "Konservi Proporcion", +DlgBtnResetSize : "Origina Grando", +DlgImgBorder : "Bordero", +DlgImgHSpace : "HSpaco", +DlgImgVSpace : "VSpaco", +DlgImgAlign : "Äœisrandigo", +DlgImgAlignLeft : "Maldekstre", +DlgImgAlignAbsBottom: "Abs Malsupre", +DlgImgAlignAbsMiddle: "Abs Centre", +DlgImgAlignBaseline : "Je Malsupro de Teksto", +DlgImgAlignBottom : "Malsupre", +DlgImgAlignMiddle : "Centre", +DlgImgAlignRight : "Dekstre", +DlgImgAlignTextTop : "Je Supro de Teksto", +DlgImgAlignTop : "Supre", +DlgImgPreview : "Vidigi Aspekton", +DlgImgAlertUrl : "Bonvolu tajpi la URL de la bildo", +DlgImgLinkTab : "Link", //MISSING + +// Flash Dialog +DlgFlashTitle : "Flash Properties", //MISSING +DlgFlashChkPlay : "Auto Play", //MISSING +DlgFlashChkLoop : "Loop", //MISSING +DlgFlashChkMenu : "Enable Flash Menu", //MISSING +DlgFlashScale : "Scale", //MISSING +DlgFlashScaleAll : "Show all", //MISSING +DlgFlashScaleNoBorder : "No Border", //MISSING +DlgFlashScaleFit : "Exact Fit", //MISSING + +// Link Dialog +DlgLnkWindowTitle : "Ligilo", +DlgLnkInfoTab : "Informoj pri la Ligilo", +DlgLnkTargetTab : "Celo", + +DlgLnkType : "Tipo de Ligilo", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Ankri en tiu ĉi paÄo", +DlgLnkTypeEMail : "RetpoÅto", +DlgLnkProto : "Protokolo", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Elekti Ankron", +DlgLnkAnchorByName : "Per Ankronomo", +DlgLnkAnchorById : "Per Elementidentigilo", +DlgLnkNoAnchors : "", +DlgLnkEMail : "Retadreso", +DlgLnkEMailSubject : "Temlinio", +DlgLnkEMailBody : "MesaÄa korpo", +DlgLnkUpload : "AlÅuti", +DlgLnkBtnUpload : "Sendi al Servilo", + +DlgLnkTarget : "Celo", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "<Åprucfenestro>", +DlgLnkTargetBlank : "Nova Fenestro (_blank)", +DlgLnkTargetParent : "Gepatra Fenestro (_parent)", +DlgLnkTargetSelf : "Sama Fenestro (_self)", +DlgLnkTargetTop : "Plej Supra Fenestro (_top)", +DlgLnkTargetFrameName : "Nomo de Kadro", +DlgLnkPopWinName : "Nomo de Åœprucfenestro", +DlgLnkPopWinFeat : "Atributoj de la Åœprucfenestro", +DlgLnkPopResize : "Grando ÅœanÄebla", +DlgLnkPopLocation : "Adresobreto", +DlgLnkPopMenu : "Menubreto", +DlgLnkPopScroll : "Rulumlisteloj", +DlgLnkPopStatus : "Statobreto", +DlgLnkPopToolbar : "Ilobreto", +DlgLnkPopFullScrn : "Tutekrane (IE)", +DlgLnkPopDependent : "Dependa (Netscape)", +DlgLnkPopWidth : "LarÄo", +DlgLnkPopHeight : "Alto", +DlgLnkPopLeft : "Pozicio de Maldekstro", +DlgLnkPopTop : "Pozicio de Supro", + +DlnLnkMsgNoUrl : "Bonvolu entajpi la URL-on", +DlnLnkMsgNoEMail : "Bonvolu entajpi la retadreson", +DlnLnkMsgNoAnchor : "Bonvolu elekti ankron", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING + +// Color Dialog +DlgColorTitle : "Elekti", +DlgColorBtnClear : "Forigi", +DlgColorHighlight : "Emfazi", +DlgColorSelected : "Elektita", + +// Smiley Dialog +DlgSmileyTitle : "Enmeti Mienvinjeton", + +// Special Character Dialog +DlgSpecialCharTitle : "Enmeti Specialan Signon", + +// Table Dialog +DlgTableTitle : "Atributoj de Tabelo", +DlgTableRows : "Linioj", +DlgTableColumns : "Kolumnoj", +DlgTableBorder : "Bordero", +DlgTableAlign : "Äœisrandigo", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Maldekstre", +DlgTableAlignCenter : "Centre", +DlgTableAlignRight : "Dekstre", +DlgTableWidth : "LarÄo", +DlgTableWidthPx : "Bitbilderoj", +DlgTableWidthPc : "elcentoj", +DlgTableHeight : "Alto", +DlgTableCellSpace : "Interspacigo de Ĉeloj", +DlgTableCellPad : "ĈirkaÅ­enhava Plenigado", +DlgTableCaption : "Titolo", +DlgTableSummary : "Summary", //MISSING +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Atributoj de Celo", +DlgCellWidth : "LarÄo", +DlgCellWidthPx : "bitbilderoj", +DlgCellWidthPc : "elcentoj", +DlgCellHeight : "Alto", +DlgCellWordWrap : "Linifaldo", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Jes", +DlgCellWordWrapNo : "Ne", +DlgCellHorAlign : "Horizonta Äœisrandigo", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Maldekstre", +DlgCellHorAlignCenter : "Centre", +DlgCellHorAlignRight: "Dekstre", +DlgCellVerAlign : "Vertikala Äœisrandigo", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Supre", +DlgCellVerAlignMiddle : "Centre", +DlgCellVerAlignBottom : "Malsupre", +DlgCellVerAlignBaseline : "Je Malsupro de Teksto", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Linioj Kunfanditaj", +DlgCellCollSpan : "Kolumnoj Kunfanditaj", +DlgCellBackColor : "Fono", +DlgCellBorderColor : "Bordero", +DlgCellBtnSelect : "Elekti...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "Serĉi", +DlgFindFindBtn : "Serĉi", +DlgFindNotFoundMsg : "La celteksto ne estas trovita.", + +// Replace Dialog +DlgReplaceTitle : "AnstataÅ­igi", +DlgReplaceFindLbl : "Serĉi:", +DlgReplaceReplaceLbl : "AnstataÅ­igi per:", +DlgReplaceCaseChk : "Kongruigi Usklecon", +DlgReplaceReplaceBtn : "AnstataÅ­igi", +DlgReplaceReplAllBtn : "AnstataÅ­igi Ĉiun", +DlgReplaceWordChk : "Tuta Vorto", + +// Paste Operations / Dialog +PasteErrorCut : "La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras eltondajn operaciojn. Bonvolu uzi la klavaron por tio (ctrl-X).", +PasteErrorCopy : "La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras kopiajn operaciojn. Bonvolu uzi la klavaron por tio (ctrl-C).", + +PasteAsText : "Interglui kiel Tekston", +PasteFromWord : "Interglui el Word", + +DlgPasteMsg2 : "Please paste inside the following box using the keyboard (Ctrl+V) and hit OK.", //MISSING +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "Ignore Font Face definitions", //MISSING +DlgPasteRemoveStyles : "Remove Styles definitions", //MISSING + +// Color Picker +ColorAutomatic : "AÅ­tomata", +ColorMoreColors : "Pli da Koloroj...", + +// Document Properties +DocProps : "Dokumentaj Atributoj", + +// Anchor Dialog +DlgAnchorTitle : "Ankraj Atributoj", +DlgAnchorName : "Ankra Nomo", +DlgAnchorErrorName : "Bv tajpi la ankran nomon", + +// Speller Pages Dialog +DlgSpellNotInDic : "Ne trovita en la vortaro", +DlgSpellChangeTo : "ÅœanÄi al", +DlgSpellBtnIgnore : "Malatenti", +DlgSpellBtnIgnoreAll : "Malatenti Ĉiun", +DlgSpellBtnReplace : "AnstataÅ­igi", +DlgSpellBtnReplaceAll : "AnstataÅ­igi Ĉiun", +DlgSpellBtnUndo : "Malfari", +DlgSpellNoSuggestions : "- Neniu propono -", +DlgSpellProgress : "Literumkontrolado daÅ­ras...", +DlgSpellNoMispell : "Literumkontrolado finita: neniu fuÅo trovita", +DlgSpellNoChanges : "Literumkontrolado finita: neniu vorto ÅanÄita", +DlgSpellOneChange : "Literumkontrolado finita: unu vorto ÅanÄita", +DlgSpellManyChanges : "Literumkontrolado finita: %1 vortoj ÅanÄitaj", + +IeSpellDownload : "Literumada Kontrolilo ne instalita. Ĉu vi volas elÅuti Äin nun?", + +// Button Dialog +DlgButtonText : "Teksto (Valoro)", +DlgButtonType : "Tipo", +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nomo", +DlgCheckboxValue : "Valoro", +DlgCheckboxSelected : "Elektita", + +// Form Dialog +DlgFormName : "Nomo", +DlgFormAction : "Ago", +DlgFormMethod : "Metodo", + +// Select Field Dialog +DlgSelectName : "Nomo", +DlgSelectValue : "Valoro", +DlgSelectSize : "Grando", +DlgSelectLines : "Linioj", +DlgSelectChkMulti : "Permesi Plurajn Elektojn", +DlgSelectOpAvail : "Elektoj Disponeblaj", +DlgSelectOpText : "Teksto", +DlgSelectOpValue : "Valoro", +DlgSelectBtnAdd : "Aldoni", +DlgSelectBtnModify : "Modifi", +DlgSelectBtnUp : "Supren", +DlgSelectBtnDown : "Malsupren", +DlgSelectBtnSetValue : "Agordi kiel Elektitan Valoron", +DlgSelectBtnDelete : "Forigi", + +// Textarea Dialog +DlgTextareaName : "Nomo", +DlgTextareaCols : "Kolumnoj", +DlgTextareaRows : "Vicoj", + +// Text Field Dialog +DlgTextName : "Nomo", +DlgTextValue : "Valoro", +DlgTextCharWidth : "SignolarÄo", +DlgTextMaxChars : "Maksimuma Nombro da Signoj", +DlgTextType : "Tipo", +DlgTextTypeText : "Teksto", +DlgTextTypePass : "Pasvorto", + +// Hidden Field Dialog +DlgHiddenName : "Nomo", +DlgHiddenValue : "Valoro", + +// Bulleted List Dialog +BulletedListProp : "Atributoj de Bula Listo", +NumberedListProp : "Atributoj de Numera Listo", +DlgLstStart : "Start", //MISSING +DlgLstType : "Tipo", +DlgLstTypeCircle : "Cirklo", +DlgLstTypeDisc : "Disc", //MISSING +DlgLstTypeSquare : "Kvadrato", +DlgLstTypeNumbers : "Ciferoj (1, 2, 3)", +DlgLstTypeLCase : "Minusklaj Literoj (a, b, c)", +DlgLstTypeUCase : "Majusklaj Literoj (A, B, C)", +DlgLstTypeSRoman : "Malgrandaj Romanaj Ciferoj (i, ii, iii)", +DlgLstTypeLRoman : "Grandaj Romanaj Ciferoj (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Äœeneralaĵoj", +DlgDocBackTab : "Fono", +DlgDocColorsTab : "Koloroj kaj MarÄenoj", +DlgDocMetaTab : "Metadatumoj", + +DlgDocPageTitle : "PaÄotitolo", +DlgDocLangDir : "Skribdirekto de la Lingvo", +DlgDocLangDirLTR : "De maldekstro dekstren (LTR)", +DlgDocLangDirRTL : "De dekstro maldekstren (LTR)", +DlgDocLangCode : "Lingvokodo", +DlgDocCharSet : "Signara Kodo", +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "Alia Signara Kodo", + +DlgDocDocType : "Dokumenta Tipo", +DlgDocDocTypeOther : "Alia Dokumenta Tipo", +DlgDocIncXHTML : "Inkluzivi XHTML Deklaroj", +DlgDocBgColor : "Fona Koloro", +DlgDocBgImage : "URL de Fona Bildo", +DlgDocBgNoScroll : "Neruluma Fono", +DlgDocCText : "Teksto", +DlgDocCLink : "Ligilo", +DlgDocCVisited : "Vizitita Ligilo", +DlgDocCActive : "Aktiva Ligilo", +DlgDocMargins : "PaÄaj MarÄenoj", +DlgDocMaTop : "Supra", +DlgDocMaLeft : "Maldekstra", +DlgDocMaRight : "Dekstra", +DlgDocMaBottom : "Malsupra", +DlgDocMeIndex : "Åœlosilvortoj de la Dokumento (apartigita de komoj)", +DlgDocMeDescr : "Dokumenta Priskribo", +DlgDocMeAuthor : "Verkinto", +DlgDocMeCopy : "Kopirajto", +DlgDocPreview : "Aspekto", + +// Templates Dialog +Templates : "Templates", //MISSING +DlgTemplatesTitle : "Content Templates", //MISSING +DlgTemplatesSelMsg : "Please select the template to open in the editor
    (the actual contents will be lost):", //MISSING +DlgTemplatesLoading : "Loading templates list. Please wait...", //MISSING +DlgTemplatesNoTpl : "(No templates defined)", //MISSING +DlgTemplatesReplace : "Replace actual contents", //MISSING + +// About Dialog +DlgAboutAboutTab : "Pri", +DlgAboutBrowserInfoTab : "Informoj pri TTT-legilo", +DlgAboutLicenseTab : "License", //MISSING +DlgAboutVersion : "versio", +DlgAboutInfo : "Por pli da informoj, vizitu", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/es.js b/www/js/FCKeditor/editor/lang/es.js new file mode 100644 index 0000000..171e7bc --- /dev/null +++ b/www/js/FCKeditor/editor/lang/es.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Spanish language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Contraer Barra", +ToolbarExpand : "Expandir Barra", + +// Toolbar Items and Context Menu +Save : "Guardar", +NewPage : "Nueva Página", +Preview : "Vista Previa", +Cut : "Cortar", +Copy : "Copiar", +Paste : "Pegar", +PasteText : "Pegar como texto plano", +PasteWord : "Pegar desde Word", +Print : "Imprimir", +SelectAll : "Seleccionar Todo", +RemoveFormat : "Eliminar Formato", +InsertLinkLbl : "Vínculo", +InsertLink : "Insertar/Editar Vínculo", +RemoveLink : "Eliminar Vínculo", +VisitLink : "Abrir enlace", +Anchor : "Referencia", +AnchorDelete : "Eliminar Referencia", +InsertImageLbl : "Imagen", +InsertImage : "Insertar/Editar Imagen", +InsertFlashLbl : "Flash", +InsertFlash : "Insertar/Editar Flash", +InsertTableLbl : "Tabla", +InsertTable : "Insertar/Editar Tabla", +InsertLineLbl : "Línea", +InsertLine : "Insertar Línea Horizontal", +InsertSpecialCharLbl: "Caracter Especial", +InsertSpecialChar : "Insertar Caracter Especial", +InsertSmileyLbl : "Emoticons", +InsertSmiley : "Insertar Emoticons", +About : "Acerca de FCKeditor", +Bold : "Negrita", +Italic : "Cursiva", +Underline : "Subrayado", +StrikeThrough : "Tachado", +Subscript : "Subíndice", +Superscript : "Superíndice", +LeftJustify : "Alinear a Izquierda", +CenterJustify : "Centrar", +RightJustify : "Alinear a Derecha", +BlockJustify : "Justificado", +DecreaseIndent : "Disminuir Sangría", +IncreaseIndent : "Aumentar Sangría", +Blockquote : "Cita", +CreateDiv : "Crear contenedor (div)", +EditDiv : "Editar contenedor (div)", +DeleteDiv : "Eliminar contenedor (div)", +Undo : "Deshacer", +Redo : "Rehacer", +NumberedListLbl : "Numeración", +NumberedList : "Insertar/Eliminar Numeración", +BulletedListLbl : "Viñetas", +BulletedList : "Insertar/Eliminar Viñetas", +ShowTableBorders : "Mostrar Bordes de Tablas", +ShowDetails : "Mostrar saltos de Párrafo", +Style : "Estilo", +FontFormat : "Formato", +Font : "Fuente", +FontSize : "Tamaño", +TextColor : "Color de Texto", +BGColor : "Color de Fondo", +Source : "Fuente HTML", +Find : "Buscar", +Replace : "Reemplazar", +SpellCheck : "Ortografía", +UniversalKeyboard : "Teclado Universal", +PageBreakLbl : "Salto de Página", +PageBreak : "Insertar Salto de Página", + +Form : "Formulario", +Checkbox : "Casilla de Verificación", +RadioButton : "Botones de Radio", +TextField : "Campo de Texto", +Textarea : "Area de Texto", +HiddenField : "Campo Oculto", +Button : "Botón", +SelectionField : "Campo de Selección", +ImageButton : "Botón Imagen", + +FitWindow : "Maximizar el tamaño del editor", +ShowBlocks : "Mostrar bloques", + +// Context Menu +EditLink : "Editar Vínculo", +CellCM : "Celda", +RowCM : "Fila", +ColumnCM : "Columna", +InsertRowAfter : "Insertar fila en la parte inferior", +InsertRowBefore : "Insertar fila en la parte superior", +DeleteRows : "Eliminar Filas", +InsertColumnAfter : "Insertar columna a la derecha", +InsertColumnBefore : "Insertar columna a la izquierda", +DeleteColumns : "Eliminar Columnas", +InsertCellAfter : "Insertar celda a la derecha", +InsertCellBefore : "Insertar celda a la izquierda", +DeleteCells : "Eliminar Celdas", +MergeCells : "Combinar Celdas", +MergeRight : "Combinar a la derecha", +MergeDown : "Combinar hacia abajo", +HorizontalSplitCell : "Dividir la celda horizontalmente", +VerticalSplitCell : "Dividir la celda verticalmente", +TableDelete : "Eliminar Tabla", +CellProperties : "Propiedades de Celda", +TableProperties : "Propiedades de Tabla", +ImageProperties : "Propiedades de Imagen", +FlashProperties : "Propiedades de Flash", + +AnchorProp : "Propiedades de Referencia", +ButtonProp : "Propiedades de Botón", +CheckboxProp : "Propiedades de Casilla", +HiddenFieldProp : "Propiedades de Campo Oculto", +RadioButtonProp : "Propiedades de Botón de Radio", +ImageButtonProp : "Propiedades de Botón de Imagen", +TextFieldProp : "Propiedades de Campo de Texto", +SelectionFieldProp : "Propiedades de Campo de Selección", +TextareaProp : "Propiedades de Area de Texto", +FormProp : "Propiedades de Formulario", + +FontFormats : "Normal;Con formato;Dirección;Encabezado 1;Encabezado 2;Encabezado 3;Encabezado 4;Encabezado 5;Encabezado 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Procesando XHTML. Por favor, espere...", +Done : "Hecho", +PasteWordConfirm : "El texto que desea parece provenir de Word. Desea depurarlo antes de pegarlo?", +NotCompatiblePaste : "Este comando está disponible sólo para Internet Explorer version 5.5 or superior. Desea pegar sin depurar?", +UnknownToolbarItem : "Item de barra desconocido \"%1\"", +UnknownCommand : "Nombre de comando desconocido \"%1\"", +NotImplemented : "Comando no implementado", +UnknownToolbarSet : "Nombre de barra \"%1\" no definido", +NoActiveX : "La configuración de las opciones de seguridad de su navegador puede estar limitando algunas características del editor. Por favor active la opción \"Ejecutar controles y complementos de ActiveX \", de lo contrario puede experimentar errores o ausencia de funcionalidades.", +BrowseServerBlocked : "La ventana de visualización del servidor no pudo ser abierta. Verifique que su navegador no esté bloqueando las ventanas emergentes (pop up).", +DialogBlocked : "No se ha podido abrir la ventana de diálogo. Verifique que su navegador no esté bloqueando las ventanas emergentes (pop up).", +VisitLinkBlocked : "Nose ha podido abrir la ventana. Asegurese de que todos los bloqueadores de popups están deshabilitados.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Cancelar", +DlgBtnClose : "Cerrar", +DlgBtnBrowseServer : "Ver Servidor", +DlgAdvancedTag : "Avanzado", +DlgOpOther : "", +DlgInfoTab : "Información", +DlgAlertUrl : "Inserte el URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Orientación", +DlgGenLangDirLtr : "Izquierda a Derecha (LTR)", +DlgGenLangDirRtl : "Derecha a Izquierda (RTL)", +DlgGenLangCode : "Cód. de idioma", +DlgGenAccessKey : "Clave de Acceso", +DlgGenName : "Nombre", +DlgGenTabIndex : "Indice de tabulación", +DlgGenLongDescr : "Descripción larga URL", +DlgGenClass : "Clases de hojas de estilo", +DlgGenTitle : "Título", +DlgGenContType : "Tipo de Contenido", +DlgGenLinkCharset : "Fuente de caracteres vinculado", +DlgGenStyle : "Estilo", + +// Image Dialog +DlgImgTitle : "Propiedades de Imagen", +DlgImgInfoTab : "Información de Imagen", +DlgImgBtnUpload : "Enviar al Servidor", +DlgImgURL : "URL", +DlgImgUpload : "Cargar", +DlgImgAlt : "Texto Alternativo", +DlgImgWidth : "Anchura", +DlgImgHeight : "Altura", +DlgImgLockRatio : "Proporcional", +DlgBtnResetSize : "Tamaño Original", +DlgImgBorder : "Borde", +DlgImgHSpace : "Esp.Horiz", +DlgImgVSpace : "Esp.Vert", +DlgImgAlign : "Alineación", +DlgImgAlignLeft : "Izquierda", +DlgImgAlignAbsBottom: "Abs inferior", +DlgImgAlignAbsMiddle: "Abs centro", +DlgImgAlignBaseline : "Línea de base", +DlgImgAlignBottom : "Pie", +DlgImgAlignMiddle : "Centro", +DlgImgAlignRight : "Derecha", +DlgImgAlignTextTop : "Tope del texto", +DlgImgAlignTop : "Tope", +DlgImgPreview : "Vista Previa", +DlgImgAlertUrl : "Por favor escriba la URL de la imagen", +DlgImgLinkTab : "Vínculo", + +// Flash Dialog +DlgFlashTitle : "Propiedades de Flash", +DlgFlashChkPlay : "Autoejecución", +DlgFlashChkLoop : "Repetir", +DlgFlashChkMenu : "Activar Menú Flash", +DlgFlashScale : "Escala", +DlgFlashScaleAll : "Mostrar todo", +DlgFlashScaleNoBorder : "Sin Borde", +DlgFlashScaleFit : "Ajustado", + +// Link Dialog +DlgLnkWindowTitle : "Vínculo", +DlgLnkInfoTab : "Información de Vínculo", +DlgLnkTargetTab : "Destino", + +DlgLnkType : "Tipo de vínculo", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Referencia en esta página", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocolo", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Seleccionar una referencia", +DlgLnkAnchorByName : "Por Nombre de Referencia", +DlgLnkAnchorById : "Por ID de elemento", +DlgLnkNoAnchors : "(No hay referencias disponibles en el documento)", +DlgLnkEMail : "Dirección de E-Mail", +DlgLnkEMailSubject : "Título del Mensaje", +DlgLnkEMailBody : "Cuerpo del Mensaje", +DlgLnkUpload : "Cargar", +DlgLnkBtnUpload : "Enviar al Servidor", + +DlgLnkTarget : "Destino", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nueva Ventana(_blank)", +DlgLnkTargetParent : "Ventana Padre (_parent)", +DlgLnkTargetSelf : "Misma Ventana (_self)", +DlgLnkTargetTop : "Ventana primaria (_top)", +DlgLnkTargetFrameName : "Nombre del Marco Destino", +DlgLnkPopWinName : "Nombre de Ventana Emergente", +DlgLnkPopWinFeat : "Características de Ventana Emergente", +DlgLnkPopResize : "Ajustable", +DlgLnkPopLocation : "Barra de ubicación", +DlgLnkPopMenu : "Barra de Menú", +DlgLnkPopScroll : "Barras de desplazamiento", +DlgLnkPopStatus : "Barra de Estado", +DlgLnkPopToolbar : "Barra de Herramientas", +DlgLnkPopFullScrn : "Pantalla Completa (IE)", +DlgLnkPopDependent : "Dependiente (Netscape)", +DlgLnkPopWidth : "Anchura", +DlgLnkPopHeight : "Altura", +DlgLnkPopLeft : "Posición Izquierda", +DlgLnkPopTop : "Posición Derecha", + +DlnLnkMsgNoUrl : "Por favor tipee el vínculo URL", +DlnLnkMsgNoEMail : "Por favor tipee la dirección de e-mail", +DlnLnkMsgNoAnchor : "Por favor seleccione una referencia", +DlnLnkMsgInvPopName : "El nombre debe empezar con un caracter alfanumérico y no debe contener espacios", + +// Color Dialog +DlgColorTitle : "Seleccionar Color", +DlgColorBtnClear : "Ninguno", +DlgColorHighlight : "Resaltado", +DlgColorSelected : "Seleccionado", + +// Smiley Dialog +DlgSmileyTitle : "Insertar un Emoticon", + +// Special Character Dialog +DlgSpecialCharTitle : "Seleccione un caracter especial", + +// Table Dialog +DlgTableTitle : "Propiedades de Tabla", +DlgTableRows : "Filas", +DlgTableColumns : "Columnas", +DlgTableBorder : "Tamaño de Borde", +DlgTableAlign : "Alineación", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Izquierda", +DlgTableAlignCenter : "Centrado", +DlgTableAlignRight : "Derecha", +DlgTableWidth : "Anchura", +DlgTableWidthPx : "pixeles", +DlgTableWidthPc : "porcentaje", +DlgTableHeight : "Altura", +DlgTableCellSpace : "Esp. e/celdas", +DlgTableCellPad : "Esp. interior", +DlgTableCaption : "Título", +DlgTableSummary : "Síntesis", +DlgTableHeaders : "Encabezados", +DlgTableHeadersNone : "Ninguno", +DlgTableHeadersColumn : "Primera columna", +DlgTableHeadersRow : "Primera fila", +DlgTableHeadersBoth : "Ambas", + +// Table Cell Dialog +DlgCellTitle : "Propiedades de Celda", +DlgCellWidth : "Anchura", +DlgCellWidthPx : "pixeles", +DlgCellWidthPc : "porcentaje", +DlgCellHeight : "Altura", +DlgCellWordWrap : "Cortar Línea", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Si", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Alineación Horizontal", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Izquierda", +DlgCellHorAlignCenter : "Centrado", +DlgCellHorAlignRight: "Derecha", +DlgCellVerAlign : "Alineación Vertical", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Tope", +DlgCellVerAlignMiddle : "Medio", +DlgCellVerAlignBottom : "ie", +DlgCellVerAlignBaseline : "Línea de Base", +DlgCellType : "Tipo de celda", +DlgCellTypeData : "Datos", +DlgCellTypeHeader : "Encabezado", +DlgCellRowSpan : "Abarcar Filas", +DlgCellCollSpan : "Abarcar Columnas", +DlgCellBackColor : "Color de Fondo", +DlgCellBorderColor : "Color de Borde", +DlgCellBtnSelect : "Seleccione...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Buscar y Reemplazar", + +// Find Dialog +DlgFindTitle : "Buscar", +DlgFindFindBtn : "Buscar", +DlgFindNotFoundMsg : "El texto especificado no ha sido encontrado.", + +// Replace Dialog +DlgReplaceTitle : "Reemplazar", +DlgReplaceFindLbl : "Texto a buscar:", +DlgReplaceReplaceLbl : "Reemplazar con:", +DlgReplaceCaseChk : "Coincidir may/min", +DlgReplaceReplaceBtn : "Reemplazar", +DlgReplaceReplAllBtn : "Reemplazar Todo", +DlgReplaceWordChk : "Coincidir toda la palabra", + +// Paste Operations / Dialog +PasteErrorCut : "La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado. Por favor use el teclado (Ctrl+X).", +PasteErrorCopy : "La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de copiado. Por favor use el teclado (Ctrl+C).", + +PasteAsText : "Pegar como Texto Plano", +PasteFromWord : "Pegar desde Word", + +DlgPasteMsg2 : "Por favor pegue dentro del cuadro utilizando el teclado (Ctrl+V); luego presione OK.", +DlgPasteSec : "Debido a la configuración de seguridad de su navegador, el editor no tiene acceso al portapapeles. Es necesario que lo pegue de nuevo en esta ventana.", +DlgPasteIgnoreFont : "Ignorar definiciones de fuentes", +DlgPasteRemoveStyles : "Remover definiciones de estilo", + +// Color Picker +ColorAutomatic : "Automático", +ColorMoreColors : "Más Colores...", + +// Document Properties +DocProps : "Propiedades del Documento", + +// Anchor Dialog +DlgAnchorTitle : "Propiedades de la Referencia", +DlgAnchorName : "Nombre de la Referencia", +DlgAnchorErrorName : "Por favor, complete el nombre de la Referencia", + +// Speller Pages Dialog +DlgSpellNotInDic : "No se encuentra en el Diccionario", +DlgSpellChangeTo : "Cambiar a", +DlgSpellBtnIgnore : "Ignorar", +DlgSpellBtnIgnoreAll : "Ignorar Todo", +DlgSpellBtnReplace : "Reemplazar", +DlgSpellBtnReplaceAll : "Reemplazar Todo", +DlgSpellBtnUndo : "Deshacer", +DlgSpellNoSuggestions : "- No hay sugerencias -", +DlgSpellProgress : "Control de Ortografía en progreso...", +DlgSpellNoMispell : "Control finalizado: no se encontraron errores", +DlgSpellNoChanges : "Control finalizado: no se ha cambiado ninguna palabra", +DlgSpellOneChange : "Control finalizado: se ha cambiado una palabra", +DlgSpellManyChanges : "Control finalizado: se ha cambiado %1 palabras", + +IeSpellDownload : "Módulo de Control de Ortografía no instalado. ¿Desea descargarlo ahora?", + +// Button Dialog +DlgButtonText : "Texto (Valor)", +DlgButtonType : "Tipo", +DlgButtonTypeBtn : "Boton", +DlgButtonTypeSbm : "Enviar", +DlgButtonTypeRst : "Reestablecer", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nombre", +DlgCheckboxValue : "Valor", +DlgCheckboxSelected : "Seleccionado", + +// Form Dialog +DlgFormName : "Nombre", +DlgFormAction : "Acción", +DlgFormMethod : "Método", + +// Select Field Dialog +DlgSelectName : "Nombre", +DlgSelectValue : "Valor", +DlgSelectSize : "Tamaño", +DlgSelectLines : "Lineas", +DlgSelectChkMulti : "Permitir múltiple selección", +DlgSelectOpAvail : "Opciones disponibles", +DlgSelectOpText : "Texto", +DlgSelectOpValue : "Valor", +DlgSelectBtnAdd : "Agregar", +DlgSelectBtnModify : "Modificar", +DlgSelectBtnUp : "Subir", +DlgSelectBtnDown : "Bajar", +DlgSelectBtnSetValue : "Establecer como predeterminado", +DlgSelectBtnDelete : "Eliminar", + +// Textarea Dialog +DlgTextareaName : "Nombre", +DlgTextareaCols : "Columnas", +DlgTextareaRows : "Filas", + +// Text Field Dialog +DlgTextName : "Nombre", +DlgTextValue : "Valor", +DlgTextCharWidth : "Caracteres de ancho", +DlgTextMaxChars : "Máximo caracteres", +DlgTextType : "Tipo", +DlgTextTypeText : "Texto", +DlgTextTypePass : "Contraseña", + +// Hidden Field Dialog +DlgHiddenName : "Nombre", +DlgHiddenValue : "Valor", + +// Bulleted List Dialog +BulletedListProp : "Propiedades de Viñetas", +NumberedListProp : "Propiedades de Numeraciones", +DlgLstStart : "Inicio", +DlgLstType : "Tipo", +DlgLstTypeCircle : "Círculo", +DlgLstTypeDisc : "Disco", +DlgLstTypeSquare : "Cuadrado", +DlgLstTypeNumbers : "Números (1, 2, 3)", +DlgLstTypeLCase : "letras en minúsculas (a, b, c)", +DlgLstTypeUCase : "letras en mayúsculas (A, B, C)", +DlgLstTypeSRoman : "Números Romanos (i, ii, iii)", +DlgLstTypeLRoman : "Números Romanos (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "General", +DlgDocBackTab : "Fondo", +DlgDocColorsTab : "Colores y Márgenes", +DlgDocMetaTab : "Meta Información", + +DlgDocPageTitle : "Título de Página", +DlgDocLangDir : "Orientación de idioma", +DlgDocLangDirLTR : "Izq. a Derecha (LTR)", +DlgDocLangDirRTL : "Der. a Izquierda (RTL)", +DlgDocLangCode : "Código de Idioma", +DlgDocCharSet : "Codif. de Conjunto de Caracteres", +DlgDocCharSetCE : "Centro Europeo", +DlgDocCharSetCT : "Chino Tradicional (Big5)", +DlgDocCharSetCR : "Cirílico", +DlgDocCharSetGR : "Griego", +DlgDocCharSetJP : "Japonés", +DlgDocCharSetKR : "Coreano", +DlgDocCharSetTR : "Turco", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Europeo occidental", +DlgDocCharSetOther : "Otra Codificación", + +DlgDocDocType : "Encabezado de Tipo de Documento", +DlgDocDocTypeOther : "Otro Encabezado", +DlgDocIncXHTML : "Incluir Declaraciones XHTML", +DlgDocBgColor : "Color de Fondo", +DlgDocBgImage : "URL de Imagen de Fondo", +DlgDocBgNoScroll : "Fondo sin rolido", +DlgDocCText : "Texto", +DlgDocCLink : "Vínculo", +DlgDocCVisited : "Vínculo Visitado", +DlgDocCActive : "Vínculo Activo", +DlgDocMargins : "Márgenes de Página", +DlgDocMaTop : "Tope", +DlgDocMaLeft : "Izquierda", +DlgDocMaRight : "Derecha", +DlgDocMaBottom : "Pie", +DlgDocMeIndex : "Claves de indexación del Documento (separados por comas)", +DlgDocMeDescr : "Descripción del Documento", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Vista Previa", + +// Templates Dialog +Templates : "Plantillas", +DlgTemplatesTitle : "Contenido de Plantillas", +DlgTemplatesSelMsg : "Por favor selecciona la plantilla a abrir en el editor
    (el contenido actual se perderá):", +DlgTemplatesLoading : "Cargando lista de Plantillas. Por favor, aguarde...", +DlgTemplatesNoTpl : "(No hay plantillas definidas)", +DlgTemplatesReplace : "Reemplazar el contenido actual", + +// About Dialog +DlgAboutAboutTab : "Acerca de", +DlgAboutBrowserInfoTab : "Información de Navegador", +DlgAboutLicenseTab : "Licencia", +DlgAboutVersion : "versión", +DlgAboutInfo : "Para mayor información por favor dirigirse a", + +// Div Dialog +DlgDivGeneralTab : "General", +DlgDivAdvancedTab : "Avanzado", +DlgDivStyle : "Estilo", +DlgDivInlineStyle : "Estilos CSS", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/et.js b/www/js/FCKeditor/editor/lang/et.js new file mode 100644 index 0000000..1b25e53 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/et.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Estonian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Voldi tööriistariba", +ToolbarExpand : "Laienda tööriistariba", + +// Toolbar Items and Context Menu +Save : "Salvesta", +NewPage : "Uus leht", +Preview : "Eelvaade", +Cut : "Lõika", +Copy : "Kopeeri", +Paste : "Kleebi", +PasteText : "Kleebi tavalise tekstina", +PasteWord : "Kleebi Wordist", +Print : "Prindi", +SelectAll : "Vali kõik", +RemoveFormat : "Eemalda vorming", +InsertLinkLbl : "Link", +InsertLink : "Sisesta link / Muuda linki", +RemoveLink : "Eemalda link", +VisitLink : "Open Link", //MISSING +Anchor : "Sisesta ankur / Muuda ankrut", +AnchorDelete : "Eemalda ankur", +InsertImageLbl : "Pilt", +InsertImage : "Sisesta pilt / Muuda pilti", +InsertFlashLbl : "Flash", +InsertFlash : "Sisesta flash / Muuda flashi", +InsertTableLbl : "Tabel", +InsertTable : "Sisesta tabel / Muuda tabelit", +InsertLineLbl : "Joon", +InsertLine : "Sisesta horisontaaljoon", +InsertSpecialCharLbl: "Erimärgid", +InsertSpecialChar : "Sisesta erimärk", +InsertSmileyLbl : "Emotikon", +InsertSmiley : "Sisesta emotikon", +About : "FCKeditor teave", +Bold : "Paks", +Italic : "Kursiiv", +Underline : "Allajoonitud", +StrikeThrough : "Läbijoonitud", +Subscript : "Allindeks", +Superscript : "Ülaindeks", +LeftJustify : "Vasakjoondus", +CenterJustify : "Keskjoondus", +RightJustify : "Paremjoondus", +BlockJustify : "Rööpjoondus", +DecreaseIndent : "Vähenda taanet", +IncreaseIndent : "Suurenda taanet", +Blockquote : "Blokktsitaat", +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Võta tagasi", +Redo : "Korda toimingut", +NumberedListLbl : "Nummerdatud loetelu", +NumberedList : "Sisesta/Eemalda nummerdatud loetelu", +BulletedListLbl : "Punktiseeritud loetelu", +BulletedList : "Sisesta/Eemalda punktiseeritud loetelu", +ShowTableBorders : "Näita tabeli jooni", +ShowDetails : "Näita üksikasju", +Style : "Laad", +FontFormat : "Vorming", +Font : "Kiri", +FontSize : "Suurus", +TextColor : "Teksti värv", +BGColor : "Tausta värv", +Source : "Lähtekood", +Find : "Otsi", +Replace : "Asenda", +SpellCheck : "Kontrolli õigekirja", +UniversalKeyboard : "Universaalne klaviatuur", +PageBreakLbl : "Lehepiir", +PageBreak : "Sisesta lehevahetuskoht", + +Form : "Vorm", +Checkbox : "Märkeruut", +RadioButton : "Raadionupp", +TextField : "Tekstilahter", +Textarea : "Tekstiala", +HiddenField : "Varjatud lahter", +Button : "Nupp", +SelectionField : "Valiklahter", +ImageButton : "Piltnupp", + +FitWindow : "Maksimeeri redaktori mõõtmed", +ShowBlocks : "Näita blokke", + +// Context Menu +EditLink : "Muuda linki", +CellCM : "Lahter", +RowCM : "Rida", +ColumnCM : "Veerg", +InsertRowAfter : "Sisesta rida peale", +InsertRowBefore : "Sisesta rida enne", +DeleteRows : "Eemalda read", +InsertColumnAfter : "Sisesta veerg peale", +InsertColumnBefore : "Sisesta veerg enne", +DeleteColumns : "Eemalda veerud", +InsertCellAfter : "Sisesta lahter peale", +InsertCellBefore : "Sisesta lahter enne", +DeleteCells : "Eemalda lahtrid", +MergeCells : "Ühenda lahtrid", +MergeRight : "Ühenda paremale", +MergeDown : "Ühenda alla", +HorizontalSplitCell : "Poolita lahter horisontaalselt", +VerticalSplitCell : "Poolita lahter vertikaalselt", +TableDelete : "Kustuta tabel", +CellProperties : "Lahtri atribuudid", +TableProperties : "Tabeli atribuudid", +ImageProperties : "Pildi atribuudid", +FlashProperties : "Flash omadused", + +AnchorProp : "Ankru omadused", +ButtonProp : "Nupu omadused", +CheckboxProp : "Märkeruudu omadused", +HiddenFieldProp : "Varjatud lahtri omadused", +RadioButtonProp : "Raadionupu omadused", +ImageButtonProp : "Piltnupu omadused", +TextFieldProp : "Tekstilahtri omadused", +SelectionFieldProp : "Valiklahtri omadused", +TextareaProp : "Tekstiala omadused", +FormProp : "Vormi omadused", + +FontFormats : "Tavaline;Vormindatud;Aadress;Pealkiri 1;Pealkiri 2;Pealkiri 3;Pealkiri 4;Pealkiri 5;Pealkiri 6;Tavaline (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Töötlen XHTML'i. Palun oota...", +Done : "Tehtud", +PasteWordConfirm : "Tekst, mida soovid lisada paistab pärinevat Word'ist. Kas soovid seda enne kleepimist puhastada?", +NotCompatiblePaste : "See käsk on saadaval ainult Internet Explorer versioon 5.5 või uuema puhul. Kas soovid kleepida ilma puhastamata?", +UnknownToolbarItem : "Tundmatu tööriistarea üksus \"%1\"", +UnknownCommand : "Tundmatu käsunimi \"%1\"", +NotImplemented : "Käsku ei täidetud", +UnknownToolbarSet : "Tööriistariba \"%1\" ei eksisteeri", +NoActiveX : "Sinu veebisirvija turvalisuse seaded võivad limiteerida mõningaid tekstirdaktori kasutusvõimalusi. Sa peaksid võimaldama valiku \"Run ActiveX controls and plug-ins\" oma veebisirvija seadetes. Muidu võid sa täheldada vigu tekstiredaktori töös ja märgata puuduvaid funktsioone.", +BrowseServerBlocked : "Ressursside sirvija avamine ebaõnnestus. Võimalda pop-up akende avanemine.", +DialogBlocked : "Ei olenud võimalik avada dialoogi akent. Võimalda pop-up akende avanemine.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Loobu", +DlgBtnClose : "Sulge", +DlgBtnBrowseServer : "Sirvi serverit", +DlgAdvancedTag : "Täpsemalt", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Palun sisesta URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Keele suund", +DlgGenLangDirLtr : "Vasakult paremale (LTR)", +DlgGenLangDirRtl : "Paremalt vasakule (RTL)", +DlgGenLangCode : "Keele kood", +DlgGenAccessKey : "Juurdepääsu võti", +DlgGenName : "Nimi", +DlgGenTabIndex : "Tab indeks", +DlgGenLongDescr : "Pikk kirjeldus URL", +DlgGenClass : "Stiilistiku klassid", +DlgGenTitle : "Juhendav tiitel", +DlgGenContType : "Juhendava sisu tüüp", +DlgGenLinkCharset : "Lingitud ressurssi märgistik", +DlgGenStyle : "Laad", + +// Image Dialog +DlgImgTitle : "Pildi atribuudid", +DlgImgInfoTab : "Pildi info", +DlgImgBtnUpload : "Saada serverissee", +DlgImgURL : "URL", +DlgImgUpload : "Lae üles", +DlgImgAlt : "Alternatiivne tekst", +DlgImgWidth : "Laius", +DlgImgHeight : "Kõrgus", +DlgImgLockRatio : "Lukusta kuvasuhe", +DlgBtnResetSize : "Lähtesta suurus", +DlgImgBorder : "Joon", +DlgImgHSpace : "H. vaheruum", +DlgImgVSpace : "V. vaheruum", +DlgImgAlign : "Joondus", +DlgImgAlignLeft : "Vasak", +DlgImgAlignAbsBottom: "Abs alla", +DlgImgAlignAbsMiddle: "Abs keskele", +DlgImgAlignBaseline : "Baasjoonele", +DlgImgAlignBottom : "Alla", +DlgImgAlignMiddle : "Keskele", +DlgImgAlignRight : "Paremale", +DlgImgAlignTextTop : "Tekstit üles", +DlgImgAlignTop : "Üles", +DlgImgPreview : "Eelvaade", +DlgImgAlertUrl : "Palun kirjuta pildi URL", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash omadused", +DlgFlashChkPlay : "Automaatne start ", +DlgFlashChkLoop : "Korduv", +DlgFlashChkMenu : "Võimalda flash menüü", +DlgFlashScale : "Mastaap", +DlgFlashScaleAll : "Näita kõike", +DlgFlashScaleNoBorder : "Äärist ei ole", +DlgFlashScaleFit : "Täpne sobivus", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Lingi info", +DlgLnkTargetTab : "Sihtkoht", + +DlgLnkType : "Lingi tüüp", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Ankur sellel lehel", +DlgLnkTypeEMail : "E-post", +DlgLnkProto : "Protokoll", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Vali ankur", +DlgLnkAnchorByName : "Ankru nime järgi", +DlgLnkAnchorById : "Elemendi id järgi", +DlgLnkNoAnchors : "(Selles dokumendis ei ole ankruid)", +DlgLnkEMail : "E-posti aadress", +DlgLnkEMailSubject : "Sõnumi teema", +DlgLnkEMailBody : "Sõnumi tekst", +DlgLnkUpload : "Lae üles", +DlgLnkBtnUpload : "Saada serverisse", + +DlgLnkTarget : "Sihtkoht", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Uus aken (_blank)", +DlgLnkTargetParent : "Esivanem aken (_parent)", +DlgLnkTargetSelf : "Sama aken (_self)", +DlgLnkTargetTop : "Pealmine aken (_top)", +DlgLnkTargetFrameName : "Sihtmärk raami nimi", +DlgLnkPopWinName : "Hüpikakna nimi", +DlgLnkPopWinFeat : "Hüpikakna omadused", +DlgLnkPopResize : "Suurendatav", +DlgLnkPopLocation : "Aadressiriba", +DlgLnkPopMenu : "Menüüriba", +DlgLnkPopScroll : "Kerimisribad", +DlgLnkPopStatus : "Olekuriba", +DlgLnkPopToolbar : "Tööriistariba", +DlgLnkPopFullScrn : "Täisekraan (IE)", +DlgLnkPopDependent : "Sõltuv (Netscape)", +DlgLnkPopWidth : "Laius", +DlgLnkPopHeight : "Kõrgus", +DlgLnkPopLeft : "Vasak asukoht", +DlgLnkPopTop : "Ülemine asukoht", + +DlnLnkMsgNoUrl : "Palun kirjuta lingi URL", +DlnLnkMsgNoEMail : "Palun kirjuta E-Posti aadress", +DlnLnkMsgNoAnchor : "Palun vali ankur", +DlnLnkMsgInvPopName : "Hüpikakna nimi peab algama alfabeetilise tähega ja ei tohi sisaldada tühikuid", + +// Color Dialog +DlgColorTitle : "Vali värv", +DlgColorBtnClear : "Tühjenda", +DlgColorHighlight : "Märgi", +DlgColorSelected : "Valitud", + +// Smiley Dialog +DlgSmileyTitle : "Sisesta emotikon", + +// Special Character Dialog +DlgSpecialCharTitle : "Vali erimärk", + +// Table Dialog +DlgTableTitle : "Tabeli atribuudid", +DlgTableRows : "Read", +DlgTableColumns : "Veerud", +DlgTableBorder : "Joone suurus", +DlgTableAlign : "Joondus", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Vasak", +DlgTableAlignCenter : "Kesk", +DlgTableAlignRight : "Parem", +DlgTableWidth : "Laius", +DlgTableWidthPx : "pikslit", +DlgTableWidthPc : "protsenti", +DlgTableHeight : "Kõrgus", +DlgTableCellSpace : "Lahtri vahe", +DlgTableCellPad : "Lahtri täidis", +DlgTableCaption : "Tabeli tiitel", +DlgTableSummary : "Kokkuvõte", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Lahtri atribuudid", +DlgCellWidth : "Laius", +DlgCellWidthPx : "pikslit", +DlgCellWidthPc : "protsenti", +DlgCellHeight : "Kõrgus", +DlgCellWordWrap : "Sõna ülekanne", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Jah", +DlgCellWordWrapNo : "Ei", +DlgCellHorAlign : "Horisontaaljoondus", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Vasak", +DlgCellHorAlignCenter : "Kesk", +DlgCellHorAlignRight: "Parem", +DlgCellVerAlign : "Vertikaaljoondus", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Üles", +DlgCellVerAlignMiddle : "Keskele", +DlgCellVerAlignBottom : "Alla", +DlgCellVerAlignBaseline : "Baasjoonele", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Reaulatus", +DlgCellCollSpan : "Veeruulatus", +DlgCellBackColor : "Tausta värv", +DlgCellBorderColor : "Joone värv", +DlgCellBtnSelect : "Vali...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Otsi ja asenda", + +// Find Dialog +DlgFindTitle : "Otsi", +DlgFindFindBtn : "Otsi", +DlgFindNotFoundMsg : "Valitud teksti ei leitud.", + +// Replace Dialog +DlgReplaceTitle : "Asenda", +DlgReplaceFindLbl : "Leia mida:", +DlgReplaceReplaceLbl : "Asenda millega:", +DlgReplaceCaseChk : "Erista suur- ja väiketähti", +DlgReplaceReplaceBtn : "Asenda", +DlgReplaceReplAllBtn : "Asenda kõik", +DlgReplaceWordChk : "Otsi terviklike sõnu", + +// Paste Operations / Dialog +PasteErrorCut : "Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl+X).", +PasteErrorCopy : "Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt kopeerida. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl+C).", + +PasteAsText : "Kleebi tavalise tekstina", +PasteFromWord : "Kleebi Wordist", + +DlgPasteMsg2 : "Palun kleebi järgnevasse kasti kasutades klaviatuuri klahvikombinatsiooni (Ctrl+V) ja vajuta seejärel OK.", +DlgPasteSec : "Sinu veebisirvija turvaseadete tõttu, ei oma redaktor otsest ligipääsu lõikelaua andmetele. Sa pead kleepima need uuesti siia aknasse.", +DlgPasteIgnoreFont : "Ignoreeri kirja definitsioone", +DlgPasteRemoveStyles : "Eemalda stiilide definitsioonid", + +// Color Picker +ColorAutomatic : "Automaatne", +ColorMoreColors : "Rohkem värve...", + +// Document Properties +DocProps : "Dokumendi omadused", + +// Anchor Dialog +DlgAnchorTitle : "Ankru omadused", +DlgAnchorName : "Ankru nimi", +DlgAnchorErrorName : "Palun sisest ankru nimi", + +// Speller Pages Dialog +DlgSpellNotInDic : "Puudub sõnastikust", +DlgSpellChangeTo : "Muuda", +DlgSpellBtnIgnore : "Ignoreeri", +DlgSpellBtnIgnoreAll : "Ignoreeri kõiki", +DlgSpellBtnReplace : "Asenda", +DlgSpellBtnReplaceAll : "Asenda kõik", +DlgSpellBtnUndo : "Võta tagasi", +DlgSpellNoSuggestions : "- Soovitused puuduvad -", +DlgSpellProgress : "Toimub õigekirja kontroll...", +DlgSpellNoMispell : "Õigekirja kontroll sooritatud: õigekirjuvigu ei leitud", +DlgSpellNoChanges : "Õigekirja kontroll sooritatud: ühtegi sõna ei muudetud", +DlgSpellOneChange : "Õigekirja kontroll sooritatud: üks sõna muudeti", +DlgSpellManyChanges : "Õigekirja kontroll sooritatud: %1 sõna muudetud", + +IeSpellDownload : "Õigekirja kontrollija ei ole installeeritud. Soovid sa selle alla laadida?", + +// Button Dialog +DlgButtonText : "Tekst (väärtus)", +DlgButtonType : "Tüüp", +DlgButtonTypeBtn : "Nupp", +DlgButtonTypeSbm : "Saada", +DlgButtonTypeRst : "Lähtesta", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nimi", +DlgCheckboxValue : "Väärtus", +DlgCheckboxSelected : "Valitud", + +// Form Dialog +DlgFormName : "Nimi", +DlgFormAction : "Toiming", +DlgFormMethod : "Meetod", + +// Select Field Dialog +DlgSelectName : "Nimi", +DlgSelectValue : "Väärtus", +DlgSelectSize : "Suurus", +DlgSelectLines : "ridu", +DlgSelectChkMulti : "Võimalda mitu valikut", +DlgSelectOpAvail : "Võimalikud valikud", +DlgSelectOpText : "Tekst", +DlgSelectOpValue : "Väärtus", +DlgSelectBtnAdd : "Lisa", +DlgSelectBtnModify : "Muuda", +DlgSelectBtnUp : "Üles", +DlgSelectBtnDown : "Alla", +DlgSelectBtnSetValue : "Sea valitud olekuna", +DlgSelectBtnDelete : "Kustuta", + +// Textarea Dialog +DlgTextareaName : "Nimi", +DlgTextareaCols : "Veerge", +DlgTextareaRows : "Ridu", + +// Text Field Dialog +DlgTextName : "Nimi", +DlgTextValue : "Väärtus", +DlgTextCharWidth : "Laius (tähemärkides)", +DlgTextMaxChars : "Maksimaalselt tähemärke", +DlgTextType : "Tüüp", +DlgTextTypeText : "Tekst", +DlgTextTypePass : "Parool", + +// Hidden Field Dialog +DlgHiddenName : "Nimi", +DlgHiddenValue : "Väärtus", + +// Bulleted List Dialog +BulletedListProp : "Täpitud loetelu omadused", +NumberedListProp : "Nummerdatud loetelu omadused", +DlgLstStart : "Alusta", +DlgLstType : "Tüüp", +DlgLstTypeCircle : "Ring", +DlgLstTypeDisc : "Ketas", +DlgLstTypeSquare : "Ruut", +DlgLstTypeNumbers : "Numbrid (1, 2, 3)", +DlgLstTypeLCase : "Väiketähed (a, b, c)", +DlgLstTypeUCase : "Suurtähed (A, B, C)", +DlgLstTypeSRoman : "Väiksed Rooma numbrid (i, ii, iii)", +DlgLstTypeLRoman : "Suured Rooma numbrid (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Üldine", +DlgDocBackTab : "Taust", +DlgDocColorsTab : "Värvid ja veerised", +DlgDocMetaTab : "Meta andmed", + +DlgDocPageTitle : "Lehekülje tiitel", +DlgDocLangDir : "Kirja suund", +DlgDocLangDirLTR : "Vasakult paremale (LTR)", +DlgDocLangDirRTL : "Paremalt vasakule (RTL)", +DlgDocLangCode : "Keele kood", +DlgDocCharSet : "Märgistiku kodeering", +DlgDocCharSetCE : "Kesk-Euroopa", +DlgDocCharSetCT : "Hiina traditsiooniline (Big5)", +DlgDocCharSetCR : "Kirillisa", +DlgDocCharSetGR : "Kreeka", +DlgDocCharSetJP : "Jaapani", +DlgDocCharSetKR : "Korea", +DlgDocCharSetTR : "Türgi", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Lääne-Euroopa", +DlgDocCharSetOther : "Ülejäänud märgistike kodeeringud", + +DlgDocDocType : "Dokumendi tüüppäis", +DlgDocDocTypeOther : "Teised dokumendi tüüppäised", +DlgDocIncXHTML : "Arva kaasa XHTML deklaratsioonid", +DlgDocBgColor : "Taustavärv", +DlgDocBgImage : "Taustapildi URL", +DlgDocBgNoScroll : "Mittekeritav tagataust", +DlgDocCText : "Tekst", +DlgDocCLink : "Link", +DlgDocCVisited : "Külastatud link", +DlgDocCActive : "Aktiivne link", +DlgDocMargins : "Lehekülje äärised", +DlgDocMaTop : "Ülaserv", +DlgDocMaLeft : "Vasakserv", +DlgDocMaRight : "Paremserv", +DlgDocMaBottom : "Alaserv", +DlgDocMeIndex : "Dokumendi võtmesõnad (eraldatud komadega)", +DlgDocMeDescr : "Dokumendi kirjeldus", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Autoriõigus", +DlgDocPreview : "Eelvaade", + +// Templates Dialog +Templates : "Šabloon", +DlgTemplatesTitle : "Sisu šabloonid", +DlgTemplatesSelMsg : "Palun vali šabloon, et avada see redaktoris
    (praegune sisu läheb kaotsi):", +DlgTemplatesLoading : "Laen šabloonide nimekirja. Palun oota...", +DlgTemplatesNoTpl : "(Ühtegi šablooni ei ole defineeritud)", +DlgTemplatesReplace : "Asenda tegelik sisu", + +// About Dialog +DlgAboutAboutTab : "Teave", +DlgAboutBrowserInfoTab : "Veebisirvija info", +DlgAboutLicenseTab : "Litsents", +DlgAboutVersion : "versioon", +DlgAboutInfo : "Täpsema info saamiseks mine", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/eu.js b/www/js/FCKeditor/editor/lang/eu.js new file mode 100644 index 0000000..57e5642 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/eu.js @@ -0,0 +1,540 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Basque language file. + * Euskara hizkuntza fitxategia. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Estutu Tresna Barra", +ToolbarExpand : "Hedatu Tresna Barra", + +// Toolbar Items and Context Menu +Save : "Gorde", +NewPage : "Orrialde Berria", +Preview : "Aurrebista", +Cut : "Ebaki", +Copy : "Kopiatu", +Paste : "Itsatsi", +PasteText : "Itsatsi testu bezala", +PasteWord : "Itsatsi Word-etik", +Print : "Inprimatu", +SelectAll : "Hautatu dena", +RemoveFormat : "Kendu Formatua", +InsertLinkLbl : "Esteka", +InsertLink : "Txertatu/Editatu Esteka", +RemoveLink : "Kendu Esteka", +VisitLink : "Ireki Esteka", +Anchor : "Aingura", +AnchorDelete : "Ezabatu Aingura", +InsertImageLbl : "Irudia", +InsertImage : "Txertatu/Editatu Irudia", +InsertFlashLbl : "Flasha", +InsertFlash : "Txertatu/Editatu Flasha", +InsertTableLbl : "Taula", +InsertTable : "Txertatu/Editatu Taula", +InsertLineLbl : "Lerroa", +InsertLine : "Txertatu Marra Horizontala", +InsertSpecialCharLbl: "Karaktere Berezia", +InsertSpecialChar : "Txertatu Karaktere Berezia", +InsertSmileyLbl : "Aurpegierak", +InsertSmiley : "Txertatu Aurpegierak", +About : "FCKeditor-ri buruz", +Bold : "Lodia", +Italic : "Etzana", +Underline : "Azpimarratu", +StrikeThrough : "Marratua", +Subscript : "Azpi-indize", +Superscript : "Goi-indize", +LeftJustify : "Lerrokatu Ezkerrean", +CenterJustify : "Lerrokatu Erdian", +RightJustify : "Lerrokatu Eskuman", +BlockJustify : "Justifikatu", +DecreaseIndent : "Txikitu Koska", +IncreaseIndent : "Handitu Koska", +Blockquote : "Aipamen blokea", +CreateDiv : "Sortu Div Edukitzailea", +EditDiv : "Editatu Div Edukitzailea", +DeleteDiv : "Ezabatu Div Edukitzailea", +Undo : "Desegin", +Redo : "Berregin", +NumberedListLbl : "Zenbakidun Zerrenda", +NumberedList : "Txertatu/Kendu Zenbakidun zerrenda", +BulletedListLbl : "Buletdun Zerrenda", +BulletedList : "Txertatu/Kendu Buletdun zerrenda", +ShowTableBorders : "Erakutsi Taularen Ertzak", +ShowDetails : "Erakutsi Xehetasunak", +Style : "Estiloa", +FontFormat : "Formatua", +Font : "Letra-tipoa", +FontSize : "Tamaina", +TextColor : "Testu Kolorea", +BGColor : "Atzeko kolorea", +Source : "HTML Iturburua", +Find : "Bilatu", +Replace : "Ordezkatu", +SpellCheck : "Ortografia", +UniversalKeyboard : "Teklatu Unibertsala", +PageBreakLbl : "Orrialde-jauzia", +PageBreak : "Txertatu Orrialde-jauzia", + +Form : "Formularioa", +Checkbox : "Kontrol-laukia", +RadioButton : "Aukera-botoia", +TextField : "Testu Eremua", +Textarea : "Testu-area", +HiddenField : "Ezkutuko Eremua", +Button : "Botoia", +SelectionField : "Hautespen Eremua", +ImageButton : "Irudi Botoia", + +FitWindow : "Maximizatu editorearen tamaina", +ShowBlocks : "Blokeak erakutsi", + +// Context Menu +EditLink : "Aldatu Esteka", +CellCM : "Gelaxka", +RowCM : "Errenkada", +ColumnCM : "Zutabea", +InsertRowAfter : "Txertatu Lerroa Ostean", +InsertRowBefore : "Txertatu Lerroa Aurretik", +DeleteRows : "Ezabatu Errenkadak", +InsertColumnAfter : "Txertatu Zutabea Ostean", +InsertColumnBefore : "Txertatu Zutabea Aurretik", +DeleteColumns : "Ezabatu Zutabeak", +InsertCellAfter : "Txertatu Gelaxka Ostean", +InsertCellBefore : "Txertatu Gelaxka Aurretik", +DeleteCells : "Kendu Gelaxkak", +MergeCells : "Batu Gelaxkak", +MergeRight : "Elkartu Eskumara", +MergeDown : "Elkartu Behera", +HorizontalSplitCell : "Banatu Gelaxkak Horizontalki", +VerticalSplitCell : "Banatu Gelaxkak Bertikalki", +TableDelete : "Ezabatu Taula", +CellProperties : "Gelaxkaren Ezaugarriak", +TableProperties : "Taularen Ezaugarriak", +ImageProperties : "Irudiaren Ezaugarriak", +FlashProperties : "Flasharen Ezaugarriak", + +AnchorProp : "Ainguraren Ezaugarriak", +ButtonProp : "Botoiaren Ezaugarriak", +CheckboxProp : "Kontrol-laukiko Ezaugarriak", +HiddenFieldProp : "Ezkutuko Eremuaren Ezaugarriak", +RadioButtonProp : "Aukera-botoiaren Ezaugarriak", +ImageButtonProp : "Irudi Botoiaren Ezaugarriak", +TextFieldProp : "Testu Eremuaren Ezaugarriak", +SelectionFieldProp : "Hautespen Eremuaren Ezaugarriak", +TextareaProp : "Testu-arearen Ezaugarriak", +FormProp : "Formularioaren Ezaugarriak", + +FontFormats : "Arrunta;Formateatua;Helbidea;Izenburua 1;Izenburua 2;Izenburua 3;Izenburua 4;Izenburua 5;Izenburua 6;Paragrafoa (DIV)", + +// Alerts and Messages +ProcessingXHTML : "XHTML Prozesatzen. Itxaron mesedez...", +Done : "Eginda", +PasteWordConfirm : "Itsatsi nahi duzun testua Wordetik hartua dela dirudi. Itsatsi baino lehen garbitu nahi duzu?", +NotCompatiblePaste : "Komando hau Internet Explorer 5.5 bertsiorako edo ondorengoentzako erabilgarria dago. Garbitu gabe itsatsi nahi duzu?", +UnknownToolbarItem : "Ataza barrako elementu ezezaguna \"%1\"", +UnknownCommand : "Komando izen ezezaguna \"%1\"", +NotImplemented : "Komando ez inplementatua", +UnknownToolbarSet : "Ataza barra \"%1\" taldea ez da existitzen", +NoActiveX : "Zure nabigatzailearen segurtasun hobespenak editore honen zenbait ezaugarri mugatu ditzake. \"ActiveX kontrolak eta pluginak\" aktibatu beharko zenituzke, bestela erroreak eta ezaugarrietan mugak egon daitezke.", +BrowseServerBlocked : "Baliabideen arakatzailea ezin da ireki. Ziurtatu popup blokeatzaileak desgaituta dituzula.", +DialogBlocked : "Ezin da elkarrizketa-leihoa ireki. Ziurtatu popup blokeatzaileak desgaituta dituzula.", +VisitLinkBlocked : "Ezin da leiho berri bat ireki. Ziurtatu popup blokeatzaileak desgaituta dituzula.", + +// Dialogs +DlgBtnOK : "Ados", +DlgBtnCancel : "Utzi", +DlgBtnClose : "Itxi", +DlgBtnBrowseServer : "Zerbitzaria arakatu", +DlgAdvancedTag : "Aurreratua", +DlgOpOther : "", +DlgInfoTab : "Informazioa", +DlgAlertUrl : "Mesedez URLa idatzi ezazu", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Hizkuntzaren Norabidea", +DlgGenLangDirLtr : "Ezkerretik Eskumara(LTR)", +DlgGenLangDirRtl : "Eskumatik Ezkerrera (RTL)", +DlgGenLangCode : "Hizkuntza Kodea", +DlgGenAccessKey : "Sarbide-gakoa", +DlgGenName : "Izena", +DlgGenTabIndex : "Tabulazio Indizea", +DlgGenLongDescr : "URL Deskribapen Luzea", +DlgGenClass : "Estilo-orriko Klaseak", +DlgGenTitle : "Izenburua", +DlgGenContType : "Eduki Mota (Content Type)", +DlgGenLinkCharset : "Estekatutako Karaktere Multzoa", +DlgGenStyle : "Estiloa", + +// Image Dialog +DlgImgTitle : "Irudi Ezaugarriak", +DlgImgInfoTab : "Irudi informazioa", +DlgImgBtnUpload : "Zerbitzarira bidalia", +DlgImgURL : "URL", +DlgImgUpload : "Gora Kargatu", +DlgImgAlt : "Ordezko Testua", +DlgImgWidth : "Zabalera", +DlgImgHeight : "Altuera", +DlgImgLockRatio : "Erlazioa Blokeatu", +DlgBtnResetSize : "Tamaina Berrezarri", +DlgImgBorder : "Ertza", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Lerrokatu", +DlgImgAlignLeft : "Ezkerrera", +DlgImgAlignAbsBottom: "Abs Behean", +DlgImgAlignAbsMiddle: "Abs Erdian", +DlgImgAlignBaseline : "Oinan", +DlgImgAlignBottom : "Behean", +DlgImgAlignMiddle : "Erdian", +DlgImgAlignRight : "Eskuman", +DlgImgAlignTextTop : "Testua Goian", +DlgImgAlignTop : "Goian", +DlgImgPreview : "Aurrebista", +DlgImgAlertUrl : "Mesedez Irudiaren URLa idatzi", +DlgImgLinkTab : "Esteka", + +// Flash Dialog +DlgFlashTitle : "Flasharen Ezaugarriak", +DlgFlashChkPlay : "Automatikoki Erreproduzitu", +DlgFlashChkLoop : "Begizta", +DlgFlashChkMenu : "Flasharen Menua Gaitu", +DlgFlashScale : "Eskalatu", +DlgFlashScaleAll : "Dena erakutsi", +DlgFlashScaleNoBorder : "Ertzik gabe", +DlgFlashScaleFit : "Doitu", + +// Link Dialog +DlgLnkWindowTitle : "Esteka", +DlgLnkInfoTab : "Estekaren Informazioa", +DlgLnkTargetTab : "Helburua", + +DlgLnkType : "Esteka Mota", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Aingura orrialde honetan", +DlgLnkTypeEMail : "ePosta", +DlgLnkProto : "Protokoloa", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Aingura bat hautatu", +DlgLnkAnchorByName : "Aingura izenagatik", +DlgLnkAnchorById : "Elementuaren ID-gatik", +DlgLnkNoAnchors : "(Ez daude aingurak eskuragarri dokumentuan)", +DlgLnkEMail : "ePosta Helbidea", +DlgLnkEMailSubject : "Mezuaren Gaia", +DlgLnkEMailBody : "Mezuaren Gorputza", +DlgLnkUpload : "Gora kargatu", +DlgLnkBtnUpload : "Zerbitzarira bidali", + +DlgLnkTarget : "Target (Helburua)", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Leiho Berria (_blank)", +DlgLnkTargetParent : "Leiho Gurasoa (_parent)", +DlgLnkTargetSelf : "Leiho Berdina (_self)", +DlgLnkTargetTop : "Goiko Leihoa (_top)", +DlgLnkTargetFrameName : "Marko Helburuaren Izena", +DlgLnkPopWinName : "Popup Leihoaren Izena", +DlgLnkPopWinFeat : "Popup Leihoaren Ezaugarriak", +DlgLnkPopResize : "Tamaina Aldakorra", +DlgLnkPopLocation : "Kokaleku Barra", +DlgLnkPopMenu : "Menu Barra", +DlgLnkPopScroll : "Korritze Barrak", +DlgLnkPopStatus : "Egoera Barra", +DlgLnkPopToolbar : "Tresna Barra", +DlgLnkPopFullScrn : "Pantaila Osoa (IE)", +DlgLnkPopDependent : "Menpekoa (Netscape)", +DlgLnkPopWidth : "Zabalera", +DlgLnkPopHeight : "Altuera", +DlgLnkPopLeft : "Ezkerreko Posizioa", +DlgLnkPopTop : "Goiko Posizioa", + +DlnLnkMsgNoUrl : "Mesedez URL esteka idatzi", +DlnLnkMsgNoEMail : "Mesedez ePosta helbidea idatzi", +DlnLnkMsgNoAnchor : "Mesedez aingura bat aukeratu", +DlnLnkMsgInvPopName : "Popup leihoaren izenak karaktere alfabetiko batekin hasi behar du eta eta ezin du zuriunerik izan", + +// Color Dialog +DlgColorTitle : "Kolore Aukeraketa", +DlgColorBtnClear : "Garbitu", +DlgColorHighlight : "Nabarmendu", +DlgColorSelected : "Aukeratuta", + +// Smiley Dialog +DlgSmileyTitle : "Aurpegiera Sartu", + +// Special Character Dialog +DlgSpecialCharTitle : "Karaktere Berezia Aukeratu", + +// Table Dialog +DlgTableTitle : "Taularen Ezaugarriak", +DlgTableRows : "Lerroak", +DlgTableColumns : "Zutabeak", +DlgTableBorder : "Ertzaren Zabalera", +DlgTableAlign : "Lerrokatu", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Ezkerrean", +DlgTableAlignCenter : "Erdian", +DlgTableAlignRight : "Eskuman", +DlgTableWidth : "Zabalera", +DlgTableWidthPx : "pixel", +DlgTableWidthPc : "ehuneko", +DlgTableHeight : "Altuera", +DlgTableCellSpace : "Gelaxka arteko tartea", +DlgTableCellPad : "Gelaxken betegarria", +DlgTableCaption : "Epigrafea", +DlgTableSummary : "Laburpena", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Gelaxken Ezaugarriak", +DlgCellWidth : "Zabalera", +DlgCellWidthPx : "pixel", +DlgCellWidthPc : "ehuneko", +DlgCellHeight : "Altuera", +DlgCellWordWrap : "Itzulbira", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Bai", +DlgCellWordWrapNo : "Ez", +DlgCellHorAlign : "Lerrokatu Horizontalki", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Ezkerrean", +DlgCellHorAlignCenter : "Erdian", +DlgCellHorAlignRight: "Eskuman", +DlgCellVerAlign : "Lerrokatu Bertikalki", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Goian", +DlgCellVerAlignMiddle : "Erdian", +DlgCellVerAlignBottom : "Behean", +DlgCellVerAlignBaseline : "Oinean", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Lerroak Hedatu", +DlgCellCollSpan : "Zutabeak Hedatu", +DlgCellBackColor : "Atzeko Kolorea", +DlgCellBorderColor : "Ertzako Kolorea", +DlgCellBtnSelect : "Aukeratu...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Bilatu eta Ordeztu", + +// Find Dialog +DlgFindTitle : "Bilaketa", +DlgFindFindBtn : "Bilatu", +DlgFindNotFoundMsg : "Idatzitako testua ez da topatu.", + +// Replace Dialog +DlgReplaceTitle : "Ordeztu", +DlgReplaceFindLbl : "Zer bilatu:", +DlgReplaceReplaceLbl : "Zerekin ordeztu:", +DlgReplaceCaseChk : "Maiuskula/minuskula", +DlgReplaceReplaceBtn : "Ordeztu", +DlgReplaceReplAllBtn : "Ordeztu Guztiak", +DlgReplaceWordChk : "Esaldi osoa bilatu", + +// Paste Operations / Dialog +PasteErrorCut : "Zure web nabigatzailearen segurtasun ezarpenak testuak automatikoki moztea ez dute baimentzen. Mesedez teklatua erabili ezazu (Ctrl+X).", +PasteErrorCopy : "Zure web nabigatzailearen segurtasun ezarpenak testuak automatikoki kopiatzea ez dute baimentzen. Mesedez teklatua erabili ezazu (Ctrl+C).", + +PasteAsText : "Testu Arrunta bezala Itsatsi", +PasteFromWord : "Word-etik itsatsi", + +DlgPasteMsg2 : "Mesedez teklatua erabilita (Ctrl+V) ondorego eremuan testua itsatsi eta OK sakatu.", +DlgPasteSec : "Nabigatzailearen segurtasun ezarpenak direla eta, editoreak ezin du arbela zuzenean erabili. Leiho honetan berriro itsatsi behar duzu.", +DlgPasteIgnoreFont : "Letra Motaren definizioa ezikusi", +DlgPasteRemoveStyles : "Estilo definizioak kendu", + +// Color Picker +ColorAutomatic : "Automatikoa", +ColorMoreColors : "Kolore gehiago...", + +// Document Properties +DocProps : "Dokumentuaren Ezarpenak", + +// Anchor Dialog +DlgAnchorTitle : "Ainguraren Ezaugarriak", +DlgAnchorName : "Ainguraren Izena", +DlgAnchorErrorName : "Idatzi ainguraren izena", + +// Speller Pages Dialog +DlgSpellNotInDic : "Ez dago hiztegian", +DlgSpellChangeTo : "Honekin ordezkatu", +DlgSpellBtnIgnore : "Ezikusi", +DlgSpellBtnIgnoreAll : "Denak Ezikusi", +DlgSpellBtnReplace : "Ordezkatu", +DlgSpellBtnReplaceAll : "Denak Ordezkatu", +DlgSpellBtnUndo : "Desegin", +DlgSpellNoSuggestions : "- Iradokizunik ez -", +DlgSpellProgress : "Zuzenketa ortografikoa martxan...", +DlgSpellNoMispell : "Zuzenketa ortografikoa bukatuta: Akatsik ez", +DlgSpellNoChanges : "Zuzenketa ortografikoa bukatuta: Ez da ezer aldatu", +DlgSpellOneChange : "Zuzenketa ortografikoa bukatuta: Hitz bat aldatu da", +DlgSpellManyChanges : "Zuzenketa ortografikoa bukatuta: %1 hitz aldatu dira", + +IeSpellDownload : "Zuzentzaile ortografikoa ez dago instalatuta. Deskargatu nahi duzu?", + +// Button Dialog +DlgButtonText : "Testua (Balorea)", +DlgButtonType : "Mota", +DlgButtonTypeBtn : "Botoia", +DlgButtonTypeSbm : "Bidali", +DlgButtonTypeRst : "Garbitu", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Izena", +DlgCheckboxValue : "Balorea", +DlgCheckboxSelected : "Hautatuta", + +// Form Dialog +DlgFormName : "Izena", +DlgFormAction : "Ekintza", +DlgFormMethod : "Metodoa", + +// Select Field Dialog +DlgSelectName : "Izena", +DlgSelectValue : "Balorea", +DlgSelectSize : "Tamaina", +DlgSelectLines : "lerro kopurura", +DlgSelectChkMulti : "Hautaketa anitzak baimendu", +DlgSelectOpAvail : "Aukera Eskuragarriak", +DlgSelectOpText : "Testua", +DlgSelectOpValue : "Balorea", +DlgSelectBtnAdd : "Gehitu", +DlgSelectBtnModify : "Aldatu", +DlgSelectBtnUp : "Gora", +DlgSelectBtnDown : "Behera", +DlgSelectBtnSetValue : "Aukeratutako balorea ezarri", +DlgSelectBtnDelete : "Ezabatu", + +// Textarea Dialog +DlgTextareaName : "Izena", +DlgTextareaCols : "Zutabeak", +DlgTextareaRows : "Lerroak", + +// Text Field Dialog +DlgTextName : "Izena", +DlgTextValue : "Balorea", +DlgTextCharWidth : "Zabalera", +DlgTextMaxChars : "Zenbat karaktere gehienez", +DlgTextType : "Mota", +DlgTextTypeText : "Testua", +DlgTextTypePass : "Pasahitza", + +// Hidden Field Dialog +DlgHiddenName : "Izena", +DlgHiddenValue : "Balorea", + +// Bulleted List Dialog +BulletedListProp : "Buletdun Zerrendaren Ezarpenak", +NumberedListProp : "Zenbakidun Zerrendaren Ezarpenak", +DlgLstStart : "Hasiera", +DlgLstType : "Mota", +DlgLstTypeCircle : "Zirkulua", +DlgLstTypeDisc : "Diskoa", +DlgLstTypeSquare : "Karratua", +DlgLstTypeNumbers : "Zenbakiak (1, 2, 3)", +DlgLstTypeLCase : "Letra xeheak (a, b, c)", +DlgLstTypeUCase : "Letra larriak (A, B, C)", +DlgLstTypeSRoman : "Erromatar zenbaki zeheak (i, ii, iii)", +DlgLstTypeLRoman : "Erromatar zenbaki larriak (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Orokorra", +DlgDocBackTab : "Atzealdea", +DlgDocColorsTab : "Koloreak eta Marjinak", +DlgDocMetaTab : "Meta Informazioa", + +DlgDocPageTitle : "Orriaren Izenburua", +DlgDocLangDir : "Hizkuntzaren Norabidea", +DlgDocLangDirLTR : "Ezkerretik eskumara (LTR)", +DlgDocLangDirRTL : "Eskumatik ezkerrera (RTL)", +DlgDocLangCode : "Hizkuntzaren Kodea", +DlgDocCharSet : "Karaktere Multzoaren Kodeketa", +DlgDocCharSetCE : "Erdialdeko Europakoa", +DlgDocCharSetCT : "Txinatar Tradizionala (Big5)", +DlgDocCharSetCR : "Zirilikoa", +DlgDocCharSetGR : "Grekoa", +DlgDocCharSetJP : "Japoniarra", +DlgDocCharSetKR : "Korearra", +DlgDocCharSetTR : "Turkiarra", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Mendebaldeko Europakoa", +DlgDocCharSetOther : "Beste Karaktere Multzoko Kodeketa", + +DlgDocDocType : "Document Type Goiburua", +DlgDocDocTypeOther : "Beste Document Type Goiburua", +DlgDocIncXHTML : "XHTML Ezarpenak", +DlgDocBgColor : "Atzeko Kolorea", +DlgDocBgImage : "Atzeko Irudiaren URL-a", +DlgDocBgNoScroll : "Korritze gabeko Atzealdea", +DlgDocCText : "Testua", +DlgDocCLink : "Estekak", +DlgDocCVisited : "Bisitatutako Estekak", +DlgDocCActive : "Esteka Aktiboa", +DlgDocMargins : "Orrialdearen marjinak", +DlgDocMaTop : "Goian", +DlgDocMaLeft : "Ezkerrean", +DlgDocMaRight : "Eskuman", +DlgDocMaBottom : "Behean", +DlgDocMeIndex : "Dokumentuaren Gako-hitzak (komarekin bananduta)", +DlgDocMeDescr : "Dokumentuaren Deskribapena", +DlgDocMeAuthor : "Egilea", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Aurrebista", + +// Templates Dialog +Templates : "Txantiloiak", +DlgTemplatesTitle : "Eduki Txantiloiak", +DlgTemplatesSelMsg : "Mesedez txantiloia aukeratu editorean kargatzeko
    (orain dauden edukiak galduko dira):", +DlgTemplatesLoading : "Txantiloiak kargatzen. Itxaron mesedez...", +DlgTemplatesNoTpl : "(Ez dago definitutako txantiloirik)", +DlgTemplatesReplace : "Ordeztu oraingo edukiak", + +// About Dialog +DlgAboutAboutTab : "Honi buruz", +DlgAboutBrowserInfoTab : "Nabigatzailearen Informazioa", +DlgAboutLicenseTab : "Lizentzia", +DlgAboutVersion : "bertsioa", +DlgAboutInfo : "Informazio gehiago eskuratzeko hona joan", + +// Div Dialog +DlgDivGeneralTab : "Orokorra", +DlgDivAdvancedTab : "Aurreratua", +DlgDivStyle : "Estiloa", +DlgDivInlineStyle : "Inline Estiloa", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/fa.js b/www/js/FCKeditor/editor/lang/fa.js new file mode 100644 index 0000000..bdf7faa --- /dev/null +++ b/www/js/FCKeditor/editor/lang/fa.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Persian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "rtl", + +ToolbarCollapse : "برچیدن نوارابزار", +ToolbarExpand : "گستردن نوارابزار", + +// Toolbar Items and Context Menu +Save : "ذخیره", +NewPage : "برگهٴ تازه", +Preview : "پیش‌نمایش", +Cut : "برش", +Copy : "Ú©Ù¾ÛŒ", +Paste : "چسباندن", +PasteText : "چسباندن به عنوان متن Ùساده", +PasteWord : "چسباندن از Word", +Print : "چاپ", +SelectAll : "گزینش همه", +RemoveFormat : "برداشتن Ùرمت", +InsertLinkLbl : "پیوند", +InsertLink : "گنجاندن/ویرایش Ùپیوند", +RemoveLink : "برداشتن پیوند", +VisitLink : "باز کردن پیوند", +Anchor : "گنجاندن/ویرایش Ùلنگر", +AnchorDelete : "برداشتن لنگر", +InsertImageLbl : "تصویر", +InsertImage : "گنجاندن/ویرایش Ùتصویر", +InsertFlashLbl : "Flash", +InsertFlash : "گنجاندن/ویرایش ÙFlash", +InsertTableLbl : "جدول", +InsertTable : "گنجاندن/ویرایش Ùجدول", +InsertLineLbl : "خط", +InsertLine : "گنجاندن خط ÙاÙÙ‚ÛŒ", +InsertSpecialCharLbl: "نویسهٴ ویژه", +InsertSpecialChar : "گنجاندن نویسهٴ ویژه", +InsertSmileyLbl : "خندانک", +InsertSmiley : "گنجاندن خندانک", +About : "دربارهٴ FCKeditor", +Bold : "درشت", +Italic : "خمیده", +Underline : "خط‌زیردار", +StrikeThrough : "میان‌خط", +Subscript : "زیرنویس", +Superscript : "بالانویس", +LeftJustify : "چپ‌چین", +CenterJustify : "میان‌چین", +RightJustify : "راست‌چین", +BlockJustify : "بلوک‌چین", +DecreaseIndent : "کاهش تورÙتگی", +IncreaseIndent : "اÙزایش تورÙتگی", +Blockquote : "بلوک نقل قول", +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "واچیدن", +Redo : "بازچیدن", +NumberedListLbl : "Ùهرست شماره‌دار", +NumberedList : "گنجاندن/برداشتن Ùهرست شماره‌دار", +BulletedListLbl : "Ùهرست نقطه‌ای", +BulletedList : "گنجاندن/برداشتن Ùهرست نقطه‌ای", +ShowTableBorders : "نمایش لبهٴ جدول", +ShowDetails : "نمایش جزئیات", +Style : "سبک", +FontFormat : "Ùرمت", +Font : "قلم", +FontSize : "اندازه", +TextColor : "رنگ متن", +BGColor : "رنگ پس‌زمینه", +Source : "منبع", +Find : "جستجو", +Replace : "جایگزینی", +SpellCheck : "بررسی املا", +UniversalKeyboard : "صÙحه‌کلید جهانی", +PageBreakLbl : "شکستگی Ùپایان Ùبرگه", +PageBreak : "گنجاندن شکستگی Ùپایان Ùبرگه", + +Form : "Ùرم", +Checkbox : "خانهٴ گزینه‌ای", +RadioButton : "دکمهٴ رادیویی", +TextField : "Ùیلد متنی", +Textarea : "ناحیهٴ متنی", +HiddenField : "Ùیلد پنهان", +Button : "دکمه", +SelectionField : "Ùیلد چندگزینه‌ای", +ImageButton : "دکمهٴ تصویری", + +FitWindow : "بیشینه‌سازی Ùاندازهٴ ویرایشگر", +ShowBlocks : "نمایش بلوک‌ها", + +// Context Menu +EditLink : "ویرایش پیوند", +CellCM : "سلول", +RowCM : "سطر", +ColumnCM : "ستون", +InsertRowAfter : "اÙزودن سطر بعد از", +InsertRowBefore : "اÙزودن سطر قبل از", +DeleteRows : "حذ٠سطرها", +InsertColumnAfter : "اÙزودن ستون بعد از", +InsertColumnBefore : "اÙزودن ستون قبل از", +DeleteColumns : "حذ٠ستونها", +InsertCellAfter : "اÙزودن سلول بعد از", +InsertCellBefore : "اÙزودن سلول قبل از", +DeleteCells : "حذ٠سلولها", +MergeCells : "ادغام سلولها", +MergeRight : "ادغام به راست", +MergeDown : "ادغام به پایین", +HorizontalSplitCell : "جدا کردن اÙÙ‚ÛŒ سلول", +VerticalSplitCell : "جدا کردن عمودی سلول", +TableDelete : "پاک‌کردن جدول", +CellProperties : "ویژگیهای سلول", +TableProperties : "ویژگیهای جدول", +ImageProperties : "ویژگیهای تصویر", +FlashProperties : "ویژگیهای Flash", + +AnchorProp : "ویژگیهای لنگر", +ButtonProp : "ویژگیهای دکمه", +CheckboxProp : "ویژگیهای خانهٴ گزینه‌ای", +HiddenFieldProp : "ویژگیهای Ùیلد پنهان", +RadioButtonProp : "ویژگیهای دکمهٴ رادیویی", +ImageButtonProp : "ویژگیهای دکمهٴ تصویری", +TextFieldProp : "ویژگیهای Ùیلد متنی", +SelectionFieldProp : "ویژگیهای Ùیلد چندگزینه‌ای", +TextareaProp : "ویژگیهای ناحیهٴ متنی", +FormProp : "ویژگیهای Ùرم", + +FontFormats : "نرمال;Ùرمت‌شده;آدرس;سرنویس 1;سرنویس 2;سرنویس 3;سرنویس 4;سرنویس 5;سرنویس 6;بند;(DIV)", + +// Alerts and Messages +ProcessingXHTML : "پردازش XHTML. لطÙا صبر کنید...", +Done : "انجام شد", +PasteWordConfirm : "متنی Ú©Ù‡ می‌خواهید بچسبانید به نظر می‌رسد از Word Ú©Ù¾ÛŒ شده است. آیا می‌خواهید قبل از چسباندن آن را پاک‌سازی کنید؟", +NotCompatiblePaste : "این Ùرمان برای مرورگر Internet Explorer از نگارش 5.5 یا بالاتر در دسترس است. آیا می‌خواهید بدون پاک‌سازی، متن را بچسبانید؟", +UnknownToolbarItem : "Ùقرهٴ نوارابزار ناشناخته \"%1\"", +UnknownCommand : "نام دستور ناشناخته \"%1\"", +NotImplemented : "دستور پیاده‌سازی‌نشده", +UnknownToolbarSet : "مجموعهٴ نوارابزار \"%1\" وجود ندارد", +NoActiveX : "تنظیمات امنیتی مرورگر شما ممکن است در بعضی از ویژگیهای مرورگر محدودیت ایجاد کند. شما باید گزینهٴ \"Run ActiveX controls and plug-ins\" را Ùعال کنید. ممکن است شما با خطاهایی روبرو باشید Ùˆ متوجه کمبود ویژگیهایی شوید.", +BrowseServerBlocked : "توانایی بازگشایی مرورگر منابع Ùراهم نیست. اطمینان حاصل کنید Ú©Ù‡ تمامی برنامه‌های پیشگیری از نمایش popup را از کار بازداشته‌اید.", +DialogBlocked : "توانایی بازگشایی پنجرهٴ Ú©ÙˆÚ†Ú© ÙÚ¯Ùتگو Ùراهم نیست. اطمینان حاصل کنید Ú©Ù‡ تمامی برنامه‌های پیشگیری از نمایش popup را از کار بازداشته‌اید.", +VisitLinkBlocked : "امکان بازکردن یک پنجره جدید نیست. اطمینان حاصل کنید Ú©Ù‡ تمامی برنامه‌های پیشگیری از نمایش popup را از کار بازداشته‌اید.", + +// Dialogs +DlgBtnOK : "پذیرش", +DlgBtnCancel : "انصراÙ", +DlgBtnClose : "بستن", +DlgBtnBrowseServer : "Ùهرست‌نمایی سرور", +DlgAdvancedTag : "پیشرÙته", +DlgOpOther : "<غیره>", +DlgInfoTab : "اطلاعات", +DlgAlertUrl : "لطÙاً URL را بنویسید", + +// General Dialogs Labels +DlgGenNotSet : "<تعین‌نشده>", +DlgGenId : "شناسه", +DlgGenLangDir : "جهت‌نمای زبان", +DlgGenLangDirLtr : "Ú†Ù¾ به راست (LTR)", +DlgGenLangDirRtl : "راست به Ú†Ù¾ (RTL)", +DlgGenLangCode : "کد زبان", +DlgGenAccessKey : "کلید دستیابی", +DlgGenName : "نام", +DlgGenTabIndex : "نمایهٴ دسترسی با Tab", +DlgGenLongDescr : "URL توصی٠طولانی", +DlgGenClass : "کلاسهای شیوه‌نامه(Stylesheet)", +DlgGenTitle : "عنوان Ú©Ù…Ú©ÛŒ", +DlgGenContType : "نوع محتوای Ú©Ù…Ú©ÛŒ", +DlgGenLinkCharset : "نویسه‌گان منبع Ùپیوندشده", +DlgGenStyle : "شیوه(style)", + +// Image Dialog +DlgImgTitle : "ویژگیهای تصویر", +DlgImgInfoTab : "اطلاعات تصویر", +DlgImgBtnUpload : "به سرور بÙرست", +DlgImgURL : "URL", +DlgImgUpload : "انتقال به سرور", +DlgImgAlt : "متن جایگزین", +DlgImgWidth : "پهنا", +DlgImgHeight : "درازا", +DlgImgLockRatio : "Ù‚Ùل‌کردن Ùنسبت", +DlgBtnResetSize : "بازنشانی اندازه", +DlgImgBorder : "لبه", +DlgImgHSpace : "Ùاصلهٴ اÙÙ‚ÛŒ", +DlgImgVSpace : "Ùاصلهٴ عمودی", +DlgImgAlign : "چینش", +DlgImgAlignLeft : "Ú†Ù¾", +DlgImgAlignAbsBottom: "پائین مطلق", +DlgImgAlignAbsMiddle: "وسط مطلق", +DlgImgAlignBaseline : "خط‌پایه", +DlgImgAlignBottom : "پائین", +DlgImgAlignMiddle : "وسط", +DlgImgAlignRight : "راست", +DlgImgAlignTextTop : "متن بالا", +DlgImgAlignTop : "بالا", +DlgImgPreview : "پیش‌نمایش", +DlgImgAlertUrl : "لطÙا URL تصویر را بنویسید", +DlgImgLinkTab : "پیوند", + +// Flash Dialog +DlgFlashTitle : "ویژگیهای Flash", +DlgFlashChkPlay : "آغاز Ùخودکار", +DlgFlashChkLoop : "اجرای پیاپی", +DlgFlashChkMenu : "دردسترس‌بودن منوی Flash", +DlgFlashScale : "مقیاس", +DlgFlashScaleAll : "نمایش همه", +DlgFlashScaleNoBorder : "بدون کران", +DlgFlashScaleFit : "جایگیری کامل", + +// Link Dialog +DlgLnkWindowTitle : "پیوند", +DlgLnkInfoTab : "اطلاعات پیوند", +DlgLnkTargetTab : "مقصد", + +DlgLnkType : "نوع پیوند", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "لنگر در همین صÙحه", +DlgLnkTypeEMail : "پست الکترونیکی", +DlgLnkProto : "پروتکل", +DlgLnkProtoOther : "<دیگر>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "یک لنگر برگزینید", +DlgLnkAnchorByName : "با نام لنگر", +DlgLnkAnchorById : "با شناسهٴ المان", +DlgLnkNoAnchors : "(در این سند لنگری دردسترس نیست)", +DlgLnkEMail : "نشانی پست الکترونیکی", +DlgLnkEMailSubject : "موضوع پیام", +DlgLnkEMailBody : "متن پیام", +DlgLnkUpload : "انتقال به سرور", +DlgLnkBtnUpload : "به سرور بÙرست", + +DlgLnkTarget : "مقصد", +DlgLnkTargetFrame : "<Ùریم>", +DlgLnkTargetPopup : "<پنجرهٴ پاپاپ>", +DlgLnkTargetBlank : "پنجرهٴ دیگر (_blank)", +DlgLnkTargetParent : "پنجرهٴ والد (_parent)", +DlgLnkTargetSelf : "همان پنجره (_self)", +DlgLnkTargetTop : "بالاترین پنجره (_top)", +DlgLnkTargetFrameName : "نام Ùریم مقصد", +DlgLnkPopWinName : "نام پنجرهٴ پاپاپ", +DlgLnkPopWinFeat : "ویژگیهای پنجرهٴ پاپاپ", +DlgLnkPopResize : "قابل تغییر اندازه", +DlgLnkPopLocation : "نوار موقعیت", +DlgLnkPopMenu : "نوار منو", +DlgLnkPopScroll : "میله‌های پیمایش", +DlgLnkPopStatus : "نوار وضعیت", +DlgLnkPopToolbar : "نوارابزار", +DlgLnkPopFullScrn : "تمام‌صÙحه (IE)", +DlgLnkPopDependent : "وابسته (Netscape)", +DlgLnkPopWidth : "پهنا", +DlgLnkPopHeight : "درازا", +DlgLnkPopLeft : "موقعیت ÙÚ†Ù¾", +DlgLnkPopTop : "موقعیت Ùبالا", + +DlnLnkMsgNoUrl : "لطÙا URL پیوند را بنویسید", +DlnLnkMsgNoEMail : "لطÙا نشانی پست الکترونیکی را بنویسید", +DlnLnkMsgNoAnchor : "لطÙا لنگری را برگزینید", +DlnLnkMsgInvPopName : "نام پنجرهٴ پاپاپ باید با یک نویسهٴ الÙبایی آغاز گردد Ùˆ نباید Ùاصله‌های خالی در آن باشند", + +// Color Dialog +DlgColorTitle : "گزینش رنگ", +DlgColorBtnClear : "پاک‌کردن", +DlgColorHighlight : "نمونه", +DlgColorSelected : "برگزیده", + +// Smiley Dialog +DlgSmileyTitle : "گنجاندن خندانک", + +// Special Character Dialog +DlgSpecialCharTitle : "گزینش نویسهٴ‌ویژه", + +// Table Dialog +DlgTableTitle : "ویژگیهای جدول", +DlgTableRows : "سطرها", +DlgTableColumns : "ستونها", +DlgTableBorder : "اندازهٴ لبه", +DlgTableAlign : "چینش", +DlgTableAlignNotSet : "<تعین‌نشده>", +DlgTableAlignLeft : "Ú†Ù¾", +DlgTableAlignCenter : "وسط", +DlgTableAlignRight : "راست", +DlgTableWidth : "پهنا", +DlgTableWidthPx : "پیکسل", +DlgTableWidthPc : "درصد", +DlgTableHeight : "درازا", +DlgTableCellSpace : "Ùاصلهٴ میان سلولها", +DlgTableCellPad : "Ùاصلهٴ پرشده در سلول", +DlgTableCaption : "عنوان", +DlgTableSummary : "خلاصه", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "ویژگیهای سلول", +DlgCellWidth : "پهنا", +DlgCellWidthPx : "پیکسل", +DlgCellWidthPc : "درصد", +DlgCellHeight : "درازا", +DlgCellWordWrap : "شکستن واژه‌ها", +DlgCellWordWrapNotSet : "<تعین‌نشده>", +DlgCellWordWrapYes : "بله", +DlgCellWordWrapNo : "خیر", +DlgCellHorAlign : "چینش ÙاÙÙ‚ÛŒ", +DlgCellHorAlignNotSet : "<تعین‌نشده>", +DlgCellHorAlignLeft : "Ú†Ù¾", +DlgCellHorAlignCenter : "وسط", +DlgCellHorAlignRight: "راست", +DlgCellVerAlign : "چینش Ùعمودی", +DlgCellVerAlignNotSet : "<تعین‌نشده>", +DlgCellVerAlignTop : "بالا", +DlgCellVerAlignMiddle : "میان", +DlgCellVerAlignBottom : "پائین", +DlgCellVerAlignBaseline : "خط‌پایه", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "گستردگی سطرها", +DlgCellCollSpan : "گستردگی ستونها", +DlgCellBackColor : "رنگ پس‌زمینه", +DlgCellBorderColor : "رنگ لبه", +DlgCellBtnSelect : "برگزینید...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "جستجو Ùˆ جایگزینی", + +// Find Dialog +DlgFindTitle : "یاÙتن", +DlgFindFindBtn : "یاÙتن", +DlgFindNotFoundMsg : "متن موردنظر یاÙت نشد.", + +// Replace Dialog +DlgReplaceTitle : "جایگزینی", +DlgReplaceFindLbl : "چه‌چیز را می‌یابید:", +DlgReplaceReplaceLbl : "جایگزینی با:", +DlgReplaceCaseChk : "همسانی در بزرگی Ùˆ Ú©ÙˆÚ†Ú©ÛŒ نویسه‌ها", +DlgReplaceReplaceBtn : "جایگزینی", +DlgReplaceReplAllBtn : "جایگزینی همهٴ یاÙته‌ها", +DlgReplaceWordChk : "همسانی با واژهٴ کامل", + +// Paste Operations / Dialog +PasteErrorCut : "تنظیمات امنیتی مرورگر شما اجازه نمی‌دهد Ú©Ù‡ ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطÙا با دکمه‌های صÙحه‌کلید این کار را انجام دهید (Ctrl+X).", +PasteErrorCopy : "تنظیمات امنیتی مرورگر شما اجازه نمی‌دهد Ú©Ù‡ ویرایشگر به طور خودکار عملکردهای کپی‌کردن را انجام دهد. لطÙا با دکمه‌های صÙحه‌کلید این کار را انجام دهید (Ctrl+C).", + +PasteAsText : "چسباندن به عنوان متن Ùساده", +PasteFromWord : "چسباندن از Word", + +DlgPasteMsg2 : "لطÙا متن را با کلیدهای (Ctrl+V) در این جعبهٴ متنی بچسبانید Ùˆ پذیرش را بزنید.", +DlgPasteSec : "به خاطر تنظیمات امنیتی مرورگر شما، ویرایشگر نمی‌تواند دسترسی مستقیم به داده‌های clipboard داشته باشد. شما باید دوباره آنرا در این پنجره بچسبانید.", +DlgPasteIgnoreFont : "چشم‌پوشی از تعاری٠نوع قلم", +DlgPasteRemoveStyles : "چشم‌پوشی از تعاری٠سبک (style)", + +// Color Picker +ColorAutomatic : "خودکار", +ColorMoreColors : "رنگهای بیشتر...", + +// Document Properties +DocProps : "ویژگیهای سند", + +// Anchor Dialog +DlgAnchorTitle : "ویژگیهای لنگر", +DlgAnchorName : "نام لنگر", +DlgAnchorErrorName : "لطÙا نام لنگر را بنویسید", + +// Speller Pages Dialog +DlgSpellNotInDic : "در واژه‌نامه یاÙت نشد", +DlgSpellChangeTo : "تغییر به", +DlgSpellBtnIgnore : "چشم‌پوشی", +DlgSpellBtnIgnoreAll : "چشم‌پوشی همه", +DlgSpellBtnReplace : "جایگزینی", +DlgSpellBtnReplaceAll : "جایگزینی همه", +DlgSpellBtnUndo : "واچینش", +DlgSpellNoSuggestions : "- پیشنهادی نیست -", +DlgSpellProgress : "بررسی املا در حال انجام...", +DlgSpellNoMispell : "بررسی املا انجام شد. هیچ غلط‌املائی یاÙت نشد", +DlgSpellNoChanges : "بررسی املا انجام شد. هیچ واژه‌ای تغییر نیاÙت", +DlgSpellOneChange : "بررسی املا انجام شد. یک واژه تغییر یاÙت", +DlgSpellManyChanges : "بررسی املا انجام شد. %1 واژه تغییر یاÙت", + +IeSpellDownload : "بررسی‌کنندهٴ املا نصب نشده است. آیا می‌خواهید آن را هم‌اکنون دریاÙت کنید؟", + +// Button Dialog +DlgButtonText : "متن (مقدار)", +DlgButtonType : "نوع", +DlgButtonTypeBtn : "دکمه", +DlgButtonTypeSbm : "Submit", +DlgButtonTypeRst : "بازنشانی (Reset)", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "نام", +DlgCheckboxValue : "مقدار", +DlgCheckboxSelected : "برگزیده", + +// Form Dialog +DlgFormName : "نام", +DlgFormAction : "رویداد", +DlgFormMethod : "متد", + +// Select Field Dialog +DlgSelectName : "نام", +DlgSelectValue : "مقدار", +DlgSelectSize : "اندازه", +DlgSelectLines : "خطوط", +DlgSelectChkMulti : "گزینش چندگانه Ùراهم باشد", +DlgSelectOpAvail : "گزینه‌های دردسترس", +DlgSelectOpText : "متن", +DlgSelectOpValue : "مقدار", +DlgSelectBtnAdd : "اÙزودن", +DlgSelectBtnModify : "ویرایش", +DlgSelectBtnUp : "بالا", +DlgSelectBtnDown : "پائین", +DlgSelectBtnSetValue : "تنظیم به عنوان مقدار Ùبرگزیده", +DlgSelectBtnDelete : "پاک‌کردن", + +// Textarea Dialog +DlgTextareaName : "نام", +DlgTextareaCols : "ستونها", +DlgTextareaRows : "سطرها", + +// Text Field Dialog +DlgTextName : "نام", +DlgTextValue : "مقدار", +DlgTextCharWidth : "پهنای نویسه", +DlgTextMaxChars : "بیشینهٴ نویسه‌ها", +DlgTextType : "نوع", +DlgTextTypeText : "متن", +DlgTextTypePass : "گذرواژه", + +// Hidden Field Dialog +DlgHiddenName : "نام", +DlgHiddenValue : "مقدار", + +// Bulleted List Dialog +BulletedListProp : "ویژگیهای Ùهرست نقطه‌ای", +NumberedListProp : "ویژگیهای Ùهرست شماره‌دار", +DlgLstStart : "آغاز", +DlgLstType : "نوع", +DlgLstTypeCircle : "دایره", +DlgLstTypeDisc : "قرص", +DlgLstTypeSquare : "چهارگوش", +DlgLstTypeNumbers : "شماره‌ها (1ØŒ 2ØŒ 3)", +DlgLstTypeLCase : "نویسه‌های Ú©ÙˆÚ†Ú© (aØŒ bØŒ c)", +DlgLstTypeUCase : "نویسه‌های بزرگ (AØŒ BØŒ C)", +DlgLstTypeSRoman : "شمارگان رومی Ú©ÙˆÚ†Ú© (iØŒ iiØŒ iii)", +DlgLstTypeLRoman : "شمارگان رومی بزرگ (IØŒ IIØŒ III)", + +// Document Properties Dialog +DlgDocGeneralTab : "عمومی", +DlgDocBackTab : "پس‌زمینه", +DlgDocColorsTab : "رنگها Ùˆ حاشیه‌ها", +DlgDocMetaTab : "Ùراداده", + +DlgDocPageTitle : "عنوان صÙحه", +DlgDocLangDir : "جهت زبان", +DlgDocLangDirLTR : "Ú†Ù¾ به راست (LTR(", +DlgDocLangDirRTL : "راست به Ú†Ù¾ (RTL(", +DlgDocLangCode : "کد زبان", +DlgDocCharSet : "رمزگذاری نویسه‌گان", +DlgDocCharSetCE : "اروپای مرکزی", +DlgDocCharSetCT : "چینی رسمی (Big5)", +DlgDocCharSetCR : "سیریلیک", +DlgDocCharSetGR : "یونانی", +DlgDocCharSetJP : "ژاپنی", +DlgDocCharSetKR : "کره‌ای", +DlgDocCharSetTR : "ترکی", +DlgDocCharSetUN : "یونیکÙد (UTF-8)", +DlgDocCharSetWE : "اروپای غربی", +DlgDocCharSetOther : "رمزگذاری نویسه‌گان دیگر", + +DlgDocDocType : "عنوان نوع سند", +DlgDocDocTypeOther : "عنوان نوع سند دیگر", +DlgDocIncXHTML : "شامل تعاری٠XHTML", +DlgDocBgColor : "رنگ پس‌زمینه", +DlgDocBgImage : "URL تصویر پس‌زمینه", +DlgDocBgNoScroll : "پس‌زمینهٴ پیمایش‌ناپذیر", +DlgDocCText : "متن", +DlgDocCLink : "پیوند", +DlgDocCVisited : "پیوند مشاهده‌شده", +DlgDocCActive : "پیوند Ùعال", +DlgDocMargins : "حاشیه‌های صÙحه", +DlgDocMaTop : "بالا", +DlgDocMaLeft : "Ú†Ù¾", +DlgDocMaRight : "راست", +DlgDocMaBottom : "پایین", +DlgDocMeIndex : "کلیدواژگان نمایه‌گذاری سند (با کاما جدا شوند)", +DlgDocMeDescr : "توصی٠سند", +DlgDocMeAuthor : "نویسنده", +DlgDocMeCopy : "کپی‌رایت", +DlgDocPreview : "پیش‌نمایش", + +// Templates Dialog +Templates : "الگوها", +DlgTemplatesTitle : "الگوهای محتویات", +DlgTemplatesSelMsg : "لطÙا الگوی موردنظر را برای بازکردن در ویرایشگر برگزینید
    (محتویات کنونی از دست خواهند رÙت):", +DlgTemplatesLoading : "بارگذاری Ùهرست الگوها. لطÙا صبر کنید...", +DlgTemplatesNoTpl : "(الگوئی تعری٠نشده است)", +DlgTemplatesReplace : "محتویات کنونی جایگزین شوند", + +// About Dialog +DlgAboutAboutTab : "درباره", +DlgAboutBrowserInfoTab : "اطلاعات مرورگر", +DlgAboutLicenseTab : "گواهینامه", +DlgAboutVersion : "نگارش", +DlgAboutInfo : "برای آگاهی بیشتر به این نشانی بروید", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/fi.js b/www/js/FCKeditor/editor/lang/fi.js new file mode 100644 index 0000000..da5d7ba --- /dev/null +++ b/www/js/FCKeditor/editor/lang/fi.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Finnish language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Piilota työkalurivi", +ToolbarExpand : "Näytä työkalurivi", + +// Toolbar Items and Context Menu +Save : "Tallenna", +NewPage : "Tyhjennä", +Preview : "Esikatsele", +Cut : "Leikkaa", +Copy : "Kopioi", +Paste : "Liitä", +PasteText : "Liitä tekstinä", +PasteWord : "Liitä Wordista", +Print : "Tulosta", +SelectAll : "Valitse kaikki", +RemoveFormat : "Poista muotoilu", +InsertLinkLbl : "Linkki", +InsertLink : "Lisää linkki/muokkaa linkkiä", +RemoveLink : "Poista linkki", +VisitLink : "Open Link", //MISSING +Anchor : "Lisää ankkuri/muokkaa ankkuria", +AnchorDelete : "Poista ankkuri", +InsertImageLbl : "Kuva", +InsertImage : "Lisää kuva/muokkaa kuvaa", +InsertFlashLbl : "Flash", +InsertFlash : "Lisää/muokkaa Flashia", +InsertTableLbl : "Taulu", +InsertTable : "Lisää taulu/muokkaa taulua", +InsertLineLbl : "Murtoviiva", +InsertLine : "Lisää murtoviiva", +InsertSpecialCharLbl: "Erikoismerkki", +InsertSpecialChar : "Lisää erikoismerkki", +InsertSmileyLbl : "Hymiö", +InsertSmiley : "Lisää hymiö", +About : "FCKeditorista", +Bold : "Lihavoitu", +Italic : "Kursivoitu", +Underline : "Alleviivattu", +StrikeThrough : "Yliviivattu", +Subscript : "Alaindeksi", +Superscript : "Yläindeksi", +LeftJustify : "Tasaa vasemmat reunat", +CenterJustify : "Keskitä", +RightJustify : "Tasaa oikeat reunat", +BlockJustify : "Tasaa molemmat reunat", +DecreaseIndent : "Pienennä sisennystä", +IncreaseIndent : "Suurenna sisennystä", +Blockquote : "Lainaus", +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Kumoa", +Redo : "Toista", +NumberedListLbl : "Numerointi", +NumberedList : "Lisää/poista numerointi", +BulletedListLbl : "Luottelomerkit", +BulletedList : "Lisää/poista luottelomerkit", +ShowTableBorders : "Näytä taulun rajat", +ShowDetails : "Näytä muotoilu", +Style : "Tyyli", +FontFormat : "Muotoilu", +Font : "Fontti", +FontSize : "Koko", +TextColor : "Tekstiväri", +BGColor : "Taustaväri", +Source : "Koodi", +Find : "Etsi", +Replace : "Korvaa", +SpellCheck : "Tarkista oikeinkirjoitus", +UniversalKeyboard : "Universaali näppäimistö", +PageBreakLbl : "Sivun vaihto", +PageBreak : "Lisää sivun vaihto", + +Form : "Lomake", +Checkbox : "Valintaruutu", +RadioButton : "Radiopainike", +TextField : "Tekstikenttä", +Textarea : "Tekstilaatikko", +HiddenField : "Piilokenttä", +Button : "Painike", +SelectionField : "Valintakenttä", +ImageButton : "Kuvapainike", + +FitWindow : "Suurenna editori koko ikkunaan", +ShowBlocks : "Näytä elementit", + +// Context Menu +EditLink : "Muokkaa linkkiä", +CellCM : "Solu", +RowCM : "Rivi", +ColumnCM : "Sarake", +InsertRowAfter : "Lisää rivi alapuolelle", +InsertRowBefore : "Lisää rivi yläpuolelle", +DeleteRows : "Poista rivit", +InsertColumnAfter : "Lisää sarake oikealle", +InsertColumnBefore : "Lisää sarake vasemmalle", +DeleteColumns : "Poista sarakkeet", +InsertCellAfter : "Lisää solu perään", +InsertCellBefore : "Lisää solu eteen", +DeleteCells : "Poista solut", +MergeCells : "Yhdistä solut", +MergeRight : "Yhdistä oikealla olevan kanssa", +MergeDown : "Yhdistä alla olevan kanssa", +HorizontalSplitCell : "Jaa solu vaakasuunnassa", +VerticalSplitCell : "Jaa solu pystysuunnassa", +TableDelete : "Poista taulu", +CellProperties : "Solun ominaisuudet", +TableProperties : "Taulun ominaisuudet", +ImageProperties : "Kuvan ominaisuudet", +FlashProperties : "Flash ominaisuudet", + +AnchorProp : "Ankkurin ominaisuudet", +ButtonProp : "Painikkeen ominaisuudet", +CheckboxProp : "Valintaruudun ominaisuudet", +HiddenFieldProp : "Piilokentän ominaisuudet", +RadioButtonProp : "Radiopainikkeen ominaisuudet", +ImageButtonProp : "Kuvapainikkeen ominaisuudet", +TextFieldProp : "Tekstikentän ominaisuudet", +SelectionFieldProp : "Valintakentän ominaisuudet", +TextareaProp : "Tekstilaatikon ominaisuudet", +FormProp : "Lomakkeen ominaisuudet", + +FontFormats : "Normaali;Muotoiltu;Osoite;Otsikko 1;Otsikko 2;Otsikko 3;Otsikko 4;Otsikko 5;Otsikko 6", + +// Alerts and Messages +ProcessingXHTML : "Prosessoidaan XHTML:ää. Odota hetki...", +Done : "Valmis", +PasteWordConfirm : "Teksti, jonka haluat liittää, näyttää olevan kopioitu Wordista. Haluatko puhdistaa sen ennen liittämistä?", +NotCompatiblePaste : "Tämä komento toimii vain Internet Explorer 5.5:ssa tai uudemmassa. Haluatko liittää ilman puhdistusta?", +UnknownToolbarItem : "Tuntemanton työkalu \"%1\"", +UnknownCommand : "Tuntematon komento \"%1\"", +NotImplemented : "Komentoa ei ole liitetty sovellukseen", +UnknownToolbarSet : "Työkalukokonaisuus \"%1\" ei ole olemassa", +NoActiveX : "Selaimesi turvallisuusasetukset voivat rajoittaa joitain editorin ominaisuuksia. Sinun pitää ottaa käyttöön asetuksista \"Suorita ActiveX komponentit ja -plugin-laajennukset\". Saatat kohdata virheitä ja huomata puuttuvia ominaisuuksia.", +BrowseServerBlocked : "Resurssiselainta ei voitu avata. Varmista, että ponnahdusikkunoiden estäjät eivät ole päällä.", +DialogBlocked : "Apuikkunaa ei voitu avaata. Varmista, että ponnahdusikkunoiden estäjät eivät ole päällä.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Peruuta", +DlgBtnClose : "Sulje", +DlgBtnBrowseServer : "Selaa palvelinta", +DlgAdvancedTag : "Lisäominaisuudet", +DlgOpOther : "Muut", +DlgInfoTab : "Info", +DlgAlertUrl : "Lisää URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Tunniste", +DlgGenLangDir : "Kielen suunta", +DlgGenLangDirLtr : "Vasemmalta oikealle (LTR)", +DlgGenLangDirRtl : "Oikealta vasemmalle (RTL)", +DlgGenLangCode : "Kielikoodi", +DlgGenAccessKey : "Pikanäppäin", +DlgGenName : "Nimi", +DlgGenTabIndex : "Tabulaattori indeksi", +DlgGenLongDescr : "Pitkän kuvauksen URL", +DlgGenClass : "Tyyliluokat", +DlgGenTitle : "Avustava otsikko", +DlgGenContType : "Avustava sisällön tyyppi", +DlgGenLinkCharset : "Linkitetty kirjaimisto", +DlgGenStyle : "Tyyli", + +// Image Dialog +DlgImgTitle : "Kuvan ominaisuudet", +DlgImgInfoTab : "Kuvan tiedot", +DlgImgBtnUpload : "Lähetä palvelimelle", +DlgImgURL : "Osoite", +DlgImgUpload : "Lisää kuva", +DlgImgAlt : "Vaihtoehtoinen teksti", +DlgImgWidth : "Leveys", +DlgImgHeight : "Korkeus", +DlgImgLockRatio : "Lukitse suhteet", +DlgBtnResetSize : "Alkuperäinen koko", +DlgImgBorder : "Raja", +DlgImgHSpace : "Vaakatila", +DlgImgVSpace : "Pystytila", +DlgImgAlign : "Kohdistus", +DlgImgAlignLeft : "Vasemmalle", +DlgImgAlignAbsBottom: "Aivan alas", +DlgImgAlignAbsMiddle: "Aivan keskelle", +DlgImgAlignBaseline : "Alas (teksti)", +DlgImgAlignBottom : "Alas", +DlgImgAlignMiddle : "Keskelle", +DlgImgAlignRight : "Oikealle", +DlgImgAlignTextTop : "Ylös (teksti)", +DlgImgAlignTop : "Ylös", +DlgImgPreview : "Esikatselu", +DlgImgAlertUrl : "Kirjoita kuvan osoite (URL)", +DlgImgLinkTab : "Linkki", + +// Flash Dialog +DlgFlashTitle : "Flash ominaisuudet", +DlgFlashChkPlay : "Automaattinen käynnistys", +DlgFlashChkLoop : "Toisto", +DlgFlashChkMenu : "Näytä Flash-valikko", +DlgFlashScale : "Levitä", +DlgFlashScaleAll : "Näytä kaikki", +DlgFlashScaleNoBorder : "Ei rajaa", +DlgFlashScaleFit : "Tarkka koko", + +// Link Dialog +DlgLnkWindowTitle : "Linkki", +DlgLnkInfoTab : "Linkin tiedot", +DlgLnkTargetTab : "Kohde", + +DlgLnkType : "Linkkityyppi", +DlgLnkTypeURL : "Osoite", +DlgLnkTypeAnchor : "Ankkuri tässä sivussa", +DlgLnkTypeEMail : "Sähköposti", +DlgLnkProto : "Protokolla", +DlgLnkProtoOther : "", +DlgLnkURL : "Osoite", +DlgLnkAnchorSel : "Valitse ankkuri", +DlgLnkAnchorByName : "Ankkurin nimen mukaan", +DlgLnkAnchorById : "Ankkurin ID:n mukaan", +DlgLnkNoAnchors : "(Ei ankkureita tässä dokumentissa)", +DlgLnkEMail : "Sähköpostiosoite", +DlgLnkEMailSubject : "Aihe", +DlgLnkEMailBody : "Viesti", +DlgLnkUpload : "Lisää tiedosto", +DlgLnkBtnUpload : "Lähetä palvelimelle", + +DlgLnkTarget : "Kohde", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Uusi ikkuna (_blank)", +DlgLnkTargetParent : "Emoikkuna (_parent)", +DlgLnkTargetSelf : "Sama ikkuna (_self)", +DlgLnkTargetTop : "Päällimmäisin ikkuna (_top)", +DlgLnkTargetFrameName : "Kohdekehyksen nimi", +DlgLnkPopWinName : "Popup ikkunan nimi", +DlgLnkPopWinFeat : "Popup ikkunan ominaisuudet", +DlgLnkPopResize : "Venytettävä", +DlgLnkPopLocation : "Osoiterivi", +DlgLnkPopMenu : "Valikkorivi", +DlgLnkPopScroll : "Vierityspalkit", +DlgLnkPopStatus : "Tilarivi", +DlgLnkPopToolbar : "Vakiopainikkeet", +DlgLnkPopFullScrn : "Täysi ikkuna (IE)", +DlgLnkPopDependent : "Riippuva (Netscape)", +DlgLnkPopWidth : "Leveys", +DlgLnkPopHeight : "Korkeus", +DlgLnkPopLeft : "Vasemmalta (px)", +DlgLnkPopTop : "Ylhäältä (px)", + +DlnLnkMsgNoUrl : "Linkille on kirjoitettava URL", +DlnLnkMsgNoEMail : "Kirjoita sähköpostiosoite", +DlnLnkMsgNoAnchor : "Valitse ankkuri", +DlnLnkMsgInvPopName : "Popup-ikkunan nimi pitää alkaa aakkosella ja ei saa sisältää välejä", + +// Color Dialog +DlgColorTitle : "Valitse väri", +DlgColorBtnClear : "Tyhjennä", +DlgColorHighlight : "Kohdalla", +DlgColorSelected : "Valittu", + +// Smiley Dialog +DlgSmileyTitle : "Lisää hymiö", + +// Special Character Dialog +DlgSpecialCharTitle : "Valitse erikoismerkki", + +// Table Dialog +DlgTableTitle : "Taulun ominaisuudet", +DlgTableRows : "Rivit", +DlgTableColumns : "Sarakkeet", +DlgTableBorder : "Rajan paksuus", +DlgTableAlign : "Kohdistus", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Vasemmalle", +DlgTableAlignCenter : "Keskelle", +DlgTableAlignRight : "Oikealle", +DlgTableWidth : "Leveys", +DlgTableWidthPx : "pikseliä", +DlgTableWidthPc : "prosenttia", +DlgTableHeight : "Korkeus", +DlgTableCellSpace : "Solujen väli", +DlgTableCellPad : "Solujen sisennys", +DlgTableCaption : "Otsikko", +DlgTableSummary : "Yhteenveto", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Solun ominaisuudet", +DlgCellWidth : "Leveys", +DlgCellWidthPx : "pikseliä", +DlgCellWidthPc : "prosenttia", +DlgCellHeight : "Korkeus", +DlgCellWordWrap : "Tekstikierrätys", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Kyllä", +DlgCellWordWrapNo : "Ei", +DlgCellHorAlign : "Vaakakohdistus", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Vasemmalle", +DlgCellHorAlignCenter : "Keskelle", +DlgCellHorAlignRight: "Oikealle", +DlgCellVerAlign : "Pystykohdistus", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Ylös", +DlgCellVerAlignMiddle : "Keskelle", +DlgCellVerAlignBottom : "Alas", +DlgCellVerAlignBaseline : "Tekstin alas", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Rivin jatkuvuus", +DlgCellCollSpan : "Sarakkeen jatkuvuus", +DlgCellBackColor : "Taustaväri", +DlgCellBorderColor : "Rajan väri", +DlgCellBtnSelect : "Valitse...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Etsi ja korvaa", + +// Find Dialog +DlgFindTitle : "Etsi", +DlgFindFindBtn : "Etsi", +DlgFindNotFoundMsg : "Etsittyä tekstiä ei löytynyt.", + +// Replace Dialog +DlgReplaceTitle : "Korvaa", +DlgReplaceFindLbl : "Etsi mitä:", +DlgReplaceReplaceLbl : "Korvaa tällä:", +DlgReplaceCaseChk : "Sama kirjainkoko", +DlgReplaceReplaceBtn : "Korvaa", +DlgReplaceReplAllBtn : "Korvaa kaikki", +DlgReplaceWordChk : "Koko sana", + +// Paste Operations / Dialog +PasteErrorCut : "Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).", +PasteErrorCopy : "Selaimesi turva-asetukset eivät salli editorin toteuttaa kopioimista. Käytä näppäimistöä kopioimiseen (Ctrl+C).", + +PasteAsText : "Liitä tekstinä", +PasteFromWord : "Liitä Wordista", + +DlgPasteMsg2 : "Liitä painamalla (Ctrl+V) ja painamalla OK.", +DlgPasteSec : "Selaimesi turva-asetukset eivät salli editorin käyttää leikepöytää suoraan. Sinun pitää suorittaa liittäminen tässä ikkunassa.", +DlgPasteIgnoreFont : "Jätä huomioimatta fonttimääritykset", +DlgPasteRemoveStyles : "Poista tyylimääritykset", + +// Color Picker +ColorAutomatic : "Automaattinen", +ColorMoreColors : "Lisää värejä...", + +// Document Properties +DocProps : "Dokumentin ominaisuudet", + +// Anchor Dialog +DlgAnchorTitle : "Ankkurin ominaisuudet", +DlgAnchorName : "Nimi", +DlgAnchorErrorName : "Ankkurille on kirjoitettava nimi", + +// Speller Pages Dialog +DlgSpellNotInDic : "Ei sanakirjassa", +DlgSpellChangeTo : "Vaihda", +DlgSpellBtnIgnore : "Jätä huomioimatta", +DlgSpellBtnIgnoreAll : "Jätä kaikki huomioimatta", +DlgSpellBtnReplace : "Korvaa", +DlgSpellBtnReplaceAll : "Korvaa kaikki", +DlgSpellBtnUndo : "Kumoa", +DlgSpellNoSuggestions : "Ei ehdotuksia", +DlgSpellProgress : "Tarkistus käynnissä...", +DlgSpellNoMispell : "Tarkistus valmis: Ei virheitä", +DlgSpellNoChanges : "Tarkistus valmis: Yhtään sanaa ei muutettu", +DlgSpellOneChange : "Tarkistus valmis: Yksi sana muutettiin", +DlgSpellManyChanges : "Tarkistus valmis: %1 sanaa muutettiin", + +IeSpellDownload : "Oikeinkirjoituksen tarkistusta ei ole asennettu. Haluatko ladata sen nyt?", + +// Button Dialog +DlgButtonText : "Teksti (arvo)", +DlgButtonType : "Tyyppi", +DlgButtonTypeBtn : "Painike", +DlgButtonTypeSbm : "Lähetä", +DlgButtonTypeRst : "Tyhjennä", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nimi", +DlgCheckboxValue : "Arvo", +DlgCheckboxSelected : "Valittu", + +// Form Dialog +DlgFormName : "Nimi", +DlgFormAction : "Toiminto", +DlgFormMethod : "Tapa", + +// Select Field Dialog +DlgSelectName : "Nimi", +DlgSelectValue : "Arvo", +DlgSelectSize : "Koko", +DlgSelectLines : "Rivit", +DlgSelectChkMulti : "Salli usea valinta", +DlgSelectOpAvail : "Ominaisuudet", +DlgSelectOpText : "Teksti", +DlgSelectOpValue : "Arvo", +DlgSelectBtnAdd : "Lisää", +DlgSelectBtnModify : "Muuta", +DlgSelectBtnUp : "Ylös", +DlgSelectBtnDown : "Alas", +DlgSelectBtnSetValue : "Aseta valituksi", +DlgSelectBtnDelete : "Poista", + +// Textarea Dialog +DlgTextareaName : "Nimi", +DlgTextareaCols : "Sarakkeita", +DlgTextareaRows : "Rivejä", + +// Text Field Dialog +DlgTextName : "Nimi", +DlgTextValue : "Arvo", +DlgTextCharWidth : "Leveys", +DlgTextMaxChars : "Maksimi merkkimäärä", +DlgTextType : "Tyyppi", +DlgTextTypeText : "Teksti", +DlgTextTypePass : "Salasana", + +// Hidden Field Dialog +DlgHiddenName : "Nimi", +DlgHiddenValue : "Arvo", + +// Bulleted List Dialog +BulletedListProp : "Luettelon ominaisuudet", +NumberedListProp : "Numeroinnin ominaisuudet", +DlgLstStart : "Alku", +DlgLstType : "Tyyppi", +DlgLstTypeCircle : "Kehä", +DlgLstTypeDisc : "Ympyrä", +DlgLstTypeSquare : "Neliö", +DlgLstTypeNumbers : "Numerot (1, 2, 3)", +DlgLstTypeLCase : "Pienet kirjaimet (a, b, c)", +DlgLstTypeUCase : "Isot kirjaimet (A, B, C)", +DlgLstTypeSRoman : "Pienet roomalaiset numerot (i, ii, iii)", +DlgLstTypeLRoman : "Isot roomalaiset numerot (Ii, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Yleiset", +DlgDocBackTab : "Tausta", +DlgDocColorsTab : "Värit ja marginaalit", +DlgDocMetaTab : "Meta-tieto", + +DlgDocPageTitle : "Sivun nimi", +DlgDocLangDir : "Kielen suunta", +DlgDocLangDirLTR : "Vasemmalta oikealle (LTR)", +DlgDocLangDirRTL : "Oikealta vasemmalle (RTL)", +DlgDocLangCode : "Kielikoodi", +DlgDocCharSet : "Merkistökoodaus", +DlgDocCharSetCE : "Keskieurooppalainen", +DlgDocCharSetCT : "Kiina, perinteinen (Big5)", +DlgDocCharSetCR : "Kyrillinen", +DlgDocCharSetGR : "Kreikka", +DlgDocCharSetJP : "Japani", +DlgDocCharSetKR : "Korealainen", +DlgDocCharSetTR : "Turkkilainen", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Länsieurooppalainen", +DlgDocCharSetOther : "Muu merkistökoodaus", + +DlgDocDocType : "Dokumentin tyyppi", +DlgDocDocTypeOther : "Muu dokumentin tyyppi", +DlgDocIncXHTML : "Lisää XHTML julistukset", +DlgDocBgColor : "Taustaväri", +DlgDocBgImage : "Taustakuva", +DlgDocBgNoScroll : "Paikallaanpysyvä tausta", +DlgDocCText : "Teksti", +DlgDocCLink : "Linkki", +DlgDocCVisited : "Vierailtu linkki", +DlgDocCActive : "Aktiivinen linkki", +DlgDocMargins : "Sivun marginaalit", +DlgDocMaTop : "Ylä", +DlgDocMaLeft : "Vasen", +DlgDocMaRight : "Oikea", +DlgDocMaBottom : "Ala", +DlgDocMeIndex : "Hakusanat (pilkulla erotettuna)", +DlgDocMeDescr : "Kuvaus", +DlgDocMeAuthor : "Tekijä", +DlgDocMeCopy : "Tekijänoikeudet", +DlgDocPreview : "Esikatselu", + +// Templates Dialog +Templates : "Pohjat", +DlgTemplatesTitle : "Sisältöpohjat", +DlgTemplatesSelMsg : "Valitse pohja editoriin
    (aiempi sisältö menetetään):", +DlgTemplatesLoading : "Ladataan listaa pohjista. Hetkinen...", +DlgTemplatesNoTpl : "(Ei määriteltyjä pohjia)", +DlgTemplatesReplace : "Korvaa editorin koko sisältö", + +// About Dialog +DlgAboutAboutTab : "Editorista", +DlgAboutBrowserInfoTab : "Selaimen tiedot", +DlgAboutLicenseTab : "Lisenssi", +DlgAboutVersion : "versio", +DlgAboutInfo : "Lisää tietoa osoitteesta", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/fo.js b/www/js/FCKeditor/editor/lang/fo.js new file mode 100644 index 0000000..3630989 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/fo.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Faroese language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Fjal amboðsbjálkan", +ToolbarExpand : "Vís amboðsbjálkan", + +// Toolbar Items and Context Menu +Save : "Goym", +NewPage : "Nýggj síða", +Preview : "Frumsýning", +Cut : "Kvett", +Copy : "Avrita", +Paste : "Innrita", +PasteText : "Innrita reinan tekst", +PasteWord : "Innrita frá Word", +Print : "Prenta", +SelectAll : "Markera alt", +RemoveFormat : "Strika sniðgeving", +InsertLinkLbl : "Tilknýti", +InsertLink : "Ger/broyt tilknýti", +RemoveLink : "Strika tilknýti", +VisitLink : "Opna tilknýti", +Anchor : "Ger/broyt marknastein", +AnchorDelete : "Strika marknastein", +InsertImageLbl : "Myndir", +InsertImage : "Set inn/broyt mynd", +InsertFlashLbl : "Flash", +InsertFlash : "Set inn/broyt Flash", +InsertTableLbl : "Tabell", +InsertTable : "Set inn/broyt tabell", +InsertLineLbl : "Linja", +InsertLine : "Ger vatnrætta linju", +InsertSpecialCharLbl: "Sertekn", +InsertSpecialChar : "Set inn sertekn", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Set inn Smiley", +About : "Um FCKeditor", +Bold : "Feit skrift", +Italic : "Skráskrift", +Underline : "Undirstrikað", +StrikeThrough : "Yvirstrikað", +Subscript : "Lækkað skrift", +Superscript : "Hækkað skrift", +LeftJustify : "Vinstrasett", +CenterJustify : "Miðsett", +RightJustify : "Høgrasett", +BlockJustify : "Javnir tekstkantar", +DecreaseIndent : "Minka reglubrotarinntriv", +IncreaseIndent : "Økja reglubrotarinntriv", +Blockquote : "Blockquote", +CreateDiv : "Ger DIV øki", +EditDiv : "Broyt DIV øki", +DeleteDiv : "Strika DIV øki", +Undo : "Angra", +Redo : "Vend aftur", +NumberedListLbl : "Talmerktur listi", +NumberedList : "Ger/strika talmerktan lista", +BulletedListLbl : "Punktmerktur listi", +BulletedList : "Ger/strika punktmerktan lista", +ShowTableBorders : "Vís tabellbordar", +ShowDetails : "Vís í smálutum", +Style : "Typografi", +FontFormat : "Skriftsnið", +Font : "Skrift", +FontSize : "Skriftstødd", +TextColor : "Tekstlitur", +BGColor : "Bakgrundslitur", +Source : "Kelda", +Find : "Leita", +Replace : "Yvirskriva", +SpellCheck : "Kanna stavseting", +UniversalKeyboard : "Knappaborð", +PageBreakLbl : "Síðuskift", +PageBreak : "Ger síðuskift", + +Form : "Formur", +Checkbox : "Flugubein", +RadioButton : "Radioknøttur", +TextField : "Tekstteigur", +Textarea : "Tekstumráði", +HiddenField : "Fjaldur teigur", +Button : "Knøttur", +SelectionField : "Valskrá", +ImageButton : "Myndaknøttur", + +FitWindow : "Set tekstviðgera til fulla stødd", +ShowBlocks : "Vís blokkar", + +// Context Menu +EditLink : "Broyt tilknýti", +CellCM : "Meski", +RowCM : "Rað", +ColumnCM : "Kolonna", +InsertRowAfter : "Set rað inn aftaná", +InsertRowBefore : "Set rað inn áðrenn", +DeleteRows : "Strika røðir", +InsertColumnAfter : "Set kolonnu inn aftaná", +InsertColumnBefore : "Set kolonnu inn áðrenn", +DeleteColumns : "Strika kolonnur", +InsertCellAfter : "Set meska inn aftaná", +InsertCellBefore : "Set meska inn áðrenn", +DeleteCells : "Strika meskar", +MergeCells : "Flætta meskar", +MergeRight : "Flætta meskar til høgru", +MergeDown : "Flætta saman", +HorizontalSplitCell : "Kloyv meska vatnrætt", +VerticalSplitCell : "Kloyv meska loddrætt", +TableDelete : "Strika tabell", +CellProperties : "Meskueginleikar", +TableProperties : "Tabelleginleikar", +ImageProperties : "Myndaeginleikar", +FlashProperties : "Flash eginleikar", + +AnchorProp : "Eginleikar fyri marknastein", +ButtonProp : "Eginleikar fyri knøtt", +CheckboxProp : "Eginleikar fyri flugubein", +HiddenFieldProp : "Eginleikar fyri fjaldan teig", +RadioButtonProp : "Eginleikar fyri radioknøtt", +ImageButtonProp : "Eginleikar fyri myndaknøtt", +TextFieldProp : "Eginleikar fyri tekstteig", +SelectionFieldProp : "Eginleikar fyri valskrá", +TextareaProp : "Eginleikar fyri tekstumráði", +FormProp : "Eginleikar fyri Form", + +FontFormats : "Vanligt;Sniðgivið;Adressa;Yvirskrift 1;Yvirskrift 2;Yvirskrift 3;Yvirskrift 4;Yvirskrift 5;Yvirskrift 6", + +// Alerts and Messages +ProcessingXHTML : "XHTML verður viðgjørt. Bíða við...", +Done : "Liðugt", +PasteWordConfirm : "Teksturin, royndur verður at seta inn, tykist at stava frá Word. Vilt tú reinsa tekstin, áðrenn hann verður settur inn?", +NotCompatiblePaste : "Hetta er bert tøkt í Internet Explorer 5.5 og nýggjari. Vilt tú seta tekstin inn kortini - óreinsaðan?", +UnknownToolbarItem : "Ókendur lutur í amboðsbjálkanum \"%1\"", +UnknownCommand : "Ókend kommando \"%1\"", +NotImplemented : "Hetta er ikki tøkt í hesi útgávuni", +UnknownToolbarSet : "Amboðsbjálkin \"%1\" finst ikki", +NoActiveX : "Trygdaruppsetingin í alnótskaganum kann sum er avmarka onkrar hentleikar í tekstviðgeranum. Tú mást loyva møguleikanum \"Run/Kør ActiveX controls and plug-ins\". Tú kanst uppliva feilir og ávaringar um tvørrandi hentleikar.", +BrowseServerBlocked : "Ambætarakagin kundi ikki opnast. Tryggja tær, at allar pop-up forðingar eru óvirknar.", +DialogBlocked : "Tað eyðnaðist ikki at opna samskiftisrútin. Tryggja tær, at allar pop-up forðingar eru óvirknar.", +VisitLinkBlocked : "Tað eyðnaðist ikki at opna nýggjan rút. Tryggja tær, at allar pop-up forðingar eru óvirknar.", + +// Dialogs +DlgBtnOK : "Góðkent", +DlgBtnCancel : "Avlýst", +DlgBtnClose : "Lat aftur", +DlgBtnBrowseServer : "Ambætarakagi", +DlgAdvancedTag : "Fjølbroytt", +DlgOpOther : "", +DlgInfoTab : "Upplýsingar", +DlgAlertUrl : "Vinarliga veit ein URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Tekstkós", +DlgGenLangDirLtr : "Frá vinstru til høgru (LTR)", +DlgGenLangDirRtl : "Frá høgru til vinstru (RTL)", +DlgGenLangCode : "Málkoda", +DlgGenAccessKey : "Snarvegisknappur", +DlgGenName : "Navn", +DlgGenTabIndex : "Inntriv indeks", +DlgGenLongDescr : "Víðkað URL frágreiðing", +DlgGenClass : "Typografi klassar", +DlgGenTitle : "Vegleiðandi heiti", +DlgGenContType : "Vegleiðandi innihaldsslag", +DlgGenLinkCharset : "Atknýtt teknsett", +DlgGenStyle : "Typografi", + +// Image Dialog +DlgImgTitle : "Myndaeginleikar", +DlgImgInfoTab : "Myndaupplýsingar", +DlgImgBtnUpload : "Send til ambætaran", +DlgImgURL : "URL", +DlgImgUpload : "Send", +DlgImgAlt : "Alternativur tekstur", +DlgImgWidth : "Breidd", +DlgImgHeight : "Hædd", +DlgImgLockRatio : "Læs lutfallið", +DlgBtnResetSize : "Upprunastødd", +DlgImgBorder : "Bordi", +DlgImgHSpace : "Høgri breddi", +DlgImgVSpace : "Vinstri breddi", +DlgImgAlign : "Justering", +DlgImgAlignLeft : "Vinstra", +DlgImgAlignAbsBottom: "Abs botnur", +DlgImgAlignAbsMiddle: "Abs miðja", +DlgImgAlignBaseline : "Basislinja", +DlgImgAlignBottom : "Botnur", +DlgImgAlignMiddle : "Miðja", +DlgImgAlignRight : "Høgra", +DlgImgAlignTextTop : "Tekst toppur", +DlgImgAlignTop : "Ovast", +DlgImgPreview : "Frumsýning", +DlgImgAlertUrl : "Rita slóðina til myndina", +DlgImgLinkTab : "Tilknýti", + +// Flash Dialog +DlgFlashTitle : "Flash eginleikar", +DlgFlashChkPlay : "Avspælingin byrjar sjálv", +DlgFlashChkLoop : "Endurspæl", +DlgFlashChkMenu : "Ger Flash skrá virkna", +DlgFlashScale : "Skalering", +DlgFlashScaleAll : "Vís alt", +DlgFlashScaleNoBorder : "Eingin bordi", +DlgFlashScaleFit : "Neyv skalering", + +// Link Dialog +DlgLnkWindowTitle : "Tilknýti", +DlgLnkInfoTab : "Tilknýtis upplýsingar", +DlgLnkTargetTab : "Mál", + +DlgLnkType : "Tilknýtisslag", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Tilknýti til marknastein í tekstinum", +DlgLnkTypeEMail : "Teldupostur", +DlgLnkProto : "Protokoll", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Vel ein marknastein", +DlgLnkAnchorByName : "Eftir navni á marknasteini", +DlgLnkAnchorById : "Eftir element Id", +DlgLnkNoAnchors : "(Eingir marknasteinar eru í hesum dokumentið)", +DlgLnkEMail : "Teldupost-adressa", +DlgLnkEMailSubject : "Evni", +DlgLnkEMailBody : "Breyðtekstur", +DlgLnkUpload : "Send til ambætaran", +DlgLnkBtnUpload : "Send til ambætaran", + +DlgLnkTarget : "Mál", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nýtt vindeyga (_blank)", +DlgLnkTargetParent : "Upphavliga vindeygað (_parent)", +DlgLnkTargetSelf : "Sama vindeygað (_self)", +DlgLnkTargetTop : "Alt vindeygað (_top)", +DlgLnkTargetFrameName : "Vís navn vindeygans", +DlgLnkPopWinName : "Popup vindeygans navn", +DlgLnkPopWinFeat : "Popup vindeygans víðkaðu eginleikar", +DlgLnkPopResize : "Kann broyta stødd", +DlgLnkPopLocation : "Adressulinja", +DlgLnkPopMenu : "Skrábjálki", +DlgLnkPopScroll : "Rullibjálki", +DlgLnkPopStatus : "Støðufrágreiðingarbjálki", +DlgLnkPopToolbar : "Amboðsbjálki", +DlgLnkPopFullScrn : "Fullur skermur (IE)", +DlgLnkPopDependent : "Bundið (Netscape)", +DlgLnkPopWidth : "Breidd", +DlgLnkPopHeight : "Hædd", +DlgLnkPopLeft : "Frástøða frá vinstru", +DlgLnkPopTop : "Frástøða frá íerva", + +DlnLnkMsgNoUrl : "Vinarliga skriva tilknýti (URL)", +DlnLnkMsgNoEMail : "Vinarliga skriva teldupost-adressu", +DlnLnkMsgNoAnchor : "Vinarliga vel marknastein", +DlnLnkMsgInvPopName : "Popup navnið má byrja við bókstavi og má ikki hava millumrúm", + +// Color Dialog +DlgColorTitle : "Vel lit", +DlgColorBtnClear : "Strika alt", +DlgColorHighlight : "Framhevja", +DlgColorSelected : "Valt", + +// Smiley Dialog +DlgSmileyTitle : "Vel Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Vel sertekn", + +// Table Dialog +DlgTableTitle : "Eginleikar fyri tabell", +DlgTableRows : "Røðir", +DlgTableColumns : "Kolonnur", +DlgTableBorder : "Bordabreidd", +DlgTableAlign : "Justering", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Vinstrasett", +DlgTableAlignCenter : "Miðsett", +DlgTableAlignRight : "Høgrasett", +DlgTableWidth : "Breidd", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "prosent", +DlgTableHeight : "Hædd", +DlgTableCellSpace : "Fjarstøða millum meskar", +DlgTableCellPad : "Meskubreddi", +DlgTableCaption : "Tabellfrágreiðing", +DlgTableSummary : "Samandráttur", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Mesku eginleikar", +DlgCellWidth : "Breidd", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "prosent", +DlgCellHeight : "Hædd", +DlgCellWordWrap : "Orðkloyving", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Ja", +DlgCellWordWrapNo : "Nei", +DlgCellHorAlign : "Vatnrøtt justering", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Vinstrasett", +DlgCellHorAlignCenter : "Miðsett", +DlgCellHorAlignRight: "Høgrasett", +DlgCellVerAlign : "Lodrøtt justering", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Ovast", +DlgCellVerAlignMiddle : "Miðjan", +DlgCellVerAlignBottom : "Niðast", +DlgCellVerAlignBaseline : "Basislinja", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Røðir, meskin fevnir um", +DlgCellCollSpan : "Kolonnur, meskin fevnir um", +DlgCellBackColor : "Bakgrundslitur", +DlgCellBorderColor : "Litur á borda", +DlgCellBtnSelect : "Vel...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Finn og broyt", + +// Find Dialog +DlgFindTitle : "Finn", +DlgFindFindBtn : "Finn", +DlgFindNotFoundMsg : "Leititeksturin varð ikki funnin", + +// Replace Dialog +DlgReplaceTitle : "Yvirskriva", +DlgReplaceFindLbl : "Finn:", +DlgReplaceReplaceLbl : "Yvirskriva við:", +DlgReplaceCaseChk : "Munur á stórum og smáðum bókstavum", +DlgReplaceReplaceBtn : "Yvirskriva", +DlgReplaceReplAllBtn : "Yvirskriva alt", +DlgReplaceWordChk : "Bert heil orð", + +// Paste Operations / Dialog +PasteErrorCut : "Trygdaruppseting alnótskagans forðar tekstviðgeranum í at kvetta tekstin. Vinarliga nýt knappaborðið til at kvetta tekstin (CTRL+X).", +PasteErrorCopy : "Trygdaruppseting alnótskagans forðar tekstviðgeranum í at avrita tekstin. Vinarliga nýt knappaborðið til at avrita tekstin (CTRL+C).", + +PasteAsText : "Innrita som reinan tekst", +PasteFromWord : "Innrita fra Word", + +DlgPasteMsg2 : "Vinarliga koyr tekstin í hendan rútin við knappaborðinum (CTRL+V) og klikk á Góðtak.", +DlgPasteSec : "Trygdaruppseting alnótskagans forðar tekstviðgeranum í beinleiðis atgongd til avritingarminnið. Tygum mugu royna aftur í hesum rútinum.", +DlgPasteIgnoreFont : "Forfjóna Font definitiónirnar", +DlgPasteRemoveStyles : "Strika typografi definitiónir", + +// Color Picker +ColorAutomatic : "Automatiskt", +ColorMoreColors : "Fleiri litir...", + +// Document Properties +DocProps : "Eginleikar fyri dokument", + +// Anchor Dialog +DlgAnchorTitle : "Eginleikar fyri marknastein", +DlgAnchorName : "Heiti marknasteinsins", +DlgAnchorErrorName : "Vinarliga rita marknasteinsins heiti", + +// Speller Pages Dialog +DlgSpellNotInDic : "Finst ikki í orðabókini", +DlgSpellChangeTo : "Broyt til", +DlgSpellBtnIgnore : "Forfjóna", +DlgSpellBtnIgnoreAll : "Forfjóna alt", +DlgSpellBtnReplace : "Yvirskriva", +DlgSpellBtnReplaceAll : "Yvirskriva alt", +DlgSpellBtnUndo : "Angra", +DlgSpellNoSuggestions : "- Einki uppskot -", +DlgSpellProgress : "Rættstavarin arbeiðir...", +DlgSpellNoMispell : "Rættstavarain liðugur: Eingin feilur funnin", +DlgSpellNoChanges : "Rættstavarain liðugur: Einki orð varð broytt", +DlgSpellOneChange : "Rættstavarain liðugur: Eitt orð er broytt", +DlgSpellManyChanges : "Rættstavarain liðugur: %1 orð broytt", + +IeSpellDownload : "Rættstavarin er ikki tøkur í tekstviðgeranum. Vilt tú heinta hann nú?", + +// Button Dialog +DlgButtonText : "Tekstur", +DlgButtonType : "Slag", +DlgButtonTypeBtn : "Knøttur", +DlgButtonTypeSbm : "Send", +DlgButtonTypeRst : "Nullstilla", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Navn", +DlgCheckboxValue : "Virði", +DlgCheckboxSelected : "Valt", + +// Form Dialog +DlgFormName : "Navn", +DlgFormAction : "Hending", +DlgFormMethod : "Háttur", + +// Select Field Dialog +DlgSelectName : "Navn", +DlgSelectValue : "Virði", +DlgSelectSize : "Stødd", +DlgSelectLines : "Linjur", +DlgSelectChkMulti : "Loyv fleiri valmøguleikum samstundis", +DlgSelectOpAvail : "Tøkir møguleikar", +DlgSelectOpText : "Tekstur", +DlgSelectOpValue : "Virði", +DlgSelectBtnAdd : "Legg afturat", +DlgSelectBtnModify : "Broyt", +DlgSelectBtnUp : "Upp", +DlgSelectBtnDown : "Niður", +DlgSelectBtnSetValue : "Set sum valt virði", +DlgSelectBtnDelete : "Strika", + +// Textarea Dialog +DlgTextareaName : "Navn", +DlgTextareaCols : "kolonnur", +DlgTextareaRows : "røðir", + +// Text Field Dialog +DlgTextName : "Navn", +DlgTextValue : "Virði", +DlgTextCharWidth : "Breidd (sjónlig tekn)", +DlgTextMaxChars : "Mest loyvdu tekn", +DlgTextType : "Slag", +DlgTextTypeText : "Tekstur", +DlgTextTypePass : "Loyniorð", + +// Hidden Field Dialog +DlgHiddenName : "Navn", +DlgHiddenValue : "Virði", + +// Bulleted List Dialog +BulletedListProp : "Eginleikar fyri punktmerktan lista", +NumberedListProp : "Eginleikar fyri talmerktan lista", +DlgLstStart : "Byrjan", +DlgLstType : "Slag", +DlgLstTypeCircle : "Sirkul", +DlgLstTypeDisc : "Fyltur sirkul", +DlgLstTypeSquare : "Fjórhyrningur", +DlgLstTypeNumbers : "Talmerkt (1, 2, 3)", +DlgLstTypeLCase : "Smáir bókstavir (a, b, c)", +DlgLstTypeUCase : "Stórir bókstavir (A, B, C)", +DlgLstTypeSRoman : "Smá rómaratøl (i, ii, iii)", +DlgLstTypeLRoman : "Stór rómaratøl (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Generelt", +DlgDocBackTab : "Bakgrund", +DlgDocColorsTab : "Litir og breddar", +DlgDocMetaTab : "META-upplýsingar", + +DlgDocPageTitle : "Síðuheiti", +DlgDocLangDir : "Tekstkós", +DlgDocLangDirLTR : "Frá vinstru móti høgru (LTR)", +DlgDocLangDirRTL : "Frá høgru móti vinstru (RTL)", +DlgDocLangCode : "Málkoda", +DlgDocCharSet : "Teknsett koda", +DlgDocCharSetCE : "Miðeuropa", +DlgDocCharSetCT : "Kinesiskt traditionelt (Big5)", +DlgDocCharSetCR : "Cyrilliskt", +DlgDocCharSetGR : "Grikst", +DlgDocCharSetJP : "Japanskt", +DlgDocCharSetKR : "Koreanskt", +DlgDocCharSetTR : "Turkiskt", +DlgDocCharSetUN : "UNICODE (UTF-8)", +DlgDocCharSetWE : "Vestureuropa", +DlgDocCharSetOther : "Onnur teknsett koda", + +DlgDocDocType : "Dokumentslag yvirskrift", +DlgDocDocTypeOther : "Annað dokumentslag yvirskrift", +DlgDocIncXHTML : "Viðfest XHTML deklaratiónir", +DlgDocBgColor : "Bakgrundslitur", +DlgDocBgImage : "Leið til bakgrundsmynd (URL)", +DlgDocBgNoScroll : "Læst bakgrund (rullar ikki)", +DlgDocCText : "Tekstur", +DlgDocCLink : "Tilknýti", +DlgDocCVisited : "Vitjaði tilknýti", +DlgDocCActive : "Virkin tilknýti", +DlgDocMargins : "Síðubreddar", +DlgDocMaTop : "Ovast", +DlgDocMaLeft : "Vinstra", +DlgDocMaRight : "Høgra", +DlgDocMaBottom : "Niðast", +DlgDocMeIndex : "Dokument index lyklaorð (sundurbýtt við komma)", +DlgDocMeDescr : "Dokumentlýsing", +DlgDocMeAuthor : "Høvundur", +DlgDocMeCopy : "Upphavsrættindi", +DlgDocPreview : "Frumsýning", + +// Templates Dialog +Templates : "Skabelónir", +DlgTemplatesTitle : "Innihaldsskabelónir", +DlgTemplatesSelMsg : "Vinarliga vel ta skabelón, ið skal opnast í tekstviðgeranum
    (Hetta yvirskrivar núverandi innihald):", +DlgTemplatesLoading : "Heinti yvirlit yvir skabelónir. Vinarliga bíða við...", +DlgTemplatesNoTpl : "(Ongar skabelónir tøkar)", +DlgTemplatesReplace : "Yvirskriva núverandi innihald", + +// About Dialog +DlgAboutAboutTab : "Um", +DlgAboutBrowserInfoTab : "Upplýsingar um alnótskagan", +DlgAboutLicenseTab : "License", +DlgAboutVersion : "version", +DlgAboutInfo : "Fyri fleiri upplýsingar, far til", + +// Div Dialog +DlgDivGeneralTab : "Generelt", +DlgDivAdvancedTab : "Fjølbroytt", +DlgDivStyle : "Typografi", +DlgDivInlineStyle : "Inline typografi", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/fr-ca.js b/www/js/FCKeditor/editor/lang/fr-ca.js new file mode 100644 index 0000000..4c3fa69 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/fr-ca.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Canadian French language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Masquer Outils", +ToolbarExpand : "Afficher Outils", + +// Toolbar Items and Context Menu +Save : "Sauvegarder", +NewPage : "Nouvelle page", +Preview : "Previsualiser", +Cut : "Couper", +Copy : "Copier", +Paste : "Coller", +PasteText : "Coller en tant que texte", +PasteWord : "Coller en tant que Word (formaté)", +Print : "Imprimer", +SelectAll : "Tout sélectionner", +RemoveFormat : "Supprimer le formatage", +InsertLinkLbl : "Lien", +InsertLink : "Insérer/modifier le lien", +RemoveLink : "Supprimer le lien", +VisitLink : "Suivre le lien", +Anchor : "Insérer/modifier l'ancre", +AnchorDelete : "Supprimer l'ancre", +InsertImageLbl : "Image", +InsertImage : "Insérer/modifier l'image", +InsertFlashLbl : "Animation Flash", +InsertFlash : "Insérer/modifier l'animation Flash", +InsertTableLbl : "Tableau", +InsertTable : "Insérer/modifier le tableau", +InsertLineLbl : "Séparateur", +InsertLine : "Insérer un séparateur", +InsertSpecialCharLbl: "Caractères spéciaux", +InsertSpecialChar : "Insérer un caractère spécial", +InsertSmileyLbl : "Emoticon", +InsertSmiley : "Insérer un Emoticon", +About : "A propos de FCKeditor", +Bold : "Gras", +Italic : "Italique", +Underline : "Souligné", +StrikeThrough : "Barrer", +Subscript : "Indice", +Superscript : "Exposant", +LeftJustify : "Aligner à gauche", +CenterJustify : "Centrer", +RightJustify : "Aligner à Droite", +BlockJustify : "Texte justifié", +DecreaseIndent : "Diminuer le retrait", +IncreaseIndent : "Augmenter le retrait", +Blockquote : "Citation", +CreateDiv : "Créer Balise Div", +EditDiv : "Modifier Balise Div", +DeleteDiv : "Supprimer Balise Div", +Undo : "Annuler", +Redo : "Refaire", +NumberedListLbl : "Liste numérotée", +NumberedList : "Insérer/supprimer la liste numérotée", +BulletedListLbl : "Liste à puces", +BulletedList : "Insérer/supprimer la liste à puces", +ShowTableBorders : "Afficher les bordures du tableau", +ShowDetails : "Afficher les caractères invisibles", +Style : "Style", +FontFormat : "Format", +Font : "Police", +FontSize : "Taille", +TextColor : "Couleur de caractère", +BGColor : "Couleur de fond", +Source : "Source", +Find : "Chercher", +Replace : "Remplacer", +SpellCheck : "Orthographe", +UniversalKeyboard : "Clavier universel", +PageBreakLbl : "Saut de page", +PageBreak : "Insérer un saut de page", + +Form : "Formulaire", +Checkbox : "Case à cocher", +RadioButton : "Bouton radio", +TextField : "Champ texte", +Textarea : "Zone de texte", +HiddenField : "Champ caché", +Button : "Bouton", +SelectionField : "Champ de sélection", +ImageButton : "Bouton image", + +FitWindow : "Edition pleine page", +ShowBlocks : "Afficher les blocs", + +// Context Menu +EditLink : "Modifier le lien", +CellCM : "Cellule", +RowCM : "Ligne", +ColumnCM : "Colonne", +InsertRowAfter : "Insérer une ligne après", +InsertRowBefore : "Insérer une ligne avant", +DeleteRows : "Supprimer des lignes", +InsertColumnAfter : "Insérer une colonne après", +InsertColumnBefore : "Insérer une colonne avant", +DeleteColumns : "Supprimer des colonnes", +InsertCellAfter : "Insérer une cellule après", +InsertCellBefore : "Insérer une cellule avant", +DeleteCells : "Supprimer des cellules", +MergeCells : "Fusionner les cellules", +MergeRight : "Fusionner à droite", +MergeDown : "Fusionner en bas", +HorizontalSplitCell : "Scinder la cellule horizontalement", +VerticalSplitCell : "Scinder la cellule verticalement", +TableDelete : "Supprimer le tableau", +CellProperties : "Propriétés de cellule", +TableProperties : "Propriétés du tableau", +ImageProperties : "Propriétés de l'image", +FlashProperties : "Propriétés de l'animation Flash", + +AnchorProp : "Propriétés de l'ancre", +ButtonProp : "Propriétés du bouton", +CheckboxProp : "Propriétés de la case à cocher", +HiddenFieldProp : "Propriétés du champ caché", +RadioButtonProp : "Propriétés du bouton radio", +ImageButtonProp : "Propriétés du bouton image", +TextFieldProp : "Propriétés du champ texte", +SelectionFieldProp : "Propriétés de la liste/du menu", +TextareaProp : "Propriétés de la zone de texte", +FormProp : "Propriétés du formulaire", + +FontFormats : "Normal;Formaté;Adresse;En-tête 1;En-tête 2;En-tête 3;En-tête 4;En-tête 5;En-tête 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Calcul XHTML. Veuillez patienter...", +Done : "Terminé", +PasteWordConfirm : "Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller?", +NotCompatiblePaste : "Cette commande nécessite Internet Explorer version 5.5 et plus. Souhaitez-vous coller sans nettoyage?", +UnknownToolbarItem : "Élément de barre d'outil inconnu \"%1\"", +UnknownCommand : "Nom de commande inconnu \"%1\"", +NotImplemented : "Commande indisponible", +UnknownToolbarSet : "La barre d'outils \"%1\" n'existe pas", +NoActiveX : "Les paramètres de sécurité de votre navigateur peuvent limiter quelques fonctionnalités de l'éditeur. Veuillez activer l'option \"Exécuter les contrôles ActiveX et les plug-ins\". Il se peut que vous rencontriez des erreurs et remarquiez quelques limitations.", +BrowseServerBlocked : "Le navigateur n'a pas pu être ouvert. Assurez-vous que les bloqueurs de popups soient désactivés.", +DialogBlocked : "La fenêtre de dialogue n'a pas pu s'ouvrir. Assurez-vous que les bloqueurs de popups soient désactivés.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Annuler", +DlgBtnClose : "Fermer", +DlgBtnBrowseServer : "Parcourir le serveur", +DlgAdvancedTag : "Avancée", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Veuillez saisir l'URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Sens d'écriture", +DlgGenLangDirLtr : "De gauche à droite (LTR)", +DlgGenLangDirRtl : "De droite à gauche (RTL)", +DlgGenLangCode : "Code langue", +DlgGenAccessKey : "Équivalent clavier", +DlgGenName : "Nom", +DlgGenTabIndex : "Ordre de tabulation", +DlgGenLongDescr : "URL de description longue", +DlgGenClass : "Classes de feuilles de style", +DlgGenTitle : "Titre", +DlgGenContType : "Type de contenu", +DlgGenLinkCharset : "Encodage de caractère", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Propriétés de l'image", +DlgImgInfoTab : "Informations sur l'image", +DlgImgBtnUpload : "Envoyer sur le serveur", +DlgImgURL : "URL", +DlgImgUpload : "Télécharger", +DlgImgAlt : "Texte de remplacement", +DlgImgWidth : "Largeur", +DlgImgHeight : "Hauteur", +DlgImgLockRatio : "Garder les proportions", +DlgBtnResetSize : "Taille originale", +DlgImgBorder : "Bordure", +DlgImgHSpace : "Espacement horizontal", +DlgImgVSpace : "Espacement vertical", +DlgImgAlign : "Alignement", +DlgImgAlignLeft : "Gauche", +DlgImgAlignAbsBottom: "Abs Bas", +DlgImgAlignAbsMiddle: "Abs Milieu", +DlgImgAlignBaseline : "Bas du texte", +DlgImgAlignBottom : "Bas", +DlgImgAlignMiddle : "Milieu", +DlgImgAlignRight : "Droite", +DlgImgAlignTextTop : "Haut du texte", +DlgImgAlignTop : "Haut", +DlgImgPreview : "Prévisualisation", +DlgImgAlertUrl : "Veuillez saisir l'URL de l'image", +DlgImgLinkTab : "Lien", + +// Flash Dialog +DlgFlashTitle : "Propriétés de l'animation Flash", +DlgFlashChkPlay : "Lecture automatique", +DlgFlashChkLoop : "Boucle", +DlgFlashChkMenu : "Activer le menu Flash", +DlgFlashScale : "Affichage", +DlgFlashScaleAll : "Par défaut (tout montrer)", +DlgFlashScaleNoBorder : "Sans bordure", +DlgFlashScaleFit : "Ajuster aux dimensions", + +// Link Dialog +DlgLnkWindowTitle : "Propriétés du lien", +DlgLnkInfoTab : "Informations sur le lien", +DlgLnkTargetTab : "Destination", + +DlgLnkType : "Type de lien", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Ancre dans cette page", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocole", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Sélectionner une ancre", +DlgLnkAnchorByName : "Par nom", +DlgLnkAnchorById : "Par id", +DlgLnkNoAnchors : "(Pas d'ancre disponible dans le document)", +DlgLnkEMail : "Adresse E-Mail", +DlgLnkEMailSubject : "Sujet du message", +DlgLnkEMailBody : "Corps du message", +DlgLnkUpload : "Télécharger", +DlgLnkBtnUpload : "Envoyer sur le serveur", + +DlgLnkTarget : "Destination", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nouvelle fenêtre (_blank)", +DlgLnkTargetParent : "Fenêtre mère (_parent)", +DlgLnkTargetSelf : "Même fenêtre (_self)", +DlgLnkTargetTop : "Fenêtre supérieure (_top)", +DlgLnkTargetFrameName : "Nom du cadre de destination", +DlgLnkPopWinName : "Nom de la fenêtre popup", +DlgLnkPopWinFeat : "Caractéristiques de la fenêtre popup", +DlgLnkPopResize : "Taille modifiable", +DlgLnkPopLocation : "Barre d'adresses", +DlgLnkPopMenu : "Barre de menu", +DlgLnkPopScroll : "Barres de défilement", +DlgLnkPopStatus : "Barre d'état", +DlgLnkPopToolbar : "Barre d'outils", +DlgLnkPopFullScrn : "Plein écran (IE)", +DlgLnkPopDependent : "Dépendante (Netscape)", +DlgLnkPopWidth : "Largeur", +DlgLnkPopHeight : "Hauteur", +DlgLnkPopLeft : "Position à partir de la gauche", +DlgLnkPopTop : "Position à partir du haut", + +DlnLnkMsgNoUrl : "Veuillez saisir l'URL", +DlnLnkMsgNoEMail : "Veuillez saisir l'adresse e-mail", +DlnLnkMsgNoAnchor : "Veuillez sélectionner une ancre", +DlnLnkMsgInvPopName : "Le nom de la fenêtre popup doit commencer par une lettre et ne doit pas contenir d'espace", + +// Color Dialog +DlgColorTitle : "Sélectionner", +DlgColorBtnClear : "Effacer", +DlgColorHighlight : "Prévisualisation", +DlgColorSelected : "Sélectionné", + +// Smiley Dialog +DlgSmileyTitle : "Insérer un Emoticon", + +// Special Character Dialog +DlgSpecialCharTitle : "Insérer un caractère spécial", + +// Table Dialog +DlgTableTitle : "Propriétés du tableau", +DlgTableRows : "Lignes", +DlgTableColumns : "Colonnes", +DlgTableBorder : "Taille de la bordure", +DlgTableAlign : "Alignement", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Gauche", +DlgTableAlignCenter : "Centré", +DlgTableAlignRight : "Droite", +DlgTableWidth : "Largeur", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "pourcentage", +DlgTableHeight : "Hauteur", +DlgTableCellSpace : "Espacement", +DlgTableCellPad : "Contour", +DlgTableCaption : "Titre", +DlgTableSummary : "Résumé", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Propriétés de la cellule", +DlgCellWidth : "Largeur", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "pourcentage", +DlgCellHeight : "Hauteur", +DlgCellWordWrap : "Retour à la ligne", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Oui", +DlgCellWordWrapNo : "Non", +DlgCellHorAlign : "Alignement horizontal", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Gauche", +DlgCellHorAlignCenter : "Centré", +DlgCellHorAlignRight: "Droite", +DlgCellVerAlign : "Alignement vertical", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Haut", +DlgCellVerAlignMiddle : "Milieu", +DlgCellVerAlignBottom : "Bas", +DlgCellVerAlignBaseline : "Bas du texte", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Lignes fusionnées", +DlgCellCollSpan : "Colonnes fusionnées", +DlgCellBackColor : "Couleur de fond", +DlgCellBorderColor : "Couleur de bordure", +DlgCellBtnSelect : "Sélectionner...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Chercher et Remplacer", + +// Find Dialog +DlgFindTitle : "Chercher", +DlgFindFindBtn : "Chercher", +DlgFindNotFoundMsg : "Le texte indiqué est introuvable.", + +// Replace Dialog +DlgReplaceTitle : "Remplacer", +DlgReplaceFindLbl : "Rechercher:", +DlgReplaceReplaceLbl : "Remplacer par:", +DlgReplaceCaseChk : "Respecter la casse", +DlgReplaceReplaceBtn : "Remplacer", +DlgReplaceReplAllBtn : "Tout remplacer", +DlgReplaceWordChk : "Mot entier", + +// Paste Operations / Dialog +PasteErrorCut : "Les paramètres de sécurité de votre navigateur empêchent l'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl+X).", +PasteErrorCopy : "Les paramètres de sécurité de votre navigateur empêchent l'éditeur de copier automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl+C).", + +PasteAsText : "Coller comme texte", +PasteFromWord : "Coller à partir de Word", + +DlgPasteMsg2 : "Veuillez coller dans la zone ci-dessous en utilisant le clavier (Ctrl+V) et appuyer sur OK.", +DlgPasteSec : "A cause des paramètres de sécurité de votre navigateur, l'éditeur ne peut accéder au presse-papier directement. Vous devez coller à nouveau le contenu dans cette fenêtre.", +DlgPasteIgnoreFont : "Ignorer les polices de caractères", +DlgPasteRemoveStyles : "Supprimer les styles", + +// Color Picker +ColorAutomatic : "Automatique", +ColorMoreColors : "Plus de couleurs...", + +// Document Properties +DocProps : "Propriétés du document", + +// Anchor Dialog +DlgAnchorTitle : "Propriétés de l'ancre", +DlgAnchorName : "Nom de l'ancre", +DlgAnchorErrorName : "Veuillez saisir le nom de l'ancre", + +// Speller Pages Dialog +DlgSpellNotInDic : "Pas dans le dictionnaire", +DlgSpellChangeTo : "Changer en", +DlgSpellBtnIgnore : "Ignorer", +DlgSpellBtnIgnoreAll : "Ignorer tout", +DlgSpellBtnReplace : "Remplacer", +DlgSpellBtnReplaceAll : "Remplacer tout", +DlgSpellBtnUndo : "Annuler", +DlgSpellNoSuggestions : "- Pas de suggestion -", +DlgSpellProgress : "Vérification d'orthographe en cours...", +DlgSpellNoMispell : "Vérification d'orthographe terminée: pas d'erreur trouvée", +DlgSpellNoChanges : "Vérification d'orthographe terminée: Pas de modifications", +DlgSpellOneChange : "Vérification d'orthographe terminée: Un mot modifié", +DlgSpellManyChanges : "Vérification d'orthographe terminée: %1 mots modifiés", + +IeSpellDownload : "Le Correcteur d'orthographe n'est pas installé. Souhaitez-vous le télécharger maintenant?", + +// Button Dialog +DlgButtonText : "Texte (Valeur)", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Bouton", +DlgButtonTypeSbm : "Soumettre", +DlgButtonTypeRst : "Réinitialiser", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nom", +DlgCheckboxValue : "Valeur", +DlgCheckboxSelected : "Sélectionné", + +// Form Dialog +DlgFormName : "Nom", +DlgFormAction : "Action", +DlgFormMethod : "Méthode", + +// Select Field Dialog +DlgSelectName : "Nom", +DlgSelectValue : "Valeur", +DlgSelectSize : "Taille", +DlgSelectLines : "lignes", +DlgSelectChkMulti : "Sélection multiple", +DlgSelectOpAvail : "Options disponibles", +DlgSelectOpText : "Texte", +DlgSelectOpValue : "Valeur", +DlgSelectBtnAdd : "Ajouter", +DlgSelectBtnModify : "Modifier", +DlgSelectBtnUp : "Monter", +DlgSelectBtnDown : "Descendre", +DlgSelectBtnSetValue : "Valeur sélectionnée", +DlgSelectBtnDelete : "Supprimer", + +// Textarea Dialog +DlgTextareaName : "Nom", +DlgTextareaCols : "Colonnes", +DlgTextareaRows : "Lignes", + +// Text Field Dialog +DlgTextName : "Nom", +DlgTextValue : "Valeur", +DlgTextCharWidth : "Largeur en caractères", +DlgTextMaxChars : "Nombre maximum de caractères", +DlgTextType : "Type", +DlgTextTypeText : "Texte", +DlgTextTypePass : "Mot de passe", + +// Hidden Field Dialog +DlgHiddenName : "Nom", +DlgHiddenValue : "Valeur", + +// Bulleted List Dialog +BulletedListProp : "Propriétés de liste à puces", +NumberedListProp : "Propriétés de liste numérotée", +DlgLstStart : "Début", +DlgLstType : "Type", +DlgLstTypeCircle : "Cercle", +DlgLstTypeDisc : "Disque", +DlgLstTypeSquare : "Carré", +DlgLstTypeNumbers : "Nombres (1, 2, 3)", +DlgLstTypeLCase : "Lettres minuscules (a, b, c)", +DlgLstTypeUCase : "Lettres majuscules (A, B, C)", +DlgLstTypeSRoman : "Chiffres romains minuscules (i, ii, iii)", +DlgLstTypeLRoman : "Chiffres romains majuscules (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Général", +DlgDocBackTab : "Fond", +DlgDocColorsTab : "Couleurs et Marges", +DlgDocMetaTab : "Méta-Données", + +DlgDocPageTitle : "Titre de la page", +DlgDocLangDir : "Sens d'écriture", +DlgDocLangDirLTR : "De la gauche vers la droite (LTR)", +DlgDocLangDirRTL : "De la droite vers la gauche (RTL)", +DlgDocLangCode : "Code langue", +DlgDocCharSet : "Encodage de caractère", +DlgDocCharSetCE : "Europe Centrale", +DlgDocCharSetCT : "Chinois Traditionnel (Big5)", +DlgDocCharSetCR : "Cyrillique", +DlgDocCharSetGR : "Grecque", +DlgDocCharSetJP : "Japonais", +DlgDocCharSetKR : "Coréen", +DlgDocCharSetTR : "Turcque", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Occidental", +DlgDocCharSetOther : "Autre encodage de caractère", + +DlgDocDocType : "Type de document", +DlgDocDocTypeOther : "Autre type de document", +DlgDocIncXHTML : "Inclure les déclarations XHTML", +DlgDocBgColor : "Couleur de fond", +DlgDocBgImage : "Image de fond", +DlgDocBgNoScroll : "Image fixe sans défilement", +DlgDocCText : "Texte", +DlgDocCLink : "Lien", +DlgDocCVisited : "Lien visité", +DlgDocCActive : "Lien activé", +DlgDocMargins : "Marges", +DlgDocMaTop : "Haut", +DlgDocMaLeft : "Gauche", +DlgDocMaRight : "Droite", +DlgDocMaBottom : "Bas", +DlgDocMeIndex : "Mots-clés (séparés par des virgules)", +DlgDocMeDescr : "Description", +DlgDocMeAuthor : "Auteur", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Prévisualisation", + +// Templates Dialog +Templates : "Modèles", +DlgTemplatesTitle : "Modèles de contenu", +DlgTemplatesSelMsg : "Sélectionner le modèle à ouvrir dans l'éditeur
    (le contenu actuel sera remplacé):", +DlgTemplatesLoading : "Chargement de la liste des modèles. Veuillez patienter...", +DlgTemplatesNoTpl : "(Aucun modèle disponible)", +DlgTemplatesReplace : "Remplacer tout le contenu actuel", + +// About Dialog +DlgAboutAboutTab : "à propos de", +DlgAboutBrowserInfoTab : "Navigateur", +DlgAboutLicenseTab : "License", +DlgAboutVersion : "Version", +DlgAboutInfo : "Pour plus d'informations, visiter", + +// Div Dialog +DlgDivGeneralTab : "Général", +DlgDivAdvancedTab : "Avancé", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Attribut Style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/fr.js b/www/js/FCKeditor/editor/lang/fr.js new file mode 100644 index 0000000..2969b32 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/fr.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * French language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Masquer Outils", +ToolbarExpand : "Afficher Outils", + +// Toolbar Items and Context Menu +Save : "Enregistrer", +NewPage : "Nouvelle page", +Preview : "Prévisualisation", +Cut : "Couper", +Copy : "Copier", +Paste : "Coller", +PasteText : "Coller comme texte", +PasteWord : "Coller de Word", +Print : "Imprimer", +SelectAll : "Tout sélectionner", +RemoveFormat : "Supprimer le format", +InsertLinkLbl : "Lien", +InsertLink : "Insérer/modifier le lien", +RemoveLink : "Supprimer le lien", +VisitLink : "Suivre le lien", +Anchor : "Insérer/modifier l'ancre", +AnchorDelete : "Supprimer l'ancre", +InsertImageLbl : "Image", +InsertImage : "Insérer/modifier l'image", +InsertFlashLbl : "Animation Flash", +InsertFlash : "Insérer/modifier l'animation Flash", +InsertTableLbl : "Tableau", +InsertTable : "Insérer/modifier le tableau", +InsertLineLbl : "Séparateur", +InsertLine : "Insérer un séparateur", +InsertSpecialCharLbl: "Caractères spéciaux", +InsertSpecialChar : "Insérer un caractère spécial", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Insérer un Smiley", +About : "A propos de FCKeditor", +Bold : "Gras", +Italic : "Italique", +Underline : "Souligné", +StrikeThrough : "Barré", +Subscript : "Indice", +Superscript : "Exposant", +LeftJustify : "Aligné à gauche", +CenterJustify : "Centré", +RightJustify : "Aligné à Droite", +BlockJustify : "Texte justifié", +DecreaseIndent : "Diminuer le retrait", +IncreaseIndent : "Augmenter le retrait", +Blockquote : "Citation", +CreateDiv : "Créer Balise Div", +EditDiv : "Modifier Balise Div", +DeleteDiv : "Supprimer Balise Div", +Undo : "Annuler", +Redo : "Refaire", +NumberedListLbl : "Liste numérotée", +NumberedList : "Insérer/supprimer la liste numérotée", +BulletedListLbl : "Liste à puces", +BulletedList : "Insérer/supprimer la liste à puces", +ShowTableBorders : "Afficher les bordures du tableau", +ShowDetails : "Afficher les caractères invisibles", +Style : "Style", +FontFormat : "Format", +Font : "Police", +FontSize : "Taille", +TextColor : "Couleur de caractère", +BGColor : "Couleur de fond", +Source : "Source", +Find : "Chercher", +Replace : "Remplacer", +SpellCheck : "Orthographe", +UniversalKeyboard : "Clavier universel", +PageBreakLbl : "Saut de page", +PageBreak : "Insérer un saut de page", + +Form : "Formulaire", +Checkbox : "Case à cocher", +RadioButton : "Bouton radio", +TextField : "Champ texte", +Textarea : "Zone de texte", +HiddenField : "Champ caché", +Button : "Bouton", +SelectionField : "Liste/menu", +ImageButton : "Bouton image", + +FitWindow : "Edition pleine page", +ShowBlocks : "Afficher les blocs", + +// Context Menu +EditLink : "Modifier le lien", +CellCM : "Cellule", +RowCM : "Ligne", +ColumnCM : "Colonne", +InsertRowAfter : "Insérer une ligne après", +InsertRowBefore : "Insérer une ligne avant", +DeleteRows : "Supprimer des lignes", +InsertColumnAfter : "Insérer une colonne après", +InsertColumnBefore : "Insérer une colonne avant", +DeleteColumns : "Supprimer des colonnes", +InsertCellAfter : "Insérer une cellule après", +InsertCellBefore : "Insérer une cellule avant", +DeleteCells : "Supprimer des cellules", +MergeCells : "Fusionner les cellules", +MergeRight : "Fusionner à droite", +MergeDown : "Fusionner en bas", +HorizontalSplitCell : "Scinder la cellule horizontalement", +VerticalSplitCell : "Scinder la cellule verticalement", +TableDelete : "Supprimer le tableau", +CellProperties : "Propriétés de cellule", +TableProperties : "Propriétés du tableau", +ImageProperties : "Propriétés de l'image", +FlashProperties : "Propriétés de l'animation Flash", + +AnchorProp : "Propriétés de l'ancre", +ButtonProp : "Propriétés du bouton", +CheckboxProp : "Propriétés de la case à cocher", +HiddenFieldProp : "Propriétés du champ caché", +RadioButtonProp : "Propriétés du bouton radio", +ImageButtonProp : "Propriétés du bouton image", +TextFieldProp : "Propriétés du champ texte", +SelectionFieldProp : "Propriétés de la liste/du menu", +TextareaProp : "Propriétés de la zone de texte", +FormProp : "Propriétés du formulaire", + +FontFormats : "Normal;Formaté;Adresse;En-tête 1;En-tête 2;En-tête 3;En-tête 4;En-tête 5;En-tête 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Calcul XHTML. Veuillez patienter...", +Done : "Terminé", +PasteWordConfirm : "Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller?", +NotCompatiblePaste : "Cette commande nécessite Internet Explorer version 5.5 minimum. Souhaitez-vous coller sans nettoyage?", +UnknownToolbarItem : "Elément de barre d'outil inconnu \"%1\"", +UnknownCommand : "Nom de commande inconnu \"%1\"", +NotImplemented : "Commande non encore écrite", +UnknownToolbarSet : "La barre d'outils \"%1\" n'existe pas", +NoActiveX : "Les paramètres de sécurité de votre navigateur peuvent limiter quelques fonctionnalités de l'éditeur. Veuillez activer l'option \"Exécuter les contrôles ActiveX et les plug-ins\". Il se peut que vous rencontriez des erreurs et remarquiez quelques limitations.", +BrowseServerBlocked : "Le navigateur n'a pas pu être ouvert. Assurez-vous que les bloqueurs de popups soient désactivés.", +DialogBlocked : "La fenêtre de dialogue n'a pas pu s'ouvrir. Assurez-vous que les bloqueurs de popups soient désactivés.", +VisitLinkBlocked : "Impossible d'ouvrir une nouvelle fenêtre. Assurez-vous que les bloqueurs de popups soient désactivés.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Annuler", +DlgBtnClose : "Fermer", +DlgBtnBrowseServer : "Parcourir le serveur", +DlgAdvancedTag : "Avancé", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Veuillez saisir l'URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Sens d'écriture", +DlgGenLangDirLtr : "De gauche à droite (LTR)", +DlgGenLangDirRtl : "De droite à gauche (RTL)", +DlgGenLangCode : "Code langue", +DlgGenAccessKey : "Equivalent clavier", +DlgGenName : "Nom", +DlgGenTabIndex : "Ordre de tabulation", +DlgGenLongDescr : "URL de description longue", +DlgGenClass : "Classes de feuilles de style", +DlgGenTitle : "Titre", +DlgGenContType : "Type de contenu", +DlgGenLinkCharset : "Encodage de caractère", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "Propriétés de l'image", +DlgImgInfoTab : "Informations sur l'image", +DlgImgBtnUpload : "Envoyer sur le serveur", +DlgImgURL : "URL", +DlgImgUpload : "Télécharger", +DlgImgAlt : "Texte de remplacement", +DlgImgWidth : "Largeur", +DlgImgHeight : "Hauteur", +DlgImgLockRatio : "Garder les proportions", +DlgBtnResetSize : "Taille originale", +DlgImgBorder : "Bordure", +DlgImgHSpace : "Espacement horizontal", +DlgImgVSpace : "Espacement vertical", +DlgImgAlign : "Alignement", +DlgImgAlignLeft : "Gauche", +DlgImgAlignAbsBottom: "Abs Bas", +DlgImgAlignAbsMiddle: "Abs Milieu", +DlgImgAlignBaseline : "Bas du texte", +DlgImgAlignBottom : "Bas", +DlgImgAlignMiddle : "Milieu", +DlgImgAlignRight : "Droite", +DlgImgAlignTextTop : "Haut du texte", +DlgImgAlignTop : "Haut", +DlgImgPreview : "Prévisualisation", +DlgImgAlertUrl : "Veuillez saisir l'URL de l'image", +DlgImgLinkTab : "Lien", + +// Flash Dialog +DlgFlashTitle : "Propriétés de l'animation Flash", +DlgFlashChkPlay : "Lecture automatique", +DlgFlashChkLoop : "Boucle", +DlgFlashChkMenu : "Activer le menu Flash", +DlgFlashScale : "Affichage", +DlgFlashScaleAll : "Par défaut (tout montrer)", +DlgFlashScaleNoBorder : "Sans bordure", +DlgFlashScaleFit : "Ajuster aux dimensions", + +// Link Dialog +DlgLnkWindowTitle : "Propriétés du lien", +DlgLnkInfoTab : "Informations sur le lien", +DlgLnkTargetTab : "Destination", + +DlgLnkType : "Type de lien", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Ancre dans cette page", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocole", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Sélectionner une ancre", +DlgLnkAnchorByName : "Par nom", +DlgLnkAnchorById : "Par id", +DlgLnkNoAnchors : "(Pas d'ancre disponible dans le document)", +DlgLnkEMail : "Adresse E-Mail", +DlgLnkEMailSubject : "Sujet du message", +DlgLnkEMailBody : "Corps du message", +DlgLnkUpload : "Télécharger", +DlgLnkBtnUpload : "Envoyer sur le serveur", + +DlgLnkTarget : "Destination", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nouvelle fenêtre (_blank)", +DlgLnkTargetParent : "Fenêtre mère (_parent)", +DlgLnkTargetSelf : "Même fenêtre (_self)", +DlgLnkTargetTop : "Fenêtre supérieure (_top)", +DlgLnkTargetFrameName : "Nom du cadre de destination", +DlgLnkPopWinName : "Nom de la fenêtre popup", +DlgLnkPopWinFeat : "Caractéristiques de la fenêtre popup", +DlgLnkPopResize : "Taille modifiable", +DlgLnkPopLocation : "Barre d'adresses", +DlgLnkPopMenu : "Barre de menu", +DlgLnkPopScroll : "Barres de défilement", +DlgLnkPopStatus : "Barre d'état", +DlgLnkPopToolbar : "Barre d'outils", +DlgLnkPopFullScrn : "Plein écran (IE)", +DlgLnkPopDependent : "Dépendante (Netscape)", +DlgLnkPopWidth : "Largeur", +DlgLnkPopHeight : "Hauteur", +DlgLnkPopLeft : "Position à partir de la gauche", +DlgLnkPopTop : "Position à partir du haut", + +DlnLnkMsgNoUrl : "Veuillez saisir l'URL", +DlnLnkMsgNoEMail : "Veuillez saisir l'adresse e-mail", +DlnLnkMsgNoAnchor : "Veuillez sélectionner une ancre", +DlnLnkMsgInvPopName : "Le nom de la fenêtre popup doit commencer par une lettre et ne doit pas contenir d'espace", + +// Color Dialog +DlgColorTitle : "Sélectionner", +DlgColorBtnClear : "Effacer", +DlgColorHighlight : "Prévisualisation", +DlgColorSelected : "Sélectionné", + +// Smiley Dialog +DlgSmileyTitle : "Insérer un Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Insérer un caractère spécial", + +// Table Dialog +DlgTableTitle : "Propriétés du tableau", +DlgTableRows : "Lignes", +DlgTableColumns : "Colonnes", +DlgTableBorder : "Bordure", +DlgTableAlign : "Alignement", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Gauche", +DlgTableAlignCenter : "Centré", +DlgTableAlignRight : "Droite", +DlgTableWidth : "Largeur", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "pourcentage", +DlgTableHeight : "Hauteur", +DlgTableCellSpace : "Espacement", +DlgTableCellPad : "Contour", +DlgTableCaption : "Titre", +DlgTableSummary : "Résumé", +DlgTableHeaders : "Entêtes", +DlgTableHeadersNone : "Sans", +DlgTableHeadersColumn : "Première colonne", +DlgTableHeadersRow : "Première Ligne", +DlgTableHeadersBoth : "Les 2", + +// Table Cell Dialog +DlgCellTitle : "Propriétés de la cellule", +DlgCellWidth : "Largeur", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "pourcentage", +DlgCellHeight : "Hauteur", +DlgCellWordWrap : "Retour à la ligne", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Oui", +DlgCellWordWrapNo : "Non", +DlgCellHorAlign : "Alignement horizontal", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Gauche", +DlgCellHorAlignCenter : "Centré", +DlgCellHorAlignRight: "Droite", +DlgCellVerAlign : "Alignement vertical", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Haut", +DlgCellVerAlignMiddle : "Milieu", +DlgCellVerAlignBottom : "Bas", +DlgCellVerAlignBaseline : "Bas du texte", +DlgCellType : "Type de Cellule", +DlgCellTypeData : "Données", +DlgCellTypeHeader : "Entête", +DlgCellRowSpan : "Lignes fusionnées", +DlgCellCollSpan : "Colonnes fusionnées", +DlgCellBackColor : "Fond", +DlgCellBorderColor : "Bordure", +DlgCellBtnSelect : "Choisir...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Chercher et Remplacer", + +// Find Dialog +DlgFindTitle : "Chercher", +DlgFindFindBtn : "Chercher", +DlgFindNotFoundMsg : "Le texte indiqué est introuvable.", + +// Replace Dialog +DlgReplaceTitle : "Remplacer", +DlgReplaceFindLbl : "Rechercher:", +DlgReplaceReplaceLbl : "Remplacer par:", +DlgReplaceCaseChk : "Respecter la casse", +DlgReplaceReplaceBtn : "Remplacer", +DlgReplaceReplAllBtn : "Tout remplacer", +DlgReplaceWordChk : "Mot entier", + +// Paste Operations / Dialog +PasteErrorCut : "Les paramètres de sécurité de votre navigateur empêchent l'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl+X).", +PasteErrorCopy : "Les paramètres de sécurité de votre navigateur empêchent l'éditeur de copier automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl+C).", + +PasteAsText : "Coller comme texte", +PasteFromWord : "Coller à partir de Word", + +DlgPasteMsg2 : "Veuillez coller dans la zone ci-dessous en utilisant le clavier (Ctrl+V) et cliquez sur OK.", +DlgPasteSec : "A cause des paramètres de sécurité de votre navigateur, l'éditeur ne peut accéder au presse-papier directement. Vous devez coller à nouveau le contenu dans cette fenêtre.", +DlgPasteIgnoreFont : "Ignorer les polices de caractères", +DlgPasteRemoveStyles : "Supprimer les styles", + +// Color Picker +ColorAutomatic : "Automatique", +ColorMoreColors : "Plus de couleurs...", + +// Document Properties +DocProps : "Propriétés du document", + +// Anchor Dialog +DlgAnchorTitle : "Propriétés de l'ancre", +DlgAnchorName : "Nom de l'ancre", +DlgAnchorErrorName : "Veuillez saisir le nom de l'ancre", + +// Speller Pages Dialog +DlgSpellNotInDic : "Pas dans le dictionnaire", +DlgSpellChangeTo : "Changer en", +DlgSpellBtnIgnore : "Ignorer", +DlgSpellBtnIgnoreAll : "Ignorer tout", +DlgSpellBtnReplace : "Remplacer", +DlgSpellBtnReplaceAll : "Remplacer tout", +DlgSpellBtnUndo : "Annuler", +DlgSpellNoSuggestions : "- Aucune suggestion -", +DlgSpellProgress : "Vérification d'orthographe en cours...", +DlgSpellNoMispell : "Vérification d'orthographe terminée: Aucune erreur trouvée", +DlgSpellNoChanges : "Vérification d'orthographe terminée: Pas de modifications", +DlgSpellOneChange : "Vérification d'orthographe terminée: Un mot modifié", +DlgSpellManyChanges : "Vérification d'orthographe terminée: %1 mots modifiés", + +IeSpellDownload : "Le Correcteur n'est pas installé. Souhaitez-vous le télécharger maintenant?", + +// Button Dialog +DlgButtonText : "Texte (valeur)", +DlgButtonType : "Type", +DlgButtonTypeBtn : "Bouton", +DlgButtonTypeSbm : "Envoyer", +DlgButtonTypeRst : "Réinitialiser", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nom", +DlgCheckboxValue : "Valeur", +DlgCheckboxSelected : "Sélectionné", + +// Form Dialog +DlgFormName : "Nom", +DlgFormAction : "Action", +DlgFormMethod : "Méthode", + +// Select Field Dialog +DlgSelectName : "Nom", +DlgSelectValue : "Valeur", +DlgSelectSize : "Taille", +DlgSelectLines : "lignes", +DlgSelectChkMulti : "Sélection multiple", +DlgSelectOpAvail : "Options disponibles", +DlgSelectOpText : "Texte", +DlgSelectOpValue : "Valeur", +DlgSelectBtnAdd : "Ajouter", +DlgSelectBtnModify : "Modifier", +DlgSelectBtnUp : "Monter", +DlgSelectBtnDown : "Descendre", +DlgSelectBtnSetValue : "Valeur sélectionnée", +DlgSelectBtnDelete : "Supprimer", + +// Textarea Dialog +DlgTextareaName : "Nom", +DlgTextareaCols : "Colonnes", +DlgTextareaRows : "Lignes", + +// Text Field Dialog +DlgTextName : "Nom", +DlgTextValue : "Valeur", +DlgTextCharWidth : "Largeur en caractères", +DlgTextMaxChars : "Nombre maximum de caractères", +DlgTextType : "Type", +DlgTextTypeText : "Texte", +DlgTextTypePass : "Mot de passe", + +// Hidden Field Dialog +DlgHiddenName : "Nom", +DlgHiddenValue : "Valeur", + +// Bulleted List Dialog +BulletedListProp : "Propriétés de liste à puces", +NumberedListProp : "Propriétés de liste numérotée", +DlgLstStart : "Début", +DlgLstType : "Type", +DlgLstTypeCircle : "Cercle", +DlgLstTypeDisc : "Disque", +DlgLstTypeSquare : "Carré", +DlgLstTypeNumbers : "Nombres (1, 2, 3)", +DlgLstTypeLCase : "Lettres minuscules (a, b, c)", +DlgLstTypeUCase : "Lettres majuscules (A, B, C)", +DlgLstTypeSRoman : "Chiffres romains minuscules (i, ii, iii)", +DlgLstTypeLRoman : "Chiffres romains majuscules (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Général", +DlgDocBackTab : "Fond", +DlgDocColorsTab : "Couleurs et marges", +DlgDocMetaTab : "Métadonnées", + +DlgDocPageTitle : "Titre de la page", +DlgDocLangDir : "Sens d'écriture", +DlgDocLangDirLTR : "De la gauche vers la droite (LTR)", +DlgDocLangDirRTL : "De la droite vers la gauche (RTL)", +DlgDocLangCode : "Code langue", +DlgDocCharSet : "Encodage de caractère", +DlgDocCharSetCE : "Europe Centrale", +DlgDocCharSetCT : "Chinois Traditionnel (Big5)", +DlgDocCharSetCR : "Cyrillique", +DlgDocCharSetGR : "Grec", +DlgDocCharSetJP : "Japonais", +DlgDocCharSetKR : "Coréen", +DlgDocCharSetTR : "Turc", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Occidental", +DlgDocCharSetOther : "Autre encodage de caractère", + +DlgDocDocType : "Type de document", +DlgDocDocTypeOther : "Autre type de document", +DlgDocIncXHTML : "Inclure les déclarations XHTML", +DlgDocBgColor : "Couleur de fond", +DlgDocBgImage : "Image de fond", +DlgDocBgNoScroll : "Image fixe sans défilement", +DlgDocCText : "Texte", +DlgDocCLink : "Lien", +DlgDocCVisited : "Lien visité", +DlgDocCActive : "Lien activé", +DlgDocMargins : "Marges", +DlgDocMaTop : "Haut", +DlgDocMaLeft : "Gauche", +DlgDocMaRight : "Droite", +DlgDocMaBottom : "Bas", +DlgDocMeIndex : "Mots-clés (séparés par des virgules)", +DlgDocMeDescr : "Description", +DlgDocMeAuthor : "Auteur", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Prévisualisation", + +// Templates Dialog +Templates : "Modèles", +DlgTemplatesTitle : "Modèles de contenu", +DlgTemplatesSelMsg : "Veuillez sélectionner le modèle à ouvrir dans l'éditeur
    (le contenu actuel sera remplacé):", +DlgTemplatesLoading : "Chargement de la liste des modèles. Veuillez patienter...", +DlgTemplatesNoTpl : "(Aucun modèle disponible)", +DlgTemplatesReplace : "Remplacer tout le contenu", + +// About Dialog +DlgAboutAboutTab : "A propos de", +DlgAboutBrowserInfoTab : "Navigateur", +DlgAboutLicenseTab : "Licence", +DlgAboutVersion : "Version", +DlgAboutInfo : "Pour plus d'informations, aller à", + +// Div Dialog +DlgDivGeneralTab : "Général", +DlgDivAdvancedTab : "Avancé", +DlgDivStyle : "Style", +DlgDivInlineStyle : "Attribut Style", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/gl.js b/www/js/FCKeditor/editor/lang/gl.js new file mode 100644 index 0000000..46a8c1e --- /dev/null +++ b/www/js/FCKeditor/editor/lang/gl.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Galician language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Ocultar Ferramentas", +ToolbarExpand : "Mostrar Ferramentas", + +// Toolbar Items and Context Menu +Save : "Gardar", +NewPage : "Nova Páxina", +Preview : "Vista Previa", +Cut : "Cortar", +Copy : "Copiar", +Paste : "Pegar", +PasteText : "Pegar como texto plano", +PasteWord : "Pegar dende Word", +Print : "Imprimir", +SelectAll : "Seleccionar todo", +RemoveFormat : "Eliminar Formato", +InsertLinkLbl : "Ligazón", +InsertLink : "Inserir/Editar Ligazón", +RemoveLink : "Eliminar Ligazón", +VisitLink : "Open Link", //MISSING +Anchor : "Inserir/Editar Referencia", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "Imaxe", +InsertImage : "Inserir/Editar Imaxe", +InsertFlashLbl : "Flash", +InsertFlash : "Inserir/Editar Flash", +InsertTableLbl : "Tabla", +InsertTable : "Inserir/Editar Tabla", +InsertLineLbl : "Liña", +InsertLine : "Inserir Liña Horizontal", +InsertSpecialCharLbl: "Carácter Special", +InsertSpecialChar : "Inserir Carácter Especial", +InsertSmileyLbl : "Smiley", +InsertSmiley : "Inserir Smiley", +About : "Acerca de FCKeditor", +Bold : "Negrita", +Italic : "Cursiva", +Underline : "Sub-raiado", +StrikeThrough : "Tachado", +Subscript : "Subíndice", +Superscript : "Superíndice", +LeftJustify : "Aliñar á Esquerda", +CenterJustify : "Centrado", +RightJustify : "Aliñar á Dereita", +BlockJustify : "Xustificado", +DecreaseIndent : "Disminuir Sangría", +IncreaseIndent : "Aumentar Sangría", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Desfacer", +Redo : "Refacer", +NumberedListLbl : "Lista Numerada", +NumberedList : "Inserir/Eliminar Lista Numerada", +BulletedListLbl : "Marcas", +BulletedList : "Inserir/Eliminar Marcas", +ShowTableBorders : "Mostrar Bordes das Táboas", +ShowDetails : "Mostrar Marcas Parágrafo", +Style : "Estilo", +FontFormat : "Formato", +Font : "Tipo", +FontSize : "Tamaño", +TextColor : "Cor do Texto", +BGColor : "Cor do Fondo", +Source : "Código Fonte", +Find : "Procurar", +Replace : "Substituir", +SpellCheck : "Corrección Ortográfica", +UniversalKeyboard : "Teclado Universal", +PageBreakLbl : "Salto de Páxina", +PageBreak : "Inserir Salto de Páxina", + +Form : "Formulario", +Checkbox : "Cadro de Verificación", +RadioButton : "Botón de Radio", +TextField : "Campo de Texto", +Textarea : "Ãrea de Texto", +HiddenField : "Campo Oculto", +Button : "Botón", +SelectionField : "Campo de Selección", +ImageButton : "Botón de Imaxe", + +FitWindow : "Maximizar o tamaño do editor", +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Editar Ligazón", +CellCM : "Cela", +RowCM : "Fila", +ColumnCM : "Columna", +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "Borrar Filas", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "Borrar Columnas", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "Borrar Cela", +MergeCells : "Unir Celas", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "Borrar Táboa", +CellProperties : "Propriedades da Cela", +TableProperties : "Propriedades da Táboa", +ImageProperties : "Propriedades Imaxe", +FlashProperties : "Propriedades Flash", + +AnchorProp : "Propriedades da Referencia", +ButtonProp : "Propriedades do Botón", +CheckboxProp : "Propriedades do Cadro de Verificación", +HiddenFieldProp : "Propriedades do Campo Oculto", +RadioButtonProp : "Propriedades do Botón de Radio", +ImageButtonProp : "Propriedades do Botón de Imaxe", +TextFieldProp : "Propriedades do Campo de Texto", +SelectionFieldProp : "Propriedades do Campo de Selección", +TextareaProp : "Propriedades da Ãrea de Texto", +FormProp : "Propriedades do Formulario", + +FontFormats : "Normal;Formateado;Enderezo;Enacabezado 1;Encabezado 2;Encabezado 3;Encabezado 4;Encabezado 5;Encabezado 6;Paragraph (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Procesando XHTML. Por facor, agarde...", +Done : "Feiro", +PasteWordConfirm : "Parece que o texto que quere pegar está copiado do Word.¿Quere limpar o formato antes de pegalo?", +NotCompatiblePaste : "Este comando está disponible para Internet Explorer versión 5.5 ou superior. ¿Quere pegalo sen limpar o formato?", +UnknownToolbarItem : "Ãtem de ferramentas descoñecido \"%1\"", +UnknownCommand : "Nome de comando descoñecido \"%1\"", +NotImplemented : "Comando non implementado", +UnknownToolbarSet : "O conxunto de ferramentas \"%1\" non existe", +NoActiveX : "As opcións de seguridade do seu navegador poderían limitar algunha das características de editor. Debe activar a opción \"Executar controis ActiveX e plug-ins\". Pode notar que faltan características e experimentar erros", +BrowseServerBlocked : "Non se poido abrir o navegador de recursos. Asegúrese de que están desactivados os bloqueadores de xanelas emerxentes", +DialogBlocked : "Non foi posible abrir a xanela de diálogo. Asegúrese de que están desactivados os bloqueadores de xanelas emerxentes", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Cancelar", +DlgBtnClose : "Pechar", +DlgBtnBrowseServer : "Navegar no Servidor", +DlgAdvancedTag : "Advanzado", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Por favor, insira a URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Orientación do Idioma", +DlgGenLangDirLtr : "Esquerda a Dereita (LTR)", +DlgGenLangDirRtl : "Dereita a Esquerda (RTL)", +DlgGenLangCode : "Código do Idioma", +DlgGenAccessKey : "Chave de Acceso", +DlgGenName : "Nome", +DlgGenTabIndex : "Ãndice de Tabulación", +DlgGenLongDescr : "Descrición Completa da URL", +DlgGenClass : "Clases da Folla de Estilos", +DlgGenTitle : "Título", +DlgGenContType : "Tipo de Contido", +DlgGenLinkCharset : "Fonte de Caracteres Vinculado", +DlgGenStyle : "Estilo", + +// Image Dialog +DlgImgTitle : "Propriedades da Imaxe", +DlgImgInfoTab : "Información da Imaxe", +DlgImgBtnUpload : "Enviar ó Servidor", +DlgImgURL : "URL", +DlgImgUpload : "Carregar", +DlgImgAlt : "Texto Alternativo", +DlgImgWidth : "Largura", +DlgImgHeight : "Altura", +DlgImgLockRatio : "Proporcional", +DlgBtnResetSize : "Tamaño Orixinal", +DlgImgBorder : "Límite", +DlgImgHSpace : "Esp. Horiz.", +DlgImgVSpace : "Esp. Vert.", +DlgImgAlign : "Aliñamento", +DlgImgAlignLeft : "Esquerda", +DlgImgAlignAbsBottom: "Abs Inferior", +DlgImgAlignAbsMiddle: "Abs Centro", +DlgImgAlignBaseline : "Liña Base", +DlgImgAlignBottom : "Pé", +DlgImgAlignMiddle : "Centro", +DlgImgAlignRight : "Dereita", +DlgImgAlignTextTop : "Tope do Texto", +DlgImgAlignTop : "Tope", +DlgImgPreview : "Vista Previa", +DlgImgAlertUrl : "Por favor, escriba a URL da imaxe", +DlgImgLinkTab : "Ligazón", + +// Flash Dialog +DlgFlashTitle : "Propriedades Flash", +DlgFlashChkPlay : "Auto Execución", +DlgFlashChkLoop : "Bucle", +DlgFlashChkMenu : "Activar Menú Flash", +DlgFlashScale : "Escalar", +DlgFlashScaleAll : "Amosar Todo", +DlgFlashScaleNoBorder : "Sen Borde", +DlgFlashScaleFit : "Encaixar axustando", + +// Link Dialog +DlgLnkWindowTitle : "Ligazón", +DlgLnkInfoTab : "Información da Ligazón", +DlgLnkTargetTab : "Referencia a esta páxina", + +DlgLnkType : "Tipo de Ligazón", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Referencia nesta páxina", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocolo", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Seleccionar unha Referencia", +DlgLnkAnchorByName : "Por Nome de Referencia", +DlgLnkAnchorById : "Por Element Id", +DlgLnkNoAnchors : "(Non hai referencias disponibles no documento)", +DlgLnkEMail : "Enderezo de E-Mail", +DlgLnkEMailSubject : "Asunto do Mensaxe", +DlgLnkEMailBody : "Corpo do Mensaxe", +DlgLnkUpload : "Carregar", +DlgLnkBtnUpload : "Enviar ó servidor", + +DlgLnkTarget : "Destino", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nova Xanela (_blank)", +DlgLnkTargetParent : "Xanela Pai (_parent)", +DlgLnkTargetSelf : "Mesma Xanela (_self)", +DlgLnkTargetTop : "Xanela Primaria (_top)", +DlgLnkTargetFrameName : "Nome do Marco Destino", +DlgLnkPopWinName : "Nome da Xanela Emerxente", +DlgLnkPopWinFeat : "Características da Xanela Emerxente", +DlgLnkPopResize : "Axustable", +DlgLnkPopLocation : "Barra de Localización", +DlgLnkPopMenu : "Barra de Menú", +DlgLnkPopScroll : "Barras de Desplazamento", +DlgLnkPopStatus : "Barra de Estado", +DlgLnkPopToolbar : "Barra de Ferramentas", +DlgLnkPopFullScrn : "A Toda Pantalla (IE)", +DlgLnkPopDependent : "Dependente (Netscape)", +DlgLnkPopWidth : "Largura", +DlgLnkPopHeight : "Altura", +DlgLnkPopLeft : "Posición Esquerda", +DlgLnkPopTop : "Posición dende Arriba", + +DlnLnkMsgNoUrl : "Por favor, escriba a ligazón URL", +DlnLnkMsgNoEMail : "Por favor, escriba o enderezo de e-mail", +DlnLnkMsgNoAnchor : "Por favor, seleccione un destino", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING + +// Color Dialog +DlgColorTitle : "Seleccionar Color", +DlgColorBtnClear : "Nengunha", +DlgColorHighlight : "Destacado", +DlgColorSelected : "Seleccionado", + +// Smiley Dialog +DlgSmileyTitle : "Inserte un Smiley", + +// Special Character Dialog +DlgSpecialCharTitle : "Seleccione Caracter Especial", + +// Table Dialog +DlgTableTitle : "Propiedades da Táboa", +DlgTableRows : "Filas", +DlgTableColumns : "Columnas", +DlgTableBorder : "Tamaño do Borde", +DlgTableAlign : "Aliñamento", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Esquerda", +DlgTableAlignCenter : "Centro", +DlgTableAlignRight : "Ereita", +DlgTableWidth : "Largura", +DlgTableWidthPx : "pixels", +DlgTableWidthPc : "percent", +DlgTableHeight : "Altura", +DlgTableCellSpace : "Marxe entre Celas", +DlgTableCellPad : "Marxe interior", +DlgTableCaption : "Título", +DlgTableSummary : "Sumario", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Propriedades da Cela", +DlgCellWidth : "Largura", +DlgCellWidthPx : "pixels", +DlgCellWidthPc : "percent", +DlgCellHeight : "Altura", +DlgCellWordWrap : "Axustar Liñas", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Si", +DlgCellWordWrapNo : "Non", +DlgCellHorAlign : "Aliñamento Horizontal", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Esquerda", +DlgCellHorAlignCenter : "Centro", +DlgCellHorAlignRight: "Dereita", +DlgCellVerAlign : "Aliñamento Vertical", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Arriba", +DlgCellVerAlignMiddle : "Medio", +DlgCellVerAlignBottom : "Abaixo", +DlgCellVerAlignBaseline : "Liña de Base", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Ocupar Filas", +DlgCellCollSpan : "Ocupar Columnas", +DlgCellBackColor : "Color de Fondo", +DlgCellBorderColor : "Color de Borde", +DlgCellBtnSelect : "Seleccionar...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "Procurar", +DlgFindFindBtn : "Procurar", +DlgFindNotFoundMsg : "Non te atopou o texto indicado.", + +// Replace Dialog +DlgReplaceTitle : "Substituir", +DlgReplaceFindLbl : "Texto a procurar:", +DlgReplaceReplaceLbl : "Substituir con:", +DlgReplaceCaseChk : "Coincidir Mai./min.", +DlgReplaceReplaceBtn : "Substituir", +DlgReplaceReplAllBtn : "Substitiur Todo", +DlgReplaceWordChk : "Coincidir con toda a palabra", + +// Paste Operations / Dialog +PasteErrorCut : "Os axustes de seguridade do seu navegador non permiten que o editor realice automáticamente as tarefas de corte. Por favor, use o teclado para iso (Ctrl+X).", +PasteErrorCopy : "Os axustes de seguridade do seu navegador non permiten que o editor realice automáticamente as tarefas de copia. Por favor, use o teclado para iso (Ctrl+C).", + +PasteAsText : "Pegar como texto plano", +PasteFromWord : "Pegar dende Word", + +DlgPasteMsg2 : "Por favor, pegue dentro do seguinte cadro usando o teclado (Ctrl+V) e pulse OK.", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "Ignorar as definicións de Tipografía", +DlgPasteRemoveStyles : "Eliminar as definicións de Estilos", + +// Color Picker +ColorAutomatic : "Automático", +ColorMoreColors : "Máis Cores...", + +// Document Properties +DocProps : "Propriedades do Documento", + +// Anchor Dialog +DlgAnchorTitle : "Propriedades da Referencia", +DlgAnchorName : "Nome da Referencia", +DlgAnchorErrorName : "Por favor, escriba o nome da referencia", + +// Speller Pages Dialog +DlgSpellNotInDic : "Non está no diccionario", +DlgSpellChangeTo : "Cambiar a", +DlgSpellBtnIgnore : "Ignorar", +DlgSpellBtnIgnoreAll : "Ignorar Todas", +DlgSpellBtnReplace : "Substituir", +DlgSpellBtnReplaceAll : "Substituir Todas", +DlgSpellBtnUndo : "Desfacer", +DlgSpellNoSuggestions : "- Sen candidatos -", +DlgSpellProgress : "Corrección ortográfica en progreso...", +DlgSpellNoMispell : "Corrección ortográfica rematada: Non se atoparon erros", +DlgSpellNoChanges : "Corrección ortográfica rematada: Non se substituiu nengunha verba", +DlgSpellOneChange : "Corrección ortográfica rematada: Unha verba substituida", +DlgSpellManyChanges : "Corrección ortográfica rematada: %1 verbas substituidas", + +IeSpellDownload : "O corrector ortográfico non está instalado. ¿Quere descargalo agora?", + +// Button Dialog +DlgButtonText : "Texto (Valor)", +DlgButtonType : "Tipo", +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nome", +DlgCheckboxValue : "Valor", +DlgCheckboxSelected : "Seleccionado", + +// Form Dialog +DlgFormName : "Nome", +DlgFormAction : "Acción", +DlgFormMethod : "Método", + +// Select Field Dialog +DlgSelectName : "Nome", +DlgSelectValue : "Valor", +DlgSelectSize : "Tamaño", +DlgSelectLines : "liñas", +DlgSelectChkMulti : "Permitir múltiples seleccións", +DlgSelectOpAvail : "Opcións Disponibles", +DlgSelectOpText : "Texto", +DlgSelectOpValue : "Valor", +DlgSelectBtnAdd : "Engadir", +DlgSelectBtnModify : "Modificar", +DlgSelectBtnUp : "Subir", +DlgSelectBtnDown : "Baixar", +DlgSelectBtnSetValue : "Definir como valor por defecto", +DlgSelectBtnDelete : "Borrar", + +// Textarea Dialog +DlgTextareaName : "Nome", +DlgTextareaCols : "Columnas", +DlgTextareaRows : "Filas", + +// Text Field Dialog +DlgTextName : "Nome", +DlgTextValue : "Valor", +DlgTextCharWidth : "Tamaño do Caracter", +DlgTextMaxChars : "Máximo de Caracteres", +DlgTextType : "Tipo", +DlgTextTypeText : "Texto", +DlgTextTypePass : "Chave", + +// Hidden Field Dialog +DlgHiddenName : "Nome", +DlgHiddenValue : "Valor", + +// Bulleted List Dialog +BulletedListProp : "Propriedades das Marcas", +NumberedListProp : "Propriedades da Lista de Numeración", +DlgLstStart : "Start", //MISSING +DlgLstType : "Tipo", +DlgLstTypeCircle : "Círculo", +DlgLstTypeDisc : "Disco", +DlgLstTypeSquare : "Cuadrado", +DlgLstTypeNumbers : "Números (1, 2, 3)", +DlgLstTypeLCase : "Letras Minúsculas (a, b, c)", +DlgLstTypeUCase : "Letras Maiúsculas (A, B, C)", +DlgLstTypeSRoman : "Números Romanos en minúscula (i, ii, iii)", +DlgLstTypeLRoman : "Números Romanos en Maiúscula (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Xeral", +DlgDocBackTab : "Fondo", +DlgDocColorsTab : "Cores e Marxes", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Título da Páxina", +DlgDocLangDir : "Orientación do Idioma", +DlgDocLangDirLTR : "Esquerda a Dereita (LTR)", +DlgDocLangDirRTL : "Dereita a Esquerda (RTL)", +DlgDocLangCode : "Código de Idioma", +DlgDocCharSet : "Codificación do Xogo de Caracteres", +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "Outra Codificación do Xogo de Caracteres", + +DlgDocDocType : "Encabezado do Tipo de Documento", +DlgDocDocTypeOther : "Outro Encabezado do Tipo de Documento", +DlgDocIncXHTML : "Incluir Declaracións XHTML", +DlgDocBgColor : "Cor de Fondo", +DlgDocBgImage : "URL da Imaxe de Fondo", +DlgDocBgNoScroll : "Fondo Fixo", +DlgDocCText : "Texto", +DlgDocCLink : "Ligazóns", +DlgDocCVisited : "Ligazón Visitada", +DlgDocCActive : "Ligazón Activa", +DlgDocMargins : "Marxes da Páxina", +DlgDocMaTop : "Arriba", +DlgDocMaLeft : "Esquerda", +DlgDocMaRight : "Dereita", +DlgDocMaBottom : "Abaixo", +DlgDocMeIndex : "Palabras Chave de Indexación do Documento (separadas por comas)", +DlgDocMeDescr : "Descripción do Documento", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Vista Previa", + +// Templates Dialog +Templates : "Plantillas", +DlgTemplatesTitle : "Plantillas de Contido", +DlgTemplatesSelMsg : "Por favor, seleccione a plantilla a abrir no editor
    (o contido actual perderase):", +DlgTemplatesLoading : "Cargando listado de plantillas. Por favor, espere...", +DlgTemplatesNoTpl : "(Non hai plantillas definidas)", +DlgTemplatesReplace : "Replace actual contents", //MISSING + +// About Dialog +DlgAboutAboutTab : "Acerca de", +DlgAboutBrowserInfoTab : "Información do Navegador", +DlgAboutLicenseTab : "Licencia", +DlgAboutVersion : "versión", +DlgAboutInfo : "Para máis información visitar:", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/gu.js b/www/js/FCKeditor/editor/lang/gu.js new file mode 100644 index 0000000..09d1da8 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/gu.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Gujarati language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "ટૂલબાર નાનà«àª‚ કરવà«àª‚", +ToolbarExpand : "ટૂલબાર મોટà«àª‚ કરવà«àª‚", + +// Toolbar Items and Context Menu +Save : "સેવ", +NewPage : "નવૠપાનà«àª‚", +Preview : "પૂરà«àªµàª¦àª°à«àª¶àª¨", +Cut : "કાપવà«àª‚", +Copy : "નકલ", +Paste : "પેસà«àªŸ", +PasteText : "પેસà«àªŸ (સાદી ટેકà«àª¸à«àªŸ)", +PasteWord : "પેસà«àªŸ (વડૅ ટેકà«àª¸à«àªŸ)", +Print : "પà«àª°àª¿àª¨à«àªŸ", +SelectAll : "બઘà«àª‚ પસંદ કરવà«àª‚", +RemoveFormat : "ફૉરà«àª®àªŸ કાઢવà«àª‚", +InsertLinkLbl : "સંબંધન, લિંક", +InsertLink : "લિંક ઇનà«àª¸àª°à«àªŸ/દાખલ કરવી", +RemoveLink : "લિંક કાઢવી", +VisitLink : "Open Link", //MISSING +Anchor : "àªàª‚કર ઇનà«àª¸àª°à«àªŸ/દાખલ કરવી", +AnchorDelete : "àªàª‚કર કાઢવી", +InsertImageLbl : "ચિતà«àª°", +InsertImage : "ચિતà«àª° ઇનà«àª¸àª°à«àªŸ/દાખલ કરવà«àª‚", +InsertFlashLbl : "ફà«àª²à«…શ", +InsertFlash : "ફà«àª²à«…શ ઇનà«àª¸àª°à«àªŸ/દાખલ કરવà«àª‚", +InsertTableLbl : "ટેબલ, કોઠો", +InsertTable : "ટેબલ, કોઠો ઇનà«àª¸àª°à«àªŸ/દાખલ કરવà«àª‚", +InsertLineLbl : "રેખા", +InsertLine : "સમસà«àª¤àª°à«€àª¯ રેખા ઇનà«àª¸àª°à«àªŸ/દાખલ કરવી", +InsertSpecialCharLbl: "વિશિષà«àªŸ અકà«àª·àª°", +InsertSpecialChar : "વિશિષà«àªŸ અકà«àª·àª° ઇનà«àª¸àª°à«àªŸ/દાખલ કરવà«àª‚", +InsertSmileyLbl : "સà«àª®àª¾àª‡àª²à«€", +InsertSmiley : "સà«àª®àª¾àª‡àª²à«€ ઇનà«àª¸àª°à«àªŸ/દાખલ કરવી", +About : "FCKeditorના વિષે", +Bold : "બોલà«àª¡/સà«àªªàª·à«àªŸ", +Italic : "ઇટેલિક, તà«àª°àª¾àª‚સા", +Underline : "અનà«àª¡àª°à«àª²àª¾àª‡àª¨, નીચે લીટી", +StrikeThrough : "છેકી નાખવà«àª‚", +Subscript : "àªàª• ચિહà«àª¨àª¨à«€ નીચે કરેલà«àª‚ બીજà«àª‚ ચિહà«àª¨", +Superscript : "àªàª• ચિહà«àª¨ ઉપર કરેલà«àª‚ બીજà«àª‚ ચિહà«àª¨.", +LeftJustify : "ડાબી બાજà«àª/બાજૠતરફ", +CenterJustify : "સંકેંદà«àª°àª£/સેંટરિંગ", +RightJustify : "જમણી બાજà«àª/બાજૠતરફ", +BlockJustify : "બà«àª²à«‰àª•, અંતરાય જસà«àªŸàª¿àª«àª¾àª‡", +DecreaseIndent : "ઇનà«àª¡à«‡àª¨à«àªŸ લીટીના આરંભમાં જગà«àª¯àª¾ ઘટાડવી", +IncreaseIndent : "ઇનà«àª¡à«‡àª¨à«àªŸ, લીટીના આરંભમાં જગà«àª¯àª¾ વધારવી", +Blockquote : "બà«àª²à«‰àª•-કોટ, અવતરણચિહà«àª¨à«‹", +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "રદ કરવà«àª‚; પહેલાં હતી àªàªµà«€ સà«àª¥àª¿àª¤àª¿ પાછી લાવવી", +Redo : "રિડૂ; પછી હતી àªàªµà«€ સà«àª¥àª¿àª¤àª¿ પાછી લાવવી", +NumberedListLbl : "સંખà«àª¯àª¾àª‚કન સૂચિ", +NumberedList : "સંખà«àª¯àª¾àª‚કન સૂચિ ઇનà«àª¸àª°à«àªŸ/દાખલ કરવી", +BulletedListLbl : "બà«àª²à«‡àªŸ સૂચિ", +BulletedList : "બà«àª²à«‡àªŸ સૂચિ ઇનà«àª¸àª°à«àªŸ/દાખલ કરવી", +ShowTableBorders : "ટેબલ, કોઠાની બાજà«(બોરà«àª¡àª°) બતાવવી", +ShowDetails : "વિસà«àª¤à«ƒàª¤ વિગતવાર બતાવવà«àª‚", +Style : "શૈલી/રીત", +FontFormat : "ફૉનà«àªŸ ફૉરà«àª®àªŸ, રચનાની શૈલી", +Font : "ફૉનà«àªŸ", +FontSize : "ફૉનà«àªŸ સાઇàª/કદ", +TextColor : "શબà«àª¦àª¨à«‹ રંગ", +BGColor : "બૅકગà«àª°àª¾àª‰àª¨à«àª¡ રંગ,", +Source : "મૂળ કે પà«àª°àª¾àª¥àª®àª¿àª• દસà«àª¤àª¾àªµà«‡àªœ", +Find : "શોધવà«àª‚", +Replace : "રિપà«àª²à«‡àª¸/બદલવà«àª‚", +SpellCheck : "જોડણી (સà«àªªà«‡àª²àª¿àª‚ગ) તપાસવી", +UniversalKeyboard : "યૂનિવરà«àª¸àª²/વિશà«àªµàªµà«àª¯àª¾àªªàª• કીબૉરà«àª¡", +PageBreakLbl : "પેજબà«àª°à«‡àª•/પાનાને અલગ કરવà«àª‚", +PageBreak : "ઇનà«àª¸àª°à«àªŸ પેજબà«àª°à«‡àª•/પાનાને અલગ કરવà«àª‚/દાખલ કરવà«àª‚", + +Form : "ફૉરà«àª®/પતà«àª°àª•", +Checkbox : "ચેક બોકà«àª¸", +RadioButton : "રેડિઓ બટન", +TextField : "ટેકà«àª¸à«àªŸ ફીલà«àª¡, શબà«àª¦ કà«àª·à«‡àª¤à«àª°", +Textarea : "ટેકà«àª¸à«àªŸ àªàª°àª¿àª†, શબà«àª¦ વિસà«àª¤àª¾àª°", +HiddenField : "ગà«àªªà«àª¤ કà«àª·à«‡àª¤à«àª°", +Button : "બટન", +SelectionField : "પસંદગી કà«àª·à«‡àª¤à«àª°", +ImageButton : "ચિતà«àª° બટન", + +FitWindow : "àªàª¡àª¿àªŸàª°àª¨à«€ સાઇઠઅધિકતમ કરવી", +ShowBlocks : "બà«àª²à«‰àª• બતાવવà«àª‚", + +// Context Menu +EditLink : " લિંક àªàª¡àª¿àªŸ/માં ફેરફાર કરવો", +CellCM : "કોષના ખાના", +RowCM : "પંકà«àª¤àª¿àª¨àª¾ ખાના", +ColumnCM : "કૉલમ/ઊભી કટાર", +InsertRowAfter : "પછી પંકà«àª¤àª¿ ઉમેરવી", +InsertRowBefore : "પહેલાં પંકà«àª¤àª¿ ઉમેરવી", +DeleteRows : "પંકà«àª¤àª¿àª“ ડિલીટ/કાઢી નાખવી", +InsertColumnAfter : "પછી કૉલમ/ઊભી કટાર ઉમેરવી", +InsertColumnBefore : "પહેલાં કૉલમ/ઊભી કટાર ઉમેરવી", +DeleteColumns : "કૉલમ/ઊભી કટાર ડિલીટ/કાઢી નાખવી", +InsertCellAfter : "પછી કોષ ઉમેરવો", +InsertCellBefore : "પહેલાં કોષ ઉમેરવો", +DeleteCells : "કોષ ડિલીટ/કાઢી નાખવો", +MergeCells : "કોષ ભેગા કરવા", +MergeRight : "જમણી બાજૠભેગા કરવા", +MergeDown : "નીચે ભેગા કરવા", +HorizontalSplitCell : "કોષને સમસà«àª¤àª°à«€àª¯ વિભાજન કરવà«àª‚", +VerticalSplitCell : "કોષને સીધà«àª‚ ને ઊભà«àª‚ વિભાજન કરવà«àª‚", +TableDelete : "કોઠો ડિલીટ/કાઢી નાખવà«àª‚", +CellProperties : "કોષના ગà«àª£", +TableProperties : "કોઠાના ગà«àª£", +ImageProperties : "ચિતà«àª°àª¨àª¾ ગà«àª£", +FlashProperties : "ફà«àª²à«…શના ગà«àª£", + +AnchorProp : "àªàª‚કરના ગà«àª£", +ButtonProp : "બટનના ગà«àª£", +CheckboxProp : "ચેક બોકà«àª¸ ગà«àª£", +HiddenFieldProp : "ગà«àªªà«àª¤ કà«àª·à«‡àª¤à«àª°àª¨àª¾ ગà«àª£", +RadioButtonProp : "રેડિઓ બટનના ગà«àª£", +ImageButtonProp : "ચિતà«àª° બટનના ગà«àª£", +TextFieldProp : "ટેકà«àª¸à«àªŸ ફીલà«àª¡, શબà«àª¦ કà«àª·à«‡àª¤à«àª°àª¨àª¾ ગà«àª£", +SelectionFieldProp : "પસંદગી કà«àª·à«‡àª¤à«àª°àª¨àª¾ ગà«àª£", +TextareaProp : "ટેકà«àª¸à«àªŸ àªàª…રિઆ, શબà«àª¦ વિસà«àª¤àª¾àª°àª¨àª¾ ગà«àª£", +FormProp : "ફૉરà«àª®/પતà«àª°àª•àª¨àª¾ ગà«àª£", + +FontFormats : "સામાનà«àª¯;ફૉરà«àª®àªŸà«‡àª¡;સરનામà«àª‚;શીરà«àª·àª• 1;શીરà«àª·àª• 2;શીરà«àª·àª• 3;શીરà«àª·àª• 4;શીરà«àª·àª• 5;શીરà«àª·àª• 6;શીરà«àª·àª• (DIV)", + +// Alerts and Messages +ProcessingXHTML : "XHTML પà«àª°àª•à«àª°àª¿àª¯àª¾ ચાલૠછે. મહેરબાની કરીને રાહ જોવો...", +Done : "પતી ગયà«àª‚", +PasteWordConfirm : "તમે જે ટેકà«àª¸à«àªŸ પેસà«àªŸ કરવા માંગો છો, તે વડૅમાંથી કોપી કરેલૠલાગે છે. પેસà«àªŸ કરતા પહેલાં ટેકà«àª¸à«àªŸ સાફ કરવી છે?", +NotCompatiblePaste : "આ કમાનà«àª¡ ઈનટરનેટ àªàª•à«àª¸àªªà«àª²à«‹àª°àª°(Internet Explorer) 5.5 અથવા àªàª¨àª¾ પછીના વરà«àªàª¨ માટેજ છે. ટેકà«àª¸à«àªŸàª¨à«‡ સાફ કયૅા પહેલાં પેસà«àªŸ કરવી છે?", +UnknownToolbarItem : "અજાણી ટૂલબાર આઇટમ \"%1\"", +UnknownCommand : "અજાણયો કમાનà«àª¡ \"%1\"", +NotImplemented : "કમાનà«àª¡ ઇમà«àªªà«àª²àª¿àª®àª¨à«àªŸ નથી કરોયો", +UnknownToolbarSet : "ટૂલબાર સેટ \"%1\" ઉપલબà«àª§ નથી", +NoActiveX : "તમારા બà«àª°àª¾àª‰àªàª°àª¨à«€ સà«àª°àª•à«àª·àª¾ સેટિંગસ àªàª¡àª¿àªŸàª°àª¨àª¾ અમà«àª• ફીચરને પરવાનગી આપતી નથી. કૃપયા \"Run ActiveX controls and plug-ins\" વિકલà«àªªàª¨à«‡ ઇનેબલ/સમરà«àª¥ કરો. તમારા બà«àª°àª¾àª‰àªàª°àª®àª¾àª‚ àªàª°àª° ઇનà«àªµàª¿àªàª¿àª¬àª² ફીચરનો અનà«àª­àªµ થઈ શકે છે. કૃપયા પૉપ-અપ બà«àª²à«‰àª•àª° ડિસેબલ કરો.", +BrowseServerBlocked : "રિસૉરà«àª¸ બà«àª°àª¾àª‰àªàª° ખોલી ન સકાયà«àª‚.", +DialogBlocked : "ડાયલૉગ વિનà«àª¡à«‹ ખોલી ન સકાયà«àª‚. કૃપયા પૉપ-અપ બà«àª²à«‰àª•àª° ડિસેબલ કરો.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "ઠીક છે", +DlgBtnCancel : "રદ કરવà«àª‚", +DlgBtnClose : "બંધ કરવà«àª‚", +DlgBtnBrowseServer : "સરà«àªµàª° બà«àª°àª¾àª‰àª કરો", +DlgAdvancedTag : "અડà«àªµàª¾àª¨à«àª¸àª¡", +DlgOpOther : "<અનà«àª¯>", +DlgInfoTab : "સૂચના", +DlgAlertUrl : "URL ઇનà«àª¸àª°à«àªŸ કરો", + +// General Dialogs Labels +DlgGenNotSet : "<સેટ નથી>", +DlgGenId : "Id", +DlgGenLangDir : "ભાષા લેખવાની પદà«àª§àª¤àª¿", +DlgGenLangDirLtr : "ડાબે થી જમણે (LTR)", +DlgGenLangDirRtl : "જમણે થી ડાબે (RTL)", +DlgGenLangCode : "ભાષા કોડ", +DlgGenAccessKey : "àªàª•à«àª¸à«‡àª¸ કી", +DlgGenName : "નામ", +DlgGenTabIndex : "ટૅબ ઇનà«àª¡à«‡àª•à«àª¸", +DlgGenLongDescr : "વધારે માહિતી માટે URL", +DlgGenClass : "સà«àªŸàª¾àª‡àª²-શીટ કà«àª²àª¾àª¸", +DlgGenTitle : "મà«àª–à«àª¯ મથાળà«àª‚", +DlgGenContType : "મà«àª–à«àª¯ કનà«àªŸà«‡àª¨à«àªŸ પà«àª°àª•àª¾àª°", +DlgGenLinkCharset : "લિંક રિસૉરà«àª¸ કૅરિકà«àªŸàª° સેટ", +DlgGenStyle : "સà«àªŸàª¾àª‡àª²", + +// Image Dialog +DlgImgTitle : "ચિતà«àª°àª¨àª¾ ગà«àª£", +DlgImgInfoTab : "ચિતà«àª° ની જાણકારી", +DlgImgBtnUpload : "આ સરà«àªµàª°àª¨à«‡ મોકલવà«àª‚", +DlgImgURL : "URL", +DlgImgUpload : "અપલોડ", +DlgImgAlt : "ઑલà«àªŸàª°à«àª¨àªŸ ટેકà«àª¸à«àªŸ", +DlgImgWidth : "પહોળાઈ", +DlgImgHeight : "ઊંચાઈ", +DlgImgLockRatio : "લૉક ગà«àª£à«‹àª¤à«àª¤àª°", +DlgBtnResetSize : "રીસેટ સાઇàª", +DlgImgBorder : "બોરà«àª¡àª°", +DlgImgHSpace : "સમસà«àª¤àª°à«€àª¯ જગà«àª¯àª¾", +DlgImgVSpace : "લંબરૂપ જગà«àª¯àª¾", +DlgImgAlign : "લાઇનદોરીમાં ગોઠવવà«àª‚", +DlgImgAlignLeft : "ડાબી બાજૠગોઠવવà«àª‚", +DlgImgAlignAbsBottom: "Abs નીચે", +DlgImgAlignAbsMiddle: "Abs ઉપર", +DlgImgAlignBaseline : "આધાર લીટી", +DlgImgAlignBottom : "નીચે", +DlgImgAlignMiddle : "વચà«àªšà«‡", +DlgImgAlignRight : "જમણી", +DlgImgAlignTextTop : "ટેકà«àª¸à«àªŸ ઉપર", +DlgImgAlignTop : "ઉપર", +DlgImgPreview : "પૂરà«àªµàª¦àª°à«àª¶àª¨", +DlgImgAlertUrl : "ચિતà«àª°àª¨à«€ URL ટાઇપ કરો", +DlgImgLinkTab : "લિંક", + +// Flash Dialog +DlgFlashTitle : "ફà«àª²à«…શ ગà«àª£", +DlgFlashChkPlay : "ઑટો/સà«àªµàª¯àª‚ પà«àª²à«‡", +DlgFlashChkLoop : "લૂપ", +DlgFlashChkMenu : "ફà«àª²à«…શ મેનà«àª¯à«‚ નો પà«àª°àª¯à«‹àª— કરો", +DlgFlashScale : "સà«àª•à«‡àª²", +DlgFlashScaleAll : "સà«àª•à«‡àª² ઓલ/બધૠબતાવો", +DlgFlashScaleNoBorder : "સà«àª•à«‡àª² બોરà«àª¡àª° વગર", +DlgFlashScaleFit : "સà«àª•à«‡àª² àªàª•àª¦àª® ફીટ", + +// Link Dialog +DlgLnkWindowTitle : "લિંક", +DlgLnkInfoTab : "લિંક ઇનà«àª«à«‰ ટૅબ", +DlgLnkTargetTab : "ટારà«àª—ેટ/લકà«àª·à«àª¯ ટૅબ", + +DlgLnkType : "લિંક પà«àª°àª•àª¾àª°", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "આ પેજનો àªàª‚કર", +DlgLnkTypeEMail : "ઈ-મેલ", +DlgLnkProto : "પà«àª°à«‹àªŸà«‹àª•à«‰àª²", +DlgLnkProtoOther : "<અનà«àª¯>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "àªàª‚કર પસંદ કરો", +DlgLnkAnchorByName : "àªàª‚કર નામથી પસંદ કરો", +DlgLnkAnchorById : "àªàª‚કર àªàª²àª¿àª®àª¨à«àªŸ Id થી પસંદ કરો", +DlgLnkNoAnchors : "(ડૉકà«àª¯à«àª®àª¨à«àªŸàª®àª¾àª‚ àªàª‚કરની સંખà«àª¯àª¾)", +DlgLnkEMail : "ઈ-મેલ સરનામà«àª‚", +DlgLnkEMailSubject : "ઈ-મેલ વિષય", +DlgLnkEMailBody : "સંદેશ", +DlgLnkUpload : "અપલોડ", +DlgLnkBtnUpload : "આ સરà«àªµàª°àª¨à«‡ મોકલવà«àª‚", + +DlgLnkTarget : "ટારà«àª—ેટ/લકà«àª·à«àª¯", +DlgLnkTargetFrame : "<ફà«àª°à«‡àª®>", +DlgLnkTargetPopup : "<પૉપ-અપ વિનà«àª¡à«‹>", +DlgLnkTargetBlank : "નવી વિનà«àª¡à«‹ (_blank)", +DlgLnkTargetParent : "મૂળ વિનà«àª¡à«‹ (_parent)", +DlgLnkTargetSelf : "આજ વિનà«àª¡à«‹ (_self)", +DlgLnkTargetTop : "ઉપરની વિનà«àª¡à«‹ (_top)", +DlgLnkTargetFrameName : "ટારà«àª—ેટ ફà«àª°à«‡àª® નà«àª‚ નામ", +DlgLnkPopWinName : "પૉપ-અપ વિનà«àª¡à«‹ નà«àª‚ નામ", +DlgLnkPopWinFeat : "પૉપ-અપ વિનà«àª¡à«‹ ફીચરસૅ", +DlgLnkPopResize : "સાઇઠબદલી સકાય છે", +DlgLnkPopLocation : "લોકેશન બાર", +DlgLnkPopMenu : "મેનà«àª¯à«‚ બાર", +DlgLnkPopScroll : "સà«àª•à«àª°à«‹àª² બાર", +DlgLnkPopStatus : "સà«àªŸà«…ટસ બાર", +DlgLnkPopToolbar : "ટૂલ બાર", +DlgLnkPopFullScrn : "ફà«àª² સà«àª•à«àª°à«€àª¨ (IE)", +DlgLnkPopDependent : "ડિપેનà«àª¡àª¨à«àªŸ (Netscape)", +DlgLnkPopWidth : "પહોળાઈ", +DlgLnkPopHeight : "ઊંચાઈ", +DlgLnkPopLeft : "ડાબી બાજà«", +DlgLnkPopTop : "જમણી બાજà«", + +DlnLnkMsgNoUrl : "લિંક URL ટાઇપ કરો", +DlnLnkMsgNoEMail : "ઈ-મેલ સરનામà«àª‚ ટાઇપ કરો", +DlnLnkMsgNoAnchor : "àªàª‚કર પસંદ કરો", +DlnLnkMsgInvPopName : "પૉપ-અપ વિનà«àª¡à«‹ નà«àª‚ નામ àªàª²à«àª«àª¬à«‡àªŸàª¥à«€ શરૂ કરવો અને તેમાં સà«àªªà«‡àª‡àª¸ ન હોવી જોઈàª", + +// Color Dialog +DlgColorTitle : "રંગ પસંદ કરો", +DlgColorBtnClear : "સાફ કરો", +DlgColorHighlight : "હાઈલાઇટ", +DlgColorSelected : "સિલેકà«àªŸà«‡àª¡/પસંદ કરવà«àª‚", + +// Smiley Dialog +DlgSmileyTitle : "સà«àª®àª¾àª‡àª²à«€ પસંદ કરો", + +// Special Character Dialog +DlgSpecialCharTitle : "સà«àªªà«‡àª¶àª¿àª…લ વિશિષà«àªŸ અકà«àª·àª° પસંદ કરો", + +// Table Dialog +DlgTableTitle : "ટેબલ, કોઠાનà«àª‚ મથાળà«àª‚", +DlgTableRows : "પંકà«àª¤àª¿àª¨àª¾ ખાના", +DlgTableColumns : "કૉલમ/ઊભી કટાર", +DlgTableBorder : "કોઠાની બાજà«(બોરà«àª¡àª°) સાઇàª", +DlgTableAlign : "અલાઇનમનà«àªŸ/ગોઠવાયેલà«àª‚ ", +DlgTableAlignNotSet : "<સેટ નથી>", +DlgTableAlignLeft : "ડાબી બાજà«", +DlgTableAlignCenter : "મધà«àª¯ સેનà«àªŸàª°", +DlgTableAlignRight : "જમણી બાજà«", +DlgTableWidth : "પહોળાઈ", +DlgTableWidthPx : "પિકસલ", +DlgTableWidthPc : "પà«àª°àª¤àª¿àª¶àª¤", +DlgTableHeight : "ઊંચાઈ", +DlgTableCellSpace : "સેલ અંતર", +DlgTableCellPad : "સેલ પૅડિંગ", +DlgTableCaption : "મથાળà«àª‚/કૅપà«àª¶àª¨ ", +DlgTableSummary : "ટૂંકો àªàª¹à«‡àªµàª¾àª²", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "પંકà«àª¤àª¿àª¨àª¾ ખાનાના ગà«àª£", +DlgCellWidth : "પહોળાઈ", +DlgCellWidthPx : "પિકસલ", +DlgCellWidthPc : "પà«àª°àª¤àª¿àª¶àª¤", +DlgCellHeight : "ઊંચાઈ", +DlgCellWordWrap : "વરà«àª¡ રૅપ", +DlgCellWordWrapNotSet : "<સેટ નથી>", +DlgCellWordWrapYes : "હા", +DlgCellWordWrapNo : "ના", +DlgCellHorAlign : "સમસà«àª¤àª°à«€àª¯ ગોઠવવà«àª‚", +DlgCellHorAlignNotSet : "<સેટ નથી>", +DlgCellHorAlignLeft : "ડાબી બાજà«", +DlgCellHorAlignCenter : "મધà«àª¯ સેનà«àªŸàª°", +DlgCellHorAlignRight: "જમણી બાજà«", +DlgCellVerAlign : "લંબરૂપ ગોઠવવà«àª‚", +DlgCellVerAlignNotSet : "<સેટ નથી>", +DlgCellVerAlignTop : "ઉપર", +DlgCellVerAlignMiddle : "મધà«àª¯ સેનà«àªŸàª°", +DlgCellVerAlignBottom : "નીચે", +DlgCellVerAlignBaseline : "મૂળ રેખા", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "પંકà«àª¤àª¿ સà«àªªàª¾àª¨", +DlgCellCollSpan : "કૉલમ/ઊભી કટાર સà«àªªàª¾àª¨", +DlgCellBackColor : "બૅકગà«àª°àª¾àª‰àª¨à«àª¡ રંગ", +DlgCellBorderColor : "બોરà«àª¡àª°àª¨à«‹ રંગ", +DlgCellBtnSelect : "પસંદ કરો...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "શોધવà«àª‚ અને બદલવà«àª‚", + +// Find Dialog +DlgFindTitle : "શોધવà«àª‚", +DlgFindFindBtn : "શોધવà«àª‚", +DlgFindNotFoundMsg : "તમે શોધેલી ટેકà«àª¸à«àªŸ નથી મળી", + +// Replace Dialog +DlgReplaceTitle : "બદલવà«àª‚", +DlgReplaceFindLbl : "આ શોધો", +DlgReplaceReplaceLbl : "આનાથી બદલો", +DlgReplaceCaseChk : "કેસ સરખા રાખો", +DlgReplaceReplaceBtn : "બદલવà«àª‚", +DlgReplaceReplAllBtn : "બઘા બદલી ", +DlgReplaceWordChk : "બઘા શબà«àª¦ સરખા રાખો", + +// Paste Operations / Dialog +PasteErrorCut : "તમારા બà«àª°àª¾àª‰àªàª° ની સà«àª°àª•à«àª·àª¿àª¤ સેટિંગસ કટ કરવાની પરવાનગી નથી આપતી. (Ctrl+X) નો ઉપયોગ કરો.", +PasteErrorCopy : "તમારા બà«àª°àª¾àª‰àªàª° ની સà«àª°àª•à«àª·àª¿àª¤ સેટિંગસ કોપી કરવાની પરવાનગી નથી આપતી. (Ctrl+C) का पà¥à¤°à¤¯à¥‹à¤— करें।", + +PasteAsText : "પેસà«àªŸ (ટેકà«àª¸à«àªŸ)", +PasteFromWord : "પેસà«àªŸ (વરà«àª¡ થી)", + +DlgPasteMsg2 : "Ctrl+V નો પà«àª°àª¯à«‹àª— કરી પેસà«àªŸ કરો", +DlgPasteSec : "તમારા બà«àª°àª¾àª‰àªàª° ની સà«àª°àª•à«àª·àª¿àª¤ સેટિંગસના કારણે,àªàª¡àª¿àªŸàª° તમારા કિલà«àªªàª¬à«‹àª°à«àª¡ ડેટા ને કોપી નથી કરી શકતો. તમારે આ વિનà«àª¡à«‹àª®àª¾àª‚ ફરીથી પેસà«àªŸ કરવà«àª‚ પડશે.", +DlgPasteIgnoreFont : "ફૉનà«àªŸàª«à«‡àª¸ વà«àª¯àª¾àª–à«àª¯àª¾àª¨à«€ અવગણના", +DlgPasteRemoveStyles : "સà«àªŸàª¾àª‡àª² વà«àª¯àª¾àª–à«àª¯àª¾ કાઢી નાખવી", + +// Color Picker +ColorAutomatic : "સà«àªµàªšàª¾àª²àª¿àª¤", +ColorMoreColors : "ઔર રંગ...", + +// Document Properties +DocProps : "ડૉકà«àª¯à«àª®àª¨à«àªŸ ગà«àª£/પà«àª°à«‰àªªàª°à«àªŸàª¿àª", + +// Anchor Dialog +DlgAnchorTitle : "àªàª‚કર ગà«àª£/પà«àª°à«‰àªªàª°à«àªŸàª¿àª", +DlgAnchorName : "àªàª‚કરનà«àª‚ નામ", +DlgAnchorErrorName : "àªàª‚કરનà«àª‚ નામ ટાઈપ કરો", + +// Speller Pages Dialog +DlgSpellNotInDic : "શબà«àª¦àª•à«‹àª¶àª®àª¾àª‚ નથી", +DlgSpellChangeTo : "આનાથી બદલવà«àª‚", +DlgSpellBtnIgnore : "ઇગà«àª¨à«‹àª°/અવગણના કરવી", +DlgSpellBtnIgnoreAll : "બધાની ઇગà«àª¨à«‹àª°/અવગણના કરવી", +DlgSpellBtnReplace : "બદલવà«àª‚", +DlgSpellBtnReplaceAll : "બધા બદલી કરો", +DlgSpellBtnUndo : "અનà«àª¡à«‚", +DlgSpellNoSuggestions : "- કઇ સજેશન નથી -", +DlgSpellProgress : "શબà«àª¦àª¨à«€ જોડણી/સà«àªªà«‡àª² ચેક ચાલૠછે...", +DlgSpellNoMispell : "શબà«àª¦àª¨à«€ જોડણી/સà«àªªà«‡àª² ચેક પૂરà«àª£: ખોટી જોડણી મળી નથી", +DlgSpellNoChanges : "શબà«àª¦àª¨à«€ જોડણી/સà«àªªà«‡àª² ચેક પૂરà«àª£: àªàª•àªªàª£ શબà«àª¦ બદલયો નથી", +DlgSpellOneChange : "શબà«àª¦àª¨à«€ જોડણી/સà«àªªà«‡àª² ચેક પૂરà«àª£: àªàª• શબà«àª¦ બદલયો છે", +DlgSpellManyChanges : "શબà«àª¦àª¨à«€ જોડણી/સà«àªªà«‡àª² ચેક પૂરà«àª£: %1 શબà«àª¦ બદલયા છે", + +IeSpellDownload : "સà«àªªà«‡àª²-ચેકર ઇનà«àª¸à«àªŸà«‹àª² નથી. શà«àª‚ તમે ડાઉનલોડ કરવા માંગો છો?", + +// Button Dialog +DlgButtonText : "ટેકà«àª¸à«àªŸ (વૅલà«àª¯à«‚)", +DlgButtonType : "પà«àª°àª•àª¾àª°", +DlgButtonTypeBtn : "બટન", +DlgButtonTypeSbm : "સબà«àª®àª¿àªŸ", +DlgButtonTypeRst : "રિસેટ", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "નામ", +DlgCheckboxValue : "વૅલà«àª¯à«‚", +DlgCheckboxSelected : "સિલેકà«àªŸà«‡àª¡", + +// Form Dialog +DlgFormName : "નામ", +DlgFormAction : "કà«àª°àª¿àª¯àª¾", +DlgFormMethod : "પદà«àª§àª¤àª¿", + +// Select Field Dialog +DlgSelectName : "નામ", +DlgSelectValue : "વૅલà«àª¯à«‚", +DlgSelectSize : "સાઇàª", +DlgSelectLines : "લીટીઓ", +DlgSelectChkMulti : "àªàª•àª¥à«€ વધારે પસંદ કરી શકો", +DlgSelectOpAvail : "ઉપલબà«àª§ વિકલà«àªª", +DlgSelectOpText : "ટેકà«àª¸à«àªŸ", +DlgSelectOpValue : "વૅલà«àª¯à«‚", +DlgSelectBtnAdd : "ઉમેરવà«àª‚", +DlgSelectBtnModify : "બદલવà«àª‚", +DlgSelectBtnUp : "ઉપર", +DlgSelectBtnDown : "નીચે", +DlgSelectBtnSetValue : "પસંદ કરલી વૅલà«àª¯à«‚ સેટ કરો", +DlgSelectBtnDelete : "રદ કરવà«àª‚", + +// Textarea Dialog +DlgTextareaName : "નામ", +DlgTextareaCols : "કૉલમ/ઊભી કટાર", +DlgTextareaRows : "પંકà«àª¤àª¿àª“", + +// Text Field Dialog +DlgTextName : "નામ", +DlgTextValue : "વૅલà«àª¯à«‚", +DlgTextCharWidth : "કેરેકà«àªŸàª°àª¨à«€ પહોળાઈ", +DlgTextMaxChars : "અધિકતમ કેરેકà«àªŸàª°", +DlgTextType : "ટાઇપ", +DlgTextTypeText : "ટેકà«àª¸à«àªŸ", +DlgTextTypePass : "પાસવરà«àª¡", + +// Hidden Field Dialog +DlgHiddenName : "નામ", +DlgHiddenValue : "વૅલà«àª¯à«‚", + +// Bulleted List Dialog +BulletedListProp : "બà«àª²à«‡àªŸ સૂચિ ગà«àª£", +NumberedListProp : "સંખà«àª¯àª¾àª‚કà«àª¤àª¿ સૂચિ ગà«àª£", +DlgLstStart : "શરૂઆતથી", +DlgLstType : "પà«àª°àª•àª¾àª°", +DlgLstTypeCircle : "વરà«àª¤à«àª³", +DlgLstTypeDisc : "ડિસà«àª•", +DlgLstTypeSquare : "ચોરસ", +DlgLstTypeNumbers : "સંખà«àª¯àª¾ (1, 2, 3)", +DlgLstTypeLCase : "નાના અકà«àª·àª° (a, b, c)", +DlgLstTypeUCase : "મોટા અકà«àª·àª° (A, B, C)", +DlgLstTypeSRoman : "નાના રોમન આંક (i, ii, iii)", +DlgLstTypeLRoman : "મોટા રોમન આંક (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "સાધારણ", +DlgDocBackTab : "બૅકગà«àª°àª¾àª‰àª¨à«àª¡", +DlgDocColorsTab : "રંગ અને મારà«àªœàª¿àª¨/કિનાર", +DlgDocMetaTab : "મેટાડૅટા", + +DlgDocPageTitle : "પેજ મથાળà«àª‚/ટાઇટલ", +DlgDocLangDir : "ભાષા લેખવાની પદà«àª§àª¤àª¿", +DlgDocLangDirLTR : "ડાબે થી જમણે (LTR)", +DlgDocLangDirRTL : "જમણે થી ડાબે (RTL)", +DlgDocLangCode : "ભાષા કોડ", +DlgDocCharSet : "કેરેકà«àªŸàª° સેટ àªàª¨à«àª•à«‹àª¡àª¿àª‚ગ", +DlgDocCharSetCE : "મધà«àª¯ યà«àª°à«‹àªªàª¿àª…ન (Central European)", +DlgDocCharSetCT : "ચાઇનીઠ(Chinese Traditional Big5)", +DlgDocCharSetCR : "સિરીલિક (Cyrillic)", +DlgDocCharSetGR : "ગà«àª°à«€àª• (Greek)", +DlgDocCharSetJP : "જાપાનિઠ(Japanese)", +DlgDocCharSetKR : "કોરીયન (Korean)", +DlgDocCharSetTR : "ટરà«àª•àª¿ (Turkish)", +DlgDocCharSetUN : "યૂનિકોડ (UTF-8)", +DlgDocCharSetWE : "પશà«àªšàª¿àª® યà«àª°à«‹àªªàª¿àª…ન (Western European)", +DlgDocCharSetOther : "અનà«àª¯ કેરેકà«àªŸàª° સેટ àªàª¨à«àª•à«‹àª¡àª¿àª‚ગ", + +DlgDocDocType : "ડૉકà«àª¯à«àª®àª¨à«àªŸ પà«àª°àª•àª¾àª° શીરà«àª·àª•", +DlgDocDocTypeOther : "અનà«àª¯ ડૉકà«àª¯à«àª®àª¨à«àªŸ પà«àª°àª•àª¾àª° શીરà«àª·àª•", +DlgDocIncXHTML : "XHTML સૂચના સમાવિષà«àªŸ કરવી", +DlgDocBgColor : "બૅકગà«àª°àª¾àª‰àª¨à«àª¡ રંગ", +DlgDocBgImage : "બૅકગà«àª°àª¾àª‰àª¨à«àª¡ ચિતà«àª° URL", +DlgDocBgNoScroll : "સà«àª•à«àª°à«‹àª² ન થાય તેવà«àª‚ બૅકગà«àª°àª¾àª‰àª¨à«àª¡", +DlgDocCText : "ટેકà«àª¸à«àªŸ", +DlgDocCLink : "લિંક", +DlgDocCVisited : "વિàªàª¿àªŸà«‡àª¡ લિંક", +DlgDocCActive : "સકà«àª°àª¿àª¯ લિંક", +DlgDocMargins : "પેજ મારà«àªœàª¿àª¨", +DlgDocMaTop : "ઉપર", +DlgDocMaLeft : "ડાબી", +DlgDocMaRight : "જમણી", +DlgDocMaBottom : "નીચે", +DlgDocMeIndex : "ડૉકà«àª¯à«àª®àª¨à«àªŸ ઇનà«àª¡à«‡àª•à«àª¸ સંકેતશબà«àª¦ (અલà«àªªàªµàª¿àª°àª¾àª® (,) થી અલગ કરો)", +DlgDocMeDescr : "ડૉકà«àª¯à«àª®àª¨à«àªŸ વરà«àª£àª¨", +DlgDocMeAuthor : "લેખક", +DlgDocMeCopy : "કૉપિરાઇટ", +DlgDocPreview : "પૂરà«àªµàª¦àª°à«àª¶àª¨", + +// Templates Dialog +Templates : "ટેમà«àªªà«àª²à«‡àªŸ", +DlgTemplatesTitle : "કનà«àªŸà«‡àª¨à«àªŸ ટેમà«àªªà«àª²à«‡àªŸ", +DlgTemplatesSelMsg : "àªàª¡àª¿àªŸàª°àª®àª¾àª‚ ઓપન કરવા ટેમà«àªªà«àª²à«‡àªŸ પસંદ કરો (વરà«àª¤àª®àª¾àª¨ કનà«àªŸà«‡àª¨à«àªŸ સેવ નહીં થાય):", +DlgTemplatesLoading : "ટેમà«àªªà«àª²à«‡àªŸ સૂચિ લોડ થાય છે. રાહ જà«àª“...", +DlgTemplatesNoTpl : "(કોઈ ટેમà«àªªà«àª²à«‡àªŸ ડિફાઇન નથી)", +DlgTemplatesReplace : "મૂળ શબà«àª¦àª¨à«‡ બદલો", + +// About Dialog +DlgAboutAboutTab : "FCKEditor ના વિષે", +DlgAboutBrowserInfoTab : "બà«àª°àª¾àª‰àªàª° ના વિષે", +DlgAboutLicenseTab : "લાઇસનà«àª¸", +DlgAboutVersion : "વરà«àªàª¨", +DlgAboutInfo : "વધારે માહિતી માટે:", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/he.js b/www/js/FCKeditor/editor/lang/he.js new file mode 100644 index 0000000..037b968 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/he.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Hebrew language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "rtl", + +ToolbarCollapse : "כיווץ סרגל הכלי×", +ToolbarExpand : "פתיחת סרגל הכלי×", + +// Toolbar Items and Context Menu +Save : "שמירה", +NewPage : "דף חדש", +Preview : "תצוגה מקדימה", +Cut : "גזירה", +Copy : "העתקה", +Paste : "הדבקה", +PasteText : "הדבקה כטקסט פשוט", +PasteWord : "הדבקה מ-וורד", +Print : "הדפסה", +SelectAll : "בחירת הכל", +RemoveFormat : "הסרת העיצוב", +InsertLinkLbl : "קישור", +InsertLink : "הוספת/עריכת קישור", +RemoveLink : "הסרת הקישור", +VisitLink : "פתח קישור", +Anchor : "הוספת/עריכת נקודת עיגון", +AnchorDelete : "הסר נקודת עיגון", +InsertImageLbl : "תמונה", +InsertImage : "הוספת/עריכת תמונה", +InsertFlashLbl : "פל×ש", +InsertFlash : "הוסף/ערוך פל×ש", +InsertTableLbl : "טבלה", +InsertTable : "הוספת/עריכת טבלה", +InsertLineLbl : "קו", +InsertLine : "הוספת קו ×ופקי", +InsertSpecialCharLbl: "תו מיוחד", +InsertSpecialChar : "הוספת תו מיוחד", +InsertSmileyLbl : "סמיילי", +InsertSmiley : "הוספת סמיילי", +About : "×ודות FCKeditor", +Bold : "מודגש", +Italic : "נטוי", +Underline : "קו תחתון", +StrikeThrough : "כתיב מחוק", +Subscript : "כתיב תחתון", +Superscript : "כתיב עליון", +LeftJustify : "יישור לשמ×ל", +CenterJustify : "מרכוז", +RightJustify : "יישור לימין", +BlockJustify : "יישור לשוליי×", +DecreaseIndent : "הקטנת ×ינדנטציה", +IncreaseIndent : "הגדלת ×ינדנטציה", +Blockquote : "בלוק ציטוט", +CreateDiv : "צור מיכל(תג)DIV", +EditDiv : "ערוך מיכל (תג)DIV", +DeleteDiv : "הסר מיכל(תג) DIV", +Undo : "ביטול צעד ×חרון", +Redo : "חזרה על צעד ×חרון", +NumberedListLbl : "רשימה ממוספרת", +NumberedList : "הוספת/הסרת רשימה ממוספרת", +BulletedListLbl : "רשימת נקודות", +BulletedList : "הוספת/הסרת רשימת נקודות", +ShowTableBorders : "הצגת מסגרת הטבלה", +ShowDetails : "הצגת פרטי×", +Style : "סגנון", +FontFormat : "עיצוב", +Font : "גופן", +FontSize : "גודל", +TextColor : "צבע טקסט", +BGColor : "צבע רקע", +Source : "מקור", +Find : "חיפוש", +Replace : "החלפה", +SpellCheck : "בדיקת ×יות", +UniversalKeyboard : "מקלדת ×וניברסלית", +PageBreakLbl : "שבירת דף", +PageBreak : "הוסף שבירת דף", + +Form : "טופס", +Checkbox : "תיבת סימון", +RadioButton : "לחצן ×פשרויות", +TextField : "שדה טקסט", +Textarea : "×יזור טקסט", +HiddenField : "שדה חבוי", +Button : "כפתור", +SelectionField : "שדה בחירה", +ImageButton : "כפתור תמונה", + +FitWindow : "הגדל ×ת גודל העורך", +ShowBlocks : "הצג בלוקי×", + +// Context Menu +EditLink : "עריכת קישור", +CellCM : "ת×", +RowCM : "שורה", +ColumnCM : "עמודה", +InsertRowAfter : "הוסף שורה ×חרי", +InsertRowBefore : "הוסף שורה לפני", +DeleteRows : "מחיקת שורות", +InsertColumnAfter : "הוסף עמודה ×חרי", +InsertColumnBefore : "הוסף עמודה לפני", +DeleteColumns : "מחיקת עמודות", +InsertCellAfter : "הוסף ×ª× ×חרי", +InsertCellBefore : "הוסף ×ª× ×חרי", +DeleteCells : "מחיקת ת××™×", +MergeCells : "מיזוג ת××™×", +MergeRight : "מזג ימינה", +MergeDown : "מזג למטה", +HorizontalSplitCell : "פצל ×ª× ×ופקית", +VerticalSplitCell : "פצל ×ª× ×נכית", +TableDelete : "מחק טבלה", +CellProperties : "תכונות הת×", +TableProperties : "תכונות הטבלה", +ImageProperties : "תכונות התמונה", +FlashProperties : "מ×פייני פל×ש", + +AnchorProp : "מ×פייני נקודת עיגון", +ButtonProp : "מ×פייני כפתור", +CheckboxProp : "מ×פייני תיבת סימון", +HiddenFieldProp : "מ×פיני שדה חבוי", +RadioButtonProp : "מ×פייני לחצן ×פשרויות", +ImageButtonProp : "מ×פיני כפתור תמונה", +TextFieldProp : "מ×פייני שדה טקסט", +SelectionFieldProp : "מ×פייני שדה בחירה", +TextareaProp : "מ×פיני ×יזור טקסט", +FormProp : "מ×פיני טופס", + +FontFormats : "נורמלי;קוד;כתובת;כותרת;כותרת 2;כותרת 3;כותרת 4;כותרת 5;כותרת 6", + +// Alerts and Messages +ProcessingXHTML : "מעבד XHTML, × × ×œ×”×ž×ª×™×Ÿ...", +Done : "המשימה הושלמה", +PasteWordConfirm : "נר××” הטקסט שבכוונתך להדביק מקורו בקובץ וורד. ×”×× ×‘×¨×¦×•× ×š לנקות ×ותו ×˜×¨× ×”×”×“×‘×§×”?", +NotCompatiblePaste : "פעולה זו זמינה לדפדפן ×ינטרנט ×קספלורר ×ž×’×™×¨×¡× 5.5 ומעלה. ×”×× ×œ×”×ž×©×™×š בהדבקה ×œ×œ× ×”× ×™×§×•×™?", +UnknownToolbarItem : "פריט ×œ× ×™×“×•×¢ בסרגל ×”×›×œ×™× \"%1\"", +UnknownCommand : "×©× ×¤×¢×•×œ×” ×œ× ×™×“×•×¢ \"%1\"", +NotImplemented : "הפקודה ×œ× ×ž×™×•×©×ž×ª", +UnknownToolbarSet : "ערכת סרגל ×”×›×œ×™× \"%1\" ×œ× ×§×™×™×ž×ª", +NoActiveX : "הגדרות ×בטחה של הדפדפן עלולות לגביל ×ת ×פשרויות העריכה.יש ל×פשר ×ת ×”×ופציה \"הרץ ×¤×§×“×™× ×¤×¢×™×œ×™× ×•×ª×•×¡×¤×•×ª\". תוכל לחוות טעויות ×•×—×™×•×•×™× ×©×œ ×פשרויות שחסרי×.", +BrowseServerBlocked : "×œ× × ×™×ª×Ÿ לגשת לדפדפן מש×בי×.×× × ×•×•×“× ×©×—×•×¡× ×—×œ×•× ×•×ª ×”×§×•×¤×¦×™× ×œ× ×¤×¢×™×œ.", +DialogBlocked : "×œ× ×”×™×” ניתן לפתוח חלון די×לוג. ×× × ×•×•×“× ×©×—×•×¡× ×—×œ×•× ×•×ª ×§×•×¤×¦×™× ×œ× ×¤×¢×™×œ.", +VisitLinkBlocked : "×œ× × ×™×ª×Ÿ לפתוח חלון חדש.× × ×œ×•×•×“× ×©×—×•×¡×ž×™ החלונות ×”×§×•×¤×¦×™× ×œ× ×¤×¢×™×œ×™×.", + +// Dialogs +DlgBtnOK : "×ישור", +DlgBtnCancel : "ביטול", +DlgBtnClose : "סגירה", +DlgBtnBrowseServer : "סייר השרת", +DlgAdvancedTag : "×פשרויות מתקדמות", +DlgOpOther : "<×חר>", +DlgInfoTab : "מידע", +DlgAlertUrl : "×× × ×”×–×Ÿ URL", + +// General Dialogs Labels +DlgGenNotSet : "<×œ× × ×§×‘×¢>", +DlgGenId : "זיהוי (Id)", +DlgGenLangDir : "כיוון שפה", +DlgGenLangDirLtr : "שמ×ל לימין (LTR)", +DlgGenLangDirRtl : "ימין לשמ×ל (RTL)", +DlgGenLangCode : "קוד שפה", +DlgGenAccessKey : "מקש גישה", +DlgGenName : "ש×", +DlgGenTabIndex : "מספר ט×ב", +DlgGenLongDescr : "קישור לתי×ור מפורט", +DlgGenClass : "גיליונות עיצוב קבוצות", +DlgGenTitle : "כותרת מוצעת", +DlgGenContType : "Content Type מוצע", +DlgGenLinkCharset : "קידוד המש×ב המקושר", +DlgGenStyle : "סגנון", + +// Image Dialog +DlgImgTitle : "תכונות התמונה", +DlgImgInfoTab : "מידע על התמונה", +DlgImgBtnUpload : "שליחה לשרת", +DlgImgURL : "כתובת (URL)", +DlgImgUpload : "העל××”", +DlgImgAlt : "טקסט חלופי", +DlgImgWidth : "רוחב", +DlgImgHeight : "גובה", +DlgImgLockRatio : "נעילת היחס", +DlgBtnResetSize : "×יפוס הגודל", +DlgImgBorder : "מסגרת", +DlgImgHSpace : "מרווח ×ופקי", +DlgImgVSpace : "מרווח ×× ×›×™", +DlgImgAlign : "יישור", +DlgImgAlignLeft : "לשמ×ל", +DlgImgAlignAbsBottom: "לתחתית ×”×בסולוטית", +DlgImgAlignAbsMiddle: "מרכוז ×בסולוטי", +DlgImgAlignBaseline : "לקו התחתית", +DlgImgAlignBottom : "לתחתית", +DlgImgAlignMiddle : "ל×מצע", +DlgImgAlignRight : "לימין", +DlgImgAlignTextTop : "לר×ש הטקסט", +DlgImgAlignTop : "למעלה", +DlgImgPreview : "תצוגה מקדימה", +DlgImgAlertUrl : "× × ×œ×”×§×œ×™×“ ×ת כתובת התמונה", +DlgImgLinkTab : "קישור", + +// Flash Dialog +DlgFlashTitle : "מ×פיני פל×ש", +DlgFlashChkPlay : "נגן ×וטומטי", +DlgFlashChkLoop : "לול××”", +DlgFlashChkMenu : "×פשר תפריט פל×ש", +DlgFlashScale : "גודל", +DlgFlashScaleAll : "הצג הכל", +DlgFlashScaleNoBorder : "×œ×œ× ×’×‘×•×œ×•×ª", +DlgFlashScaleFit : "הת×מה מושלמת", + +// Link Dialog +DlgLnkWindowTitle : "קישור", +DlgLnkInfoTab : "מידע על הקישור", +DlgLnkTargetTab : "מטרה", + +DlgLnkType : "סוג קישור", +DlgLnkTypeURL : "כתובת (URL)", +DlgLnkTypeAnchor : "עוגן בעמוד ×–×”", +DlgLnkTypeEMail : "דו×''ל", +DlgLnkProto : "פרוטוקול", +DlgLnkProtoOther : "<×חר>", +DlgLnkURL : "כתובת (URL)", +DlgLnkAnchorSel : "בחירת עוגן", +DlgLnkAnchorByName : "עפ''×™ ×©× ×”×¢×•×’×Ÿ", +DlgLnkAnchorById : "עפ''×™ זיהוי (Id) הרכיב", +DlgLnkNoAnchors : "(×ין ×¢×•×’× ×™× ×–×ž×™× ×™× ×‘×“×£)", +DlgLnkEMail : "כתובת הדו×''ל", +DlgLnkEMailSubject : "× ×•×©× ×”×”×•×“×¢×”", +DlgLnkEMailBody : "גוף ההודעה", +DlgLnkUpload : "העל××”", +DlgLnkBtnUpload : "שליחה לשרת", + +DlgLnkTarget : "מטרה", +DlgLnkTargetFrame : "<מסגרת>", +DlgLnkTargetPopup : "<חלון קופץ>", +DlgLnkTargetBlank : "חלון חדש (_blank)", +DlgLnkTargetParent : "חלון ×”×ב (_parent)", +DlgLnkTargetSelf : "ב×ותו החלון (_self)", +DlgLnkTargetTop : "חלון ר×שי (_top)", +DlgLnkTargetFrameName : "×©× ×ž×¡×’×¨×ª היעד", +DlgLnkPopWinName : "×©× ×”×—×œ×•×Ÿ הקופץ", +DlgLnkPopWinFeat : "תכונות החלון הקופץ", +DlgLnkPopResize : "בעל גודל ניתן לשינוי", +DlgLnkPopLocation : "סרגל כתובת", +DlgLnkPopMenu : "סרגל תפריט", +DlgLnkPopScroll : "ניתן לגלילה", +DlgLnkPopStatus : "סרגל חיווי", +DlgLnkPopToolbar : "סרגל הכלי×", +DlgLnkPopFullScrn : "מסך ×ž×œ× (IE)", +DlgLnkPopDependent : "תלוי (Netscape)", +DlgLnkPopWidth : "רוחב", +DlgLnkPopHeight : "גובה", +DlgLnkPopLeft : "×ž×™×§×•× ×¦×“ שמ×ל", +DlgLnkPopTop : "×ž×™×§×•× ×¦×“ עליון", + +DlnLnkMsgNoUrl : "× × ×œ×”×§×œ×™×“ ×ת כתובת הקישור (URL)", +DlnLnkMsgNoEMail : "× × ×œ×”×§×œ×™×“ ×ת כתובת הדו×''ל", +DlnLnkMsgNoAnchor : "× × ×œ×‘×—×•×¨ עוגן במסמך", +DlnLnkMsgInvPopName : "×©× ×”×—×œ×•×Ÿ הקופץ חייב להתחיל ב×ותיות ו×סור לכלול רווחי×", + +// Color Dialog +DlgColorTitle : "בחירת צבע", +DlgColorBtnClear : "×יפוס", +DlgColorHighlight : "נוכחי", +DlgColorSelected : "נבחר", + +// Smiley Dialog +DlgSmileyTitle : "הוספת סמיילי", + +// Special Character Dialog +DlgSpecialCharTitle : "בחירת תו מיוחד", + +// Table Dialog +DlgTableTitle : "תכונות טבלה", +DlgTableRows : "שורות", +DlgTableColumns : "עמודות", +DlgTableBorder : "גודל מסגרת", +DlgTableAlign : "יישור", +DlgTableAlignNotSet : "<×œ× × ×§×‘×¢>", +DlgTableAlignLeft : "שמ×ל", +DlgTableAlignCenter : "מרכז", +DlgTableAlignRight : "ימין", +DlgTableWidth : "רוחב", +DlgTableWidthPx : "פיקסלי×", +DlgTableWidthPc : "×חוז", +DlgTableHeight : "גובה", +DlgTableCellSpace : "מרווח ת×", +DlgTableCellPad : "ריפוד ת×", +DlgTableCaption : "כיתוב", +DlgTableSummary : "סיכו×", +DlgTableHeaders : "כותרות", +DlgTableHeadersNone : "×ין", +DlgTableHeadersColumn : "עמודה ר×שונה", +DlgTableHeadersRow : "שורה ר×שונה", +DlgTableHeadersBoth : "שניה×", + +// Table Cell Dialog +DlgCellTitle : "תכונות ת×", +DlgCellWidth : "רוחב", +DlgCellWidthPx : "פיקסלי×", +DlgCellWidthPc : "×חוז", +DlgCellHeight : "גובה", +DlgCellWordWrap : "גלילת שורות", +DlgCellWordWrapNotSet : "<×œ× × ×§×‘×¢>", +DlgCellWordWrapYes : "כן", +DlgCellWordWrapNo : "ל×", +DlgCellHorAlign : "יישור ×ופקי", +DlgCellHorAlignNotSet : "<×œ× × ×§×‘×¢>", +DlgCellHorAlignLeft : "שמ×ל", +DlgCellHorAlignCenter : "מרכז", +DlgCellHorAlignRight: "ימין", +DlgCellVerAlign : "יישור ×× ×›×™", +DlgCellVerAlignNotSet : "<×œ× × ×§×‘×¢>", +DlgCellVerAlignTop : "למעלה", +DlgCellVerAlignMiddle : "ל×מצע", +DlgCellVerAlignBottom : "לתחתית", +DlgCellVerAlignBaseline : "קו תחתית", +DlgCellType : "סוג ת×", +DlgCellTypeData : "סוג", +DlgCellTypeHeader : "כותרת", +DlgCellRowSpan : "טווח שורות", +DlgCellCollSpan : "טווח עמודות", +DlgCellBackColor : "צבע רקע", +DlgCellBorderColor : "צבע מסגרת", +DlgCellBtnSelect : "בחירה...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "חפש והחלף", + +// Find Dialog +DlgFindTitle : "חיפוש", +DlgFindFindBtn : "חיפוש", +DlgFindNotFoundMsg : "הטקסט המבוקש ×œ× × ×ž×¦×.", + +// Replace Dialog +DlgReplaceTitle : "החלפה", +DlgReplaceFindLbl : "חיפוש מחרוזת:", +DlgReplaceReplaceLbl : "החלפה במחרוזת:", +DlgReplaceCaseChk : "הת×מת סוג ×ותיות (Case)", +DlgReplaceReplaceBtn : "החלפה", +DlgReplaceReplAllBtn : "החלפה בכל העמוד", +DlgReplaceWordChk : "הת×מה למילה המל××”", + +// Paste Operations / Dialog +PasteErrorCut : "הגדרות ×”×בטחה בדפדפן שלך ×œ× ×ž×פשרות לעורך לבצע פעולות גזירה ×וטומטיות. יש להשתמש במקלדת ×œ×©× ×›×š (Ctrl+X).", +PasteErrorCopy : "הגדרות ×”×בטחה בדפדפן שלך ×œ× ×ž×פשרות לעורך לבצע פעולות העתקה ×וטומטיות. יש להשתמש במקלדת ×œ×©× ×›×š (Ctrl+C).", + +PasteAsText : "הדבקה כטקסט פשוט", +PasteFromWord : "הדבקה מ-וורד", + +DlgPasteMsg2 : "×× × ×”×“×‘×§ בתוך הקופסה ב×מצעות (Ctrl+V) ולחץ על ×ישור.", +DlgPasteSec : "עקב הגדרות ×בטחה בדפדפן, ×œ× × ×™×ª×Ÿ לגשת ×ל לוח ×”×’×–×™×¨×™× (clipboard) בצורה ישירה.×× × ×‘×¦×¢ הדבק שוב בחלון ×–×”.", +DlgPasteIgnoreFont : "×”×ª×¢×œ× ×ž×”×’×“×¨×•×ª סוג פונט", +DlgPasteRemoveStyles : "הסר הגדרות סגנון", + +// Color Picker +ColorAutomatic : "×וטומטי", +ColorMoreColors : "×¦×‘×¢×™× × ×•×¡×¤×™×...", + +// Document Properties +DocProps : "מ×פיני מסמך", + +// Anchor Dialog +DlgAnchorTitle : "מ×פיני נקודת עיגון", +DlgAnchorName : "×©× ×œ× ×§×•×“×ª עיגון", +DlgAnchorErrorName : "×× × ×”×–×Ÿ ×©× ×œ× ×§×•×“×ª עיגון", + +// Speller Pages Dialog +DlgSpellNotInDic : "×œ× × ×ž×¦× ×‘×ž×™×œ×•×Ÿ", +DlgSpellChangeTo : "שנה ל", +DlgSpellBtnIgnore : "התעל×", +DlgSpellBtnIgnoreAll : "×”×ª×¢×œ× ×ž×”×›×œ", +DlgSpellBtnReplace : "החלף", +DlgSpellBtnReplaceAll : "החלף הכל", +DlgSpellBtnUndo : "החזר", +DlgSpellNoSuggestions : "- ×ין הצעות -", +DlgSpellProgress : "בדיקות ×יות בתהליך ....", +DlgSpellNoMispell : "בדיקות ×יות הסתיימה: ×œ× × ×ž×¦×ו שגיעות כתיב", +DlgSpellNoChanges : "בדיקות ×יות הסתיימה: ×œ× ×©×•× ×ª×” ××£ מילה", +DlgSpellOneChange : "בדיקות ×יות הסתיימה: שונתה מילה ×חת", +DlgSpellManyChanges : "בדיקות ×יות הסתיימה: %1 ×ž×™×œ×™× ×©×•× ×•", + +IeSpellDownload : "בודק ×”×יות ×œ× ×ž×•×ª×§×Ÿ, ×”×× ×תה מעוניין להוריד?", + +// Button Dialog +DlgButtonText : "טקסט (ערך)", +DlgButtonType : "סוג", +DlgButtonTypeBtn : "כפתור", +DlgButtonTypeSbm : "שלח", +DlgButtonTypeRst : "×פס", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "ש×", +DlgCheckboxValue : "ערך", +DlgCheckboxSelected : "בחור", + +// Form Dialog +DlgFormName : "ש×", +DlgFormAction : "שלח ×ל", +DlgFormMethod : "סוג שליחה", + +// Select Field Dialog +DlgSelectName : "ש×", +DlgSelectValue : "ערך", +DlgSelectSize : "גודל", +DlgSelectLines : "שורות", +DlgSelectChkMulti : "×פשר בחירות מרובות", +DlgSelectOpAvail : "×פשרויות זמינות", +DlgSelectOpText : "טקסט", +DlgSelectOpValue : "ערך", +DlgSelectBtnAdd : "הוסף", +DlgSelectBtnModify : "שנה", +DlgSelectBtnUp : "למעלה", +DlgSelectBtnDown : "למטה", +DlgSelectBtnSetValue : "קבע כברירת מחדל", +DlgSelectBtnDelete : "מחק", + +// Textarea Dialog +DlgTextareaName : "ש×", +DlgTextareaCols : "עמודות", +DlgTextareaRows : "שורות", + +// Text Field Dialog +DlgTextName : "ש×", +DlgTextValue : "ערך", +DlgTextCharWidth : "רוחב ב×ותיות", +DlgTextMaxChars : "מקסימות ×ותיות", +DlgTextType : "סוג", +DlgTextTypeText : "טקסט", +DlgTextTypePass : "סיסמה", + +// Hidden Field Dialog +DlgHiddenName : "ש×", +DlgHiddenValue : "ערך", + +// Bulleted List Dialog +BulletedListProp : "מ×פייני רשימה", +NumberedListProp : "מ×פייני רשימה ממוספרת", +DlgLstStart : "התחלה", +DlgLstType : "סוג", +DlgLstTypeCircle : "עיגול", +DlgLstTypeDisc : "דיסק", +DlgLstTypeSquare : "מרובע", +DlgLstTypeNumbers : "×ž×¡×¤×¨×™× (1, 2, 3)", +DlgLstTypeLCase : "×ותיות קטנות (a, b, c)", +DlgLstTypeUCase : "×ותיות גדולות (A, B, C)", +DlgLstTypeSRoman : "ספרות רומ×יות קטנות (i, ii, iii)", +DlgLstTypeLRoman : "ספרות רומ×יות גדולות (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "כללי", +DlgDocBackTab : "רקע", +DlgDocColorsTab : "×¦×‘×¢×™× ×•×’×‘×•×œ×•×ª", +DlgDocMetaTab : "נתוני META", + +DlgDocPageTitle : "כותרת דף", +DlgDocLangDir : "כיוון שפה", +DlgDocLangDirLTR : "שמ×ל לימין (LTR)", +DlgDocLangDirRTL : "ימין לשמ×ל (RTL)", +DlgDocLangCode : "קוד שפה", +DlgDocCharSet : "קידוד ×ותיות", +DlgDocCharSetCE : "מרכז ×ירופה", +DlgDocCharSetCT : "סיני מסורתי (Big5)", +DlgDocCharSetCR : "קירילי", +DlgDocCharSetGR : "יוונית", +DlgDocCharSetJP : "יפנית", +DlgDocCharSetKR : "קור×נית", +DlgDocCharSetTR : "טורקית", +DlgDocCharSetUN : "יוני קוד (UTF-8)", +DlgDocCharSetWE : "מערב ×ירופה", +DlgDocCharSetOther : "קידוד ×ותיות ×חר", + +DlgDocDocType : "הגדרות סוג מסמך", +DlgDocDocTypeOther : "הגדרות סוג מסמך ×חרות", +DlgDocIncXHTML : "כלול הגדרות XHTML", +DlgDocBgColor : "צבע רקע", +DlgDocBgImage : "URL לתמונת רקע", +DlgDocBgNoScroll : "רגע ×œ×œ× ×’×œ×™×œ×”", +DlgDocCText : "טקסט", +DlgDocCLink : "קישור", +DlgDocCVisited : "קישור שבוקר", +DlgDocCActive : " קישור פעיל", +DlgDocMargins : "גבולות דף", +DlgDocMaTop : "למעלה", +DlgDocMaLeft : "שמ×לה", +DlgDocMaRight : "ימינה", +DlgDocMaBottom : "למטה", +DlgDocMeIndex : "מפתח ×¢× ×™×™× ×™× ×©×œ המסמך )מופרד בפסיק(", +DlgDocMeDescr : "ת×ור מסמך", +DlgDocMeAuthor : "מחבר", +DlgDocMeCopy : "זכויות יוצרי×", +DlgDocPreview : "תצוגה מקדימה", + +// Templates Dialog +Templates : "תבניות", +DlgTemplatesTitle : "תביות תוכן", +DlgTemplatesSelMsg : "×× × ×‘×—×¨ תבנית לפתיחה בעורך
    התוכן המקורי ימחק:", +DlgTemplatesLoading : "מעלה רשימת תבניות ×× × ×”×ž×ª×Ÿ", +DlgTemplatesNoTpl : "(×œ× ×”×•×’×“×¨×• תבניות)", +DlgTemplatesReplace : "החלפת תוכן ממשי", + +// About Dialog +DlgAboutAboutTab : "×ודות", +DlgAboutBrowserInfoTab : "גירסת דפדפן", +DlgAboutLicenseTab : "רשיון", +DlgAboutVersion : "גירס×", +DlgAboutInfo : "מידע נוסף ניתן ×œ×ž×¦×•× ×›×ן:", + +// Div Dialog +DlgDivGeneralTab : "כללי", +DlgDivAdvancedTab : "מתקד×", +DlgDivStyle : "סגנון", +DlgDivInlineStyle : "סגנון בתוך השורה", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/hi.js b/www/js/FCKeditor/editor/lang/hi.js new file mode 100644 index 0000000..f7ba7d9 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/hi.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Hindi language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "टूलबार सिमटायें", +ToolbarExpand : "टूलबार का विसà¥à¤¤à¤¾à¤° करें", + +// Toolbar Items and Context Menu +Save : "सेव", +NewPage : "नया पेज", +Preview : "पà¥à¤°à¥€à¤µà¥à¤¯à¥‚", +Cut : "कट", +Copy : "कॉपी", +Paste : "पेसà¥à¤Ÿ", +PasteText : "पेसà¥à¤Ÿ (सादा टॅकà¥à¤¸à¥à¤Ÿ)", +PasteWord : "पेसà¥à¤Ÿ (वरà¥à¤¡ से)", +Print : "पà¥à¤°à¤¿à¤¨à¥à¤Ÿ", +SelectAll : "सब सॅलॅकà¥à¤Ÿ करें", +RemoveFormat : "फ़ॉरà¥à¤®à¥ˆà¤Ÿ हटायें", +InsertLinkLbl : "लिंक", +InsertLink : "लिंक इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +RemoveLink : "लिंक हटायें", +VisitLink : "लिंक खोलें", +Anchor : "à¤à¤‚कर इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +AnchorDelete : "à¤à¤‚कर हटायें", +InsertImageLbl : "तसà¥à¤µà¥€à¤°", +InsertImage : "तसà¥à¤µà¥€à¤° इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +InsertFlashLbl : "फ़à¥à¤²à¥ˆà¤¶", +InsertFlash : "फ़à¥à¤²à¥ˆà¤¶ इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +InsertTableLbl : "टेबल", +InsertTable : "टेबल इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +InsertLineLbl : "रेखा", +InsertLine : "हॉरिज़ॉनà¥à¤Ÿà¤² रेखा इनà¥à¤¸à¤°à¥à¤Ÿ करें", +InsertSpecialCharLbl: "विशेष करॅकà¥à¤Ÿà¤°", +InsertSpecialChar : "विशेष करॅकà¥à¤Ÿà¤° इनà¥à¤¸à¤°à¥à¤Ÿ करें", +InsertSmileyLbl : "सà¥à¤®à¤¾à¤‡à¤²à¥€", +InsertSmiley : "सà¥à¤®à¤¾à¤‡à¤²à¥€ इनà¥à¤¸à¤°à¥à¤Ÿ करें", +About : "FCKeditor के बारे में", +Bold : "बोलà¥à¤¡", +Italic : "इटैलिक", +Underline : "रेखांकण", +StrikeThrough : "सà¥à¤Ÿà¥à¤°à¤¾à¤‡à¤• थà¥à¤°à¥‚", +Subscript : "अधोलेख", +Superscript : "अभिलेख", +LeftJustify : "बायीं तरफ", +CenterJustify : "बीच में", +RightJustify : "दायीं तरफ", +BlockJustify : "बà¥à¤²à¥‰à¤• जसà¥à¤Ÿà¥€à¥žà¤¾à¤ˆ", +DecreaseIndent : "इनà¥à¤¡à¥…नà¥à¤Ÿ कम करें", +IncreaseIndent : "इनà¥à¤¡à¥…नà¥à¤Ÿ बà¥à¤¾à¤¯à¥‡à¤‚", +Blockquote : "बà¥à¤²à¥‰à¤•-कोट", +CreateDiv : "डिव (Div) कनà¥à¤Ÿà¥‡à¤¨à¤° बनायें", +EditDiv : "डिव (Div) कनà¥à¤Ÿà¥‡à¤¨à¤° बदलें", +DeleteDiv : "डिव कनà¥à¤Ÿà¥‡à¤¨à¤° हटायें", +Undo : "अनà¥à¤¡à¥‚", +Redo : "रीडू", +NumberedListLbl : "अंकीय सूची", +NumberedList : "अंकीय सूची इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +BulletedListLbl : "बà¥à¤²à¥…ट सूची", +BulletedList : "बà¥à¤²à¥…ट सूची इनà¥à¤¸à¤°à¥à¤Ÿ/संपादन", +ShowTableBorders : "टेबल बॉरà¥à¤¡à¤°à¤¯à¥‡à¤‚ दिखायें", +ShowDetails : "जà¥à¤¯à¤¾à¤¦à¤¾ दिखायें", +Style : "सà¥à¤Ÿà¤¾à¤‡à¤²", +FontFormat : "फ़ॉरà¥à¤®à¥ˆà¤Ÿ", +Font : "फ़ॉनà¥à¤Ÿ", +FontSize : "साइज़", +TextColor : "टेकà¥à¤¸à¥à¤Ÿ रंग", +BGColor : "बैकà¥à¤—à¥à¤°à¤¾à¤‰à¤¨à¥à¤¡ रंग", +Source : "सोरà¥à¤¸", +Find : "खोजें", +Replace : "रीपà¥à¤²à¥‡à¤¸", +SpellCheck : "वरà¥à¤¤à¤¨à¥€ (सà¥à¤ªà¥‡à¤²à¤¿à¤‚ग) जाà¤à¤š", +UniversalKeyboard : "यूनीवरà¥à¤¸à¤² कीबोरà¥à¤¡", +PageBreakLbl : "पेज बà¥à¤°à¥‡à¤•", +PageBreak : "पेज बà¥à¤°à¥‡à¤• इनà¥à¤¸à¤°à¥à¤Ÿà¥ करें", + +Form : "फ़ॉरà¥à¤®", +Checkbox : "चॅक बॉकà¥à¤¸", +RadioButton : "रेडिओ बटन", +TextField : "टेकà¥à¤¸à¥à¤Ÿ फ़ीलà¥à¤¡", +Textarea : "टेकà¥à¤¸à¥à¤Ÿ à¤à¤°à¤¿à¤¯à¤¾", +HiddenField : "गà¥à¤ªà¥à¤¤ फ़ीलà¥à¤¡", +Button : "बटन", +SelectionField : "चà¥à¤¨à¤¾à¤µ फ़ीलà¥à¤¡", +ImageButton : "तसà¥à¤µà¥€à¤° बटन", + +FitWindow : "à¤à¤¡à¤¿à¤Ÿà¤° साइज़ को चरम सीमा तक बà¥à¤¾à¤¯à¥‡à¤‚", +ShowBlocks : "बà¥à¤²à¥‰à¤• दिखायें", + +// Context Menu +EditLink : "लिंक संपादन", +CellCM : "खाना", +RowCM : "पंकà¥à¤¤à¤¿", +ColumnCM : "कालम", +InsertRowAfter : "बाद में पंकà¥à¤¤à¤¿ डालें", +InsertRowBefore : "पहले पंकà¥à¤¤à¤¿ डालें", +DeleteRows : "पंकà¥à¤¤à¤¿à¤¯à¤¾à¤ डिलीट करें", +InsertColumnAfter : "बाद में कालम डालें", +InsertColumnBefore : "पहले कालम डालें", +DeleteColumns : "कालम डिलीट करें", +InsertCellAfter : "बाद में सैल डालें", +InsertCellBefore : "पहले सैल डालें", +DeleteCells : "सैल डिलीट करें", +MergeCells : "सैल मिलायें", +MergeRight : "बाà¤à¤¯à¤¾ विलय", +MergeDown : "नीचे विलय करें", +HorizontalSplitCell : "सैल को कà¥à¤·à¥ˆà¤¤à¤¿à¤œ सà¥à¤¥à¤¿à¤¤à¤¿ में विभाजित करें", +VerticalSplitCell : "सैल को लमà¥à¤¬à¤¾à¤•à¤¾à¤° में विभाजित करें", +TableDelete : "टेबल डिलीट करें", +CellProperties : "सैल पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +TableProperties : "टेबल पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +ImageProperties : "तसà¥à¤µà¥€à¤° पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +FlashProperties : "फ़à¥à¤²à¥ˆà¤¶ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", + +AnchorProp : "à¤à¤‚कर पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +ButtonProp : "बटन पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +CheckboxProp : "चॅक बॉकà¥à¤¸ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +HiddenFieldProp : "गà¥à¤ªà¥à¤¤ फ़ीलà¥à¤¡ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +RadioButtonProp : "रेडिओ बटन पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +ImageButtonProp : "तसà¥à¤µà¥€à¤° बटन पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +TextFieldProp : "टेकà¥à¤¸à¥à¤Ÿ फ़ीलà¥à¤¡ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +SelectionFieldProp : "चà¥à¤¨à¤¾à¤µ फ़ीलà¥à¤¡ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +TextareaProp : "टेकà¥à¤¸à¥à¤¤ à¤à¤°à¤¿à¤¯à¤¾ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +FormProp : "फ़ॉरà¥à¤® पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", + +FontFormats : "साधारण;फ़ॉरà¥à¤®à¥ˆà¤Ÿà¥…ड;पता;शीरà¥à¤·à¤• 1;शीरà¥à¤·à¤• 2;शीरà¥à¤·à¤• 3;शीरà¥à¤·à¤• 4;शीरà¥à¤·à¤• 5;शीरà¥à¤·à¤• 6;शीरà¥à¤·à¤• (DIV)", + +// Alerts and Messages +ProcessingXHTML : "XHTML पà¥à¤°à¥‹à¤¸à¥…स हो रहा है। ज़रा ठहरें...", +Done : "पूरा हà¥à¤†", +PasteWordConfirm : "आप जो टेकà¥à¤¸à¥à¤Ÿ पेसà¥à¤Ÿ करना चाहते हैं, वह वरà¥à¤¡ से कॉपी किया हà¥à¤† लग रहा है। कà¥à¤¯à¤¾ पेसà¥à¤Ÿ करने से पहले आप इसे साफ़ करना चाहेंगे?", +NotCompatiblePaste : "यह कमांड इनà¥à¤Ÿà¤°à¤¨à¥…ट à¤à¤•à¥à¤¸à¥à¤ªà¥à¤²à¥‹à¤°à¤°(Internet Explorer) 5.5 या उसके बाद के वरà¥à¥›à¤¨ के लिठही उपलबà¥à¤§ है। कà¥à¤¯à¤¾ आप बिना साफ़ किठपेसà¥à¤Ÿ करना चाहेंगे?", +UnknownToolbarItem : "अनजान टूलबार आइटम \"%1\"", +UnknownCommand : "अनजान कमानà¥à¤¡ \"%1\"", +NotImplemented : "कमानà¥à¤¡ इमà¥à¤ªà¥à¤²à¥€à¤®à¥…नà¥à¤Ÿ नहीं किया गया है", +UnknownToolbarSet : "टूलबार सॅट \"%1\" उपलबà¥à¤§ नहीं है", +NoActiveX : "आपके बà¥à¤°à¤¾à¤‰à¥›à¤°à¥ की सà¥à¤°à¤•à¥à¤¶à¤¾ सेटिंगà¥à¤¸à¥ à¤à¤¡à¤¿à¤Ÿà¤° की कà¥à¤›à¥ फ़ीचरों को सीमित करॠसकती हैं। कà¥à¤°à¤¿à¤ªà¤¯à¤¾ \"Run ActiveX controls and plug-ins\" विकलà¥à¤ª को à¤à¤¨à¥‡à¤¬à¤² करें. आपको à¤à¤°à¤°à¥à¤¸à¥ और गायब फ़ीचरà¥à¤¸à¥ का अनà¥à¤­à¤µ हो सकता है।", +BrowseServerBlocked : "रिसोरà¥à¤¸à¥‡à¥› बà¥à¤°à¤¾à¤‰à¥›à¤°à¥ नहीं खोला जा सका। कà¥à¤°à¤¿à¤ªà¤¯à¤¾ सभी पॉपà¥-अपॠबà¥à¤²à¥‰à¤•à¤°à¥à¤¸à¥ को निषà¥à¤•à¥à¤°à¤¿à¤¯ करें।", +DialogBlocked : "डायलग विनà¥à¤¡à¥‹ नहीं खोला जा सका। कà¥à¤°à¤¿à¤ªà¤¯à¤¾ सभी पॉपà¥-अपॠबà¥à¤²à¥‰à¤•à¤°à¥à¤¸à¥ को निषà¥à¤•à¥à¤°à¤¿à¤¯ करें।", +VisitLinkBlocked : "नया विनà¥à¤¡à¥‹ नहीं खोला जा सका। कà¥à¤°à¤¿à¤ªà¤¯à¤¾ सभी पॉपà¥-अपॠबà¥à¤²à¥‰à¤•à¤°à¥à¤¸à¥ को निषà¥à¤•à¥à¤°à¤¿à¤¯ करें।", + +// Dialogs +DlgBtnOK : "ठीक है", +DlgBtnCancel : "रदà¥à¤¦ करें", +DlgBtnClose : "बनà¥à¤¦ करें", +DlgBtnBrowseServer : "सरà¥à¤µà¤° बà¥à¤°à¤¾à¤‰à¥› करें", +DlgAdvancedTag : "à¤à¤¡à¥à¤µà¤¾à¤¨à¥à¤¸à¥à¤¡", +DlgOpOther : "<अनà¥à¤¯>", +DlgInfoTab : "सूचना", +DlgAlertUrl : "URL इनà¥à¤¸à¤°à¥à¤Ÿ करें", + +// General Dialogs Labels +DlgGenNotSet : "<सॅट नहीं>", +DlgGenId : "Id", +DlgGenLangDir : "भाषा लिखने की दिशा", +DlgGenLangDirLtr : "बायें से दायें (LTR)", +DlgGenLangDirRtl : "दायें से बायें (RTL)", +DlgGenLangCode : "भाषा कोड", +DlgGenAccessKey : "à¤à¤•à¥à¤¸à¥…स की", +DlgGenName : "नाम", +DlgGenTabIndex : "टैब इनà¥à¤¡à¥…कà¥à¤¸", +DlgGenLongDescr : "अधिक विवरण के लिठURL", +DlgGenClass : "सà¥à¤Ÿà¤¾à¤‡à¤²-शीट कà¥à¤²à¤¾à¤¸", +DlgGenTitle : "परामरà¥à¤¶ शीरà¥à¤¶à¤•", +DlgGenContType : "परामरà¥à¤¶ कनà¥à¤Ÿà¥…नà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤°", +DlgGenLinkCharset : "लिंक रिसोरà¥à¤¸ करॅकà¥à¤Ÿà¤° सॅट", +DlgGenStyle : "सà¥à¤Ÿà¤¾à¤‡à¤²", + +// Image Dialog +DlgImgTitle : "तसà¥à¤µà¥€à¤° पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +DlgImgInfoTab : "तसà¥à¤µà¥€à¤° की जानकारी", +DlgImgBtnUpload : "इसे सरà¥à¤µà¤° को भेजें", +DlgImgURL : "URL", +DlgImgUpload : "अपलोड", +DlgImgAlt : "वैकलà¥à¤ªà¤¿à¤• टेकà¥à¤¸à¥à¤Ÿ", +DlgImgWidth : "चौड़ाई", +DlgImgHeight : "ऊà¤à¤šà¤¾à¤ˆ", +DlgImgLockRatio : "लॉक अनà¥à¤ªà¤¾à¤¤", +DlgBtnResetSize : "रीसॅट साइज़", +DlgImgBorder : "बॉरà¥à¤¡à¤°", +DlgImgHSpace : "हॉरिज़ॉनà¥à¤Ÿà¤² सà¥à¤ªà¥‡à¤¸", +DlgImgVSpace : "वरà¥à¤Ÿà¤¿à¤•à¤² सà¥à¤ªà¥‡à¤¸", +DlgImgAlign : "à¤à¤²à¤¾à¤‡à¤¨", +DlgImgAlignLeft : "दायें", +DlgImgAlignAbsBottom: "Abs नीचे", +DlgImgAlignAbsMiddle: "Abs ऊपर", +DlgImgAlignBaseline : "मूल रेखा", +DlgImgAlignBottom : "नीचे", +DlgImgAlignMiddle : "मधà¥à¤¯", +DlgImgAlignRight : "दायें", +DlgImgAlignTextTop : "टेकà¥à¤¸à¥à¤Ÿ ऊपर", +DlgImgAlignTop : "ऊपर", +DlgImgPreview : "पà¥à¤°à¥€à¤µà¥à¤¯à¥‚", +DlgImgAlertUrl : "तसà¥à¤µà¥€à¤° का URL टाइप करें ", +DlgImgLinkTab : "लिंक", + +// Flash Dialog +DlgFlashTitle : "फ़à¥à¤²à¥ˆà¤¶ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +DlgFlashChkPlay : "ऑटो पà¥à¤²à¥‡", +DlgFlashChkLoop : "लूप", +DlgFlashChkMenu : "फ़à¥à¤²à¥ˆà¤¶ मॅनà¥à¤¯à¥‚ का पà¥à¤°à¤¯à¥‹à¤— करें", +DlgFlashScale : "सà¥à¤•à¥‡à¤²", +DlgFlashScaleAll : "सभी दिखायें", +DlgFlashScaleNoBorder : "कोई बॉरà¥à¤¡à¤° नहीं", +DlgFlashScaleFit : "बिलà¥à¤•à¥à¤² फ़िट", + +// Link Dialog +DlgLnkWindowTitle : "लिंक", +DlgLnkInfoTab : "लिंक ", +DlgLnkTargetTab : "टारà¥à¤—ेट", + +DlgLnkType : "लिंक पà¥à¤°à¤•à¤¾à¤°", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "इस पेज का à¤à¤‚कर", +DlgLnkTypeEMail : "ई-मेल", +DlgLnkProto : "पà¥à¤°à¥‹à¤Ÿà¥‹à¤•à¥‰à¤²", +DlgLnkProtoOther : "<अनà¥à¤¯>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "à¤à¤‚कर चà¥à¤¨à¥‡à¤‚", +DlgLnkAnchorByName : "à¤à¤‚कर नाम से", +DlgLnkAnchorById : "à¤à¤²à¥€à¤®à¥…नà¥à¤Ÿ Id से", +DlgLnkNoAnchors : "(डॉकà¥à¤¯à¥‚मॅनà¥à¤Ÿ में à¤à¤‚करà¥à¤¸ की संखà¥à¤¯à¤¾)", +DlgLnkEMail : "ई-मेल पता", +DlgLnkEMailSubject : "संदेश विषय", +DlgLnkEMailBody : "संदेश", +DlgLnkUpload : "अपलोड", +DlgLnkBtnUpload : "इसे सरà¥à¤µà¤° को भेजें", + +DlgLnkTarget : "टारà¥à¤—ेट", +DlgLnkTargetFrame : "<फ़à¥à¤°à¥‡à¤®>", +DlgLnkTargetPopup : "<पॉप-अप विनà¥à¤¡à¥‹>", +DlgLnkTargetBlank : "नया विनà¥à¤¡à¥‹ (_blank)", +DlgLnkTargetParent : "मूल विनà¥à¤¡à¥‹ (_parent)", +DlgLnkTargetSelf : "इसी विनà¥à¤¡à¥‹ (_self)", +DlgLnkTargetTop : "शीरà¥à¤· विनà¥à¤¡à¥‹ (_top)", +DlgLnkTargetFrameName : "टारà¥à¤—ेट फ़à¥à¤°à¥‡à¤® का नाम", +DlgLnkPopWinName : "पॉप-अप विनà¥à¤¡à¥‹ का नाम", +DlgLnkPopWinFeat : "पॉप-अप विनà¥à¤¡à¥‹ फ़ीचरà¥à¤¸", +DlgLnkPopResize : "साइज़ बदला जा सकता है", +DlgLnkPopLocation : "लोकेशन बार", +DlgLnkPopMenu : "मॅनà¥à¤¯à¥‚ बार", +DlgLnkPopScroll : "सà¥à¤•à¥à¤°à¥‰à¤² बार", +DlgLnkPopStatus : "सà¥à¤Ÿà¥‡à¤Ÿà¤¸ बार", +DlgLnkPopToolbar : "टूल बार", +DlgLnkPopFullScrn : "फ़à¥à¤² सà¥à¤•à¥à¤°à¥€à¤¨ (IE)", +DlgLnkPopDependent : "डिपेनà¥à¤¡à¥…नà¥à¤Ÿ (Netscape)", +DlgLnkPopWidth : "चौड़ाई", +DlgLnkPopHeight : "ऊà¤à¤šà¤¾à¤ˆ", +DlgLnkPopLeft : "बायीं तरफ", +DlgLnkPopTop : "दायीं तरफ", + +DlnLnkMsgNoUrl : "लिंक URL टाइप करें", +DlnLnkMsgNoEMail : "ई-मेल पता टाइप करें", +DlnLnkMsgNoAnchor : "à¤à¤‚कर चà¥à¤¨à¥‡à¤‚", +DlnLnkMsgInvPopName : "पॉप-अप का नाम अलà¥à¤«à¤¾à¤¬à¥‡à¤Ÿ से शà¥à¤°à¥‚ होना चाहिये और उसमें सà¥à¤ªà¥‡à¤¸ नहीं होने चाहिà¤", + +// Color Dialog +DlgColorTitle : "रंग चà¥à¤¨à¥‡à¤‚", +DlgColorBtnClear : "साफ़ करें", +DlgColorHighlight : "हाइलाइट", +DlgColorSelected : "सॅलॅकà¥à¤Ÿà¥…ड", + +// Smiley Dialog +DlgSmileyTitle : "सà¥à¤®à¤¾à¤‡à¤²à¥€ इनà¥à¤¸à¤°à¥à¤Ÿ करें", + +// Special Character Dialog +DlgSpecialCharTitle : "विशेष करॅकà¥à¤Ÿà¤° चà¥à¤¨à¥‡à¤‚", + +// Table Dialog +DlgTableTitle : "टेबल पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +DlgTableRows : "पंकà¥à¤¤à¤¿à¤¯à¤¾à¤", +DlgTableColumns : "कालम", +DlgTableBorder : "बॉरà¥à¤¡à¤° साइज़", +DlgTableAlign : "à¤à¤²à¤¾à¤‡à¤¨à¥à¤®à¥…नà¥à¤Ÿ", +DlgTableAlignNotSet : "<सॅट नहीं>", +DlgTableAlignLeft : "दायें", +DlgTableAlignCenter : "बीच में", +DlgTableAlignRight : "बायें", +DlgTableWidth : "चौड़ाई", +DlgTableWidthPx : "पिकà¥à¤¸à¥ˆà¤²", +DlgTableWidthPc : "पà¥à¤°à¤¤à¤¿à¤¶à¤¤", +DlgTableHeight : "ऊà¤à¤šà¤¾à¤ˆ", +DlgTableCellSpace : "सैल अंतर", +DlgTableCellPad : "सैल पैडिंग", +DlgTableCaption : "शीरà¥à¤·à¤•", +DlgTableSummary : "सारांश", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "सैल पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +DlgCellWidth : "चौड़ाई", +DlgCellWidthPx : "पिकà¥à¤¸à¥ˆà¤²", +DlgCellWidthPc : "पà¥à¤°à¤¤à¤¿à¤¶à¤¤", +DlgCellHeight : "ऊà¤à¤šà¤¾à¤ˆ", +DlgCellWordWrap : "वरà¥à¤¡ रैप", +DlgCellWordWrapNotSet : "<सॅट नहीं>", +DlgCellWordWrapYes : "हाà¤", +DlgCellWordWrapNo : "नहीं", +DlgCellHorAlign : "हॉरिज़ॉनà¥à¤Ÿà¤² à¤à¤²à¤¾à¤‡à¤¨à¥à¤®à¥…नà¥à¤Ÿ", +DlgCellHorAlignNotSet : "<सॅट नहीं>", +DlgCellHorAlignLeft : "दायें", +DlgCellHorAlignCenter : "बीच में", +DlgCellHorAlignRight: "बायें", +DlgCellVerAlign : "वरà¥à¤Ÿà¤¿à¤•à¤² à¤à¤²à¤¾à¤‡à¤¨à¥à¤®à¥…नà¥à¤Ÿ", +DlgCellVerAlignNotSet : "<सॅट नहीं>", +DlgCellVerAlignTop : "ऊपर", +DlgCellVerAlignMiddle : "मधà¥à¤¯", +DlgCellVerAlignBottom : "नीचे", +DlgCellVerAlignBaseline : "मूलरेखा", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "पंकà¥à¤¤à¤¿ सà¥à¤ªà¥ˆà¤¨", +DlgCellCollSpan : "कालम सà¥à¤ªà¥ˆà¤¨", +DlgCellBackColor : "बैकà¥à¤—à¥à¤°à¤¾à¤‰à¤¨à¥à¤¡ रंग", +DlgCellBorderColor : "बॉरà¥à¤¡à¤° का रंग", +DlgCellBtnSelect : "चà¥à¤¨à¥‡à¤‚...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "खोजें और बदलें", + +// Find Dialog +DlgFindTitle : "खोजें", +DlgFindFindBtn : "खोजें", +DlgFindNotFoundMsg : "आपके दà¥à¤µà¤¾à¤°à¤¾ दिया गया टेकà¥à¤¸à¥à¤Ÿ नहीं मिला", + +// Replace Dialog +DlgReplaceTitle : "रिपà¥à¤²à¥‡à¤¸", +DlgReplaceFindLbl : "यह खोजें:", +DlgReplaceReplaceLbl : "इससे रिपà¥à¤²à¥‡à¤¸ करें:", +DlgReplaceCaseChk : "केस मिलायें", +DlgReplaceReplaceBtn : "रिपà¥à¤²à¥‡à¤¸", +DlgReplaceReplAllBtn : "सभी रिपà¥à¤²à¥‡à¤¸ करें", +DlgReplaceWordChk : "पूरा शबà¥à¤¦ मिलायें", + +// Paste Operations / Dialog +PasteErrorCut : "आपके बà¥à¤°à¤¾à¤‰à¥›à¤° की सà¥à¤°à¤•à¥à¤·à¤¾ सॅटिनà¥à¤—à¥à¤¸ ने कट करने की अनà¥à¤®à¤¤à¤¿ नहीं पà¥à¤°à¤¦à¤¾à¤¨ की है। (Ctrl+X) का पà¥à¤°à¤¯à¥‹à¤— करें।", +PasteErrorCopy : "आपके बà¥à¤°à¤¾à¤†à¤‰à¥›à¤° की सà¥à¤°à¤•à¥à¤·à¤¾ सॅटिनà¥à¤—à¥à¤¸ ने कॉपी करने की अनà¥à¤®à¤¤à¤¿ नहीं पà¥à¤°à¤¦à¤¾à¤¨ की है। (Ctrl+C) का पà¥à¤°à¤¯à¥‹à¤— करें।", + +PasteAsText : "पेसà¥à¤Ÿ (सादा टॅकà¥à¤¸à¥à¤Ÿ)", +PasteFromWord : "पेसà¥à¤Ÿ (वरà¥à¤¡ से)", + +DlgPasteMsg2 : "Ctrl+V का पà¥à¤°à¤¯à¥‹à¤— करके पेसà¥à¤Ÿ करें और ठीक है करें.", +DlgPasteSec : "आपके बà¥à¤°à¤¾à¤‰à¥›à¤° की सà¥à¤°à¤•à¥à¤·à¤¾ आपके बà¥à¤°à¤¾à¤‰à¥›à¤° की सà¥à¤°Kश सैटिंग के कारण, à¤à¤¡à¤¿à¤Ÿà¤° आपके कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡ डेटा को नहीं पा सकता है. आपको उसे इस विनà¥à¤¡à¥‹ में दोबारा पेसà¥à¤Ÿ करना होगा.", +DlgPasteIgnoreFont : "फ़ॉनà¥à¤Ÿ परिभाषा निकालें", +DlgPasteRemoveStyles : "सà¥à¤Ÿà¤¾à¤‡à¤² परिभाषा निकालें", + +// Color Picker +ColorAutomatic : "सà¥à¤µà¤šà¤¾à¤²à¤¿à¤¤", +ColorMoreColors : "और रंग...", + +// Document Properties +DocProps : "डॉकà¥à¤¯à¥‚मॅनà¥à¤Ÿ पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", + +// Anchor Dialog +DlgAnchorTitle : "à¤à¤‚कर पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +DlgAnchorName : "à¤à¤‚कर का नाम", +DlgAnchorErrorName : "à¤à¤‚कर का नाम टाइप करें", + +// Speller Pages Dialog +DlgSpellNotInDic : "शबà¥à¤¦à¤•à¥‹à¤¶ में नहीं", +DlgSpellChangeTo : "इसमें बदलें", +DlgSpellBtnIgnore : "इगà¥à¤¨à¥‹à¤°", +DlgSpellBtnIgnoreAll : "सभी इगà¥à¤¨à¥‹à¤° करें", +DlgSpellBtnReplace : "रिपà¥à¤²à¥‡à¤¸", +DlgSpellBtnReplaceAll : "सभी रिपà¥à¤²à¥‡à¤¸ करें", +DlgSpellBtnUndo : "अनà¥à¤¡à¥‚", +DlgSpellNoSuggestions : "- कोई सà¥à¤à¤¾à¤µ नहीं -", +DlgSpellProgress : "वरà¥à¤¤à¤¨à¥€ की जाà¤à¤š (सà¥à¤ªà¥…ल-चॅक) जारी है...", +DlgSpellNoMispell : "वरà¥à¤¤à¤¨à¥€ की जाà¤à¤š : कोई गलत वरà¥à¤¤à¤¨à¥€ (सà¥à¤ªà¥…लिंग) नहीं पाई गई", +DlgSpellNoChanges : "वरà¥à¤¤à¤¨à¥€ की जाà¤à¤š :कोई शबà¥à¤¦ नहीं बदला गया", +DlgSpellOneChange : "वरà¥à¤¤à¤¨à¥€ की जाà¤à¤š : à¤à¤• शबà¥à¤¦ बदला गया", +DlgSpellManyChanges : "वरà¥à¤¤à¤¨à¥€ की जाà¤à¤š : %1 शबà¥à¤¦ बदले गये", + +IeSpellDownload : "सà¥à¤ªà¥…ल-चॅकर इनà¥à¤¸à¥à¤Ÿà¤¾à¤² नहीं किया गया है। कà¥à¤¯à¤¾ आप इसे डा‌उनलोड करना चाहेंगे?", + +// Button Dialog +DlgButtonText : "टेकà¥à¤¸à¥à¤Ÿ (वैलà¥à¤¯à¥‚)", +DlgButtonType : "पà¥à¤°à¤•à¤¾à¤°", +DlgButtonTypeBtn : "बटन", +DlgButtonTypeSbm : "सबà¥à¤®à¤¿à¤Ÿ", +DlgButtonTypeRst : "रिसेट", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "नाम", +DlgCheckboxValue : "वैलà¥à¤¯à¥‚", +DlgCheckboxSelected : "सॅलॅकà¥à¤Ÿà¥…ड", + +// Form Dialog +DlgFormName : "नाम", +DlgFormAction : "कà¥à¤°à¤¿à¤¯à¤¾", +DlgFormMethod : "तरीका", + +// Select Field Dialog +DlgSelectName : "नाम", +DlgSelectValue : "वैलà¥à¤¯à¥‚", +DlgSelectSize : "साइज़", +DlgSelectLines : "पंकà¥à¤¤à¤¿à¤¯à¤¾à¤", +DlgSelectChkMulti : "à¤à¤• से जà¥à¤¯à¤¾à¤¦à¤¾ विकलà¥à¤ª चà¥à¤¨à¤¨à¥‡ दें", +DlgSelectOpAvail : "उपलबà¥à¤§ विकलà¥à¤ª", +DlgSelectOpText : "टेकà¥à¤¸à¥à¤Ÿ", +DlgSelectOpValue : "वैलà¥à¤¯à¥‚", +DlgSelectBtnAdd : "जोड़ें", +DlgSelectBtnModify : "बदलें", +DlgSelectBtnUp : "ऊपर", +DlgSelectBtnDown : "नीचे", +DlgSelectBtnSetValue : "चà¥à¤¨à¥€ गई वैलà¥à¤¯à¥‚ सॅट करें", +DlgSelectBtnDelete : "डिलीट", + +// Textarea Dialog +DlgTextareaName : "नाम", +DlgTextareaCols : "कालम", +DlgTextareaRows : "पंकà¥à¤¤à¤¿à¤¯à¤¾à¤‚", + +// Text Field Dialog +DlgTextName : "नाम", +DlgTextValue : "वैलà¥à¤¯à¥‚", +DlgTextCharWidth : "करॅकà¥à¤Ÿà¤° की चौà¥à¤¾à¤ˆ", +DlgTextMaxChars : "अधिकतम करॅकà¥à¤Ÿà¤°", +DlgTextType : "टाइप", +DlgTextTypeText : "टेकà¥à¤¸à¥à¤Ÿ", +DlgTextTypePass : "पासà¥à¤µà¤°à¥à¤¡", + +// Hidden Field Dialog +DlgHiddenName : "नाम", +DlgHiddenValue : "वैलà¥à¤¯à¥‚", + +// Bulleted List Dialog +BulletedListProp : "बà¥à¤²à¥…ट सूची पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +NumberedListProp : "अंकीय सूची पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€à¥›", +DlgLstStart : "पà¥à¤°à¤¾à¤°à¤®à¥à¤­", +DlgLstType : "पà¥à¤°à¤•à¤¾à¤°", +DlgLstTypeCircle : "गोल", +DlgLstTypeDisc : "डिसà¥à¤•", +DlgLstTypeSquare : "चौकॊण", +DlgLstTypeNumbers : "अंक (1, 2, 3)", +DlgLstTypeLCase : "छोटे अकà¥à¤·à¤° (a, b, c)", +DlgLstTypeUCase : "बड़े अकà¥à¤·à¤° (A, B, C)", +DlgLstTypeSRoman : "छोटे रोमन अंक (i, ii, iii)", +DlgLstTypeLRoman : "बड़े रोमन अंक (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "आम", +DlgDocBackTab : "बैकà¥à¤—à¥à¤°à¤¾à¤‰à¤¨à¥à¤¡", +DlgDocColorsTab : "रंग और मारà¥à¤œà¤¿à¤¨", +DlgDocMetaTab : "मॅटाडेटा", + +DlgDocPageTitle : "पेज शीरà¥à¤·à¤•", +DlgDocLangDir : "भाषा लिखने की दिशा", +DlgDocLangDirLTR : "बायें से दायें (LTR)", +DlgDocLangDirRTL : "दायें से बायें (RTL)", +DlgDocLangCode : "भाषा कोड", +DlgDocCharSet : "करेकà¥à¤Ÿà¤° सॅट à¤à¤¨à¥à¤•à¥‹à¤¡à¤¿à¤‚ग", +DlgDocCharSetCE : "मधà¥à¤¯ यूरोपीय (Central European)", +DlgDocCharSetCT : "चीनी (Chinese Traditional Big5)", +DlgDocCharSetCR : "सिरीलिक (Cyrillic)", +DlgDocCharSetGR : "यवन (Greek)", +DlgDocCharSetJP : "जापानी (Japanese)", +DlgDocCharSetKR : "कोरीयन (Korean)", +DlgDocCharSetTR : "तà¥à¤°à¥à¤•à¥€ (Turkish)", +DlgDocCharSetUN : "यूनीकोड (UTF-8)", +DlgDocCharSetWE : "पशà¥à¤šà¤¿à¤® यूरोपीय (Western European)", +DlgDocCharSetOther : "अनà¥à¤¯ करेकà¥à¤Ÿà¤° सॅट à¤à¤¨à¥à¤•à¥‹à¤¡à¤¿à¤‚ग", + +DlgDocDocType : "डॉकà¥à¤¯à¥‚मॅनà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤° शीरà¥à¤·à¤•", +DlgDocDocTypeOther : "अनà¥à¤¯ डॉकà¥à¤¯à¥‚मॅनà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤° शीरà¥à¤·à¤•", +DlgDocIncXHTML : "XHTML सूचना समà¥à¤®à¤¿à¤²à¤¿à¤¤ करें", +DlgDocBgColor : "बैकà¥à¤—à¥à¤°à¤¾à¤‰à¤¨à¥à¤¡ रंग", +DlgDocBgImage : "बैकà¥à¤—à¥à¤°à¤¾à¤‰à¤¨à¥à¤¡ तसà¥à¤µà¥€à¤° URL", +DlgDocBgNoScroll : "सà¥à¤•à¥à¤°à¥‰à¤² न करने वाला बैकà¥à¤—à¥à¤°à¤¾à¤‰à¤¨à¥à¤¡", +DlgDocCText : "टेकà¥à¤¸à¥à¤Ÿ", +DlgDocCLink : "लिंक", +DlgDocCVisited : "विज़िट किया गया लिंक", +DlgDocCActive : "सकà¥à¤°à¤¿à¤¯ लिंक", +DlgDocMargins : "पेज मारà¥à¤œà¤¿à¤¨", +DlgDocMaTop : "ऊपर", +DlgDocMaLeft : "बायें", +DlgDocMaRight : "दायें", +DlgDocMaBottom : "नीचे", +DlgDocMeIndex : "डॉकà¥à¤¯à¥à¤®à¥…नà¥à¤Ÿ इनà¥à¤¡à¥‡à¤•à¥à¤¸ संकेतशबà¥à¤¦ (अलà¥à¤ªà¤µà¤¿à¤°à¤¾à¤® से अलग करें)", +DlgDocMeDescr : "डॉकà¥à¤¯à¥‚मॅनà¥à¤Ÿ करॅकà¥à¤Ÿà¤°à¤¨", +DlgDocMeAuthor : "लेखक", +DlgDocMeCopy : "कॉपीराइट", +DlgDocPreview : "पà¥à¤°à¥€à¤µà¥à¤¯à¥‚", + +// Templates Dialog +Templates : "टॅमà¥à¤ªà¥à¤²à¥‡à¤Ÿ", +DlgTemplatesTitle : "कनà¥à¤Ÿà¥‡à¤¨à¥à¤Ÿ टॅमà¥à¤ªà¥à¤²à¥‡à¤Ÿ", +DlgTemplatesSelMsg : "à¤à¤¡à¤¿à¤Ÿà¤° में ओपन करने हेतॠटॅमà¥à¤ªà¥à¤²à¥‡à¤Ÿ चà¥à¤¨à¥‡à¤‚(वरà¥à¤¤à¤®à¤¾à¤¨ कनà¥à¤Ÿà¥…नà¥à¤Ÿ सेव नहीं होंगे):", +DlgTemplatesLoading : "टॅमà¥à¤ªà¥à¤²à¥‡à¤Ÿ सूची लोड की जा रही है। ज़रा ठहरें...", +DlgTemplatesNoTpl : "(कोई टॅमà¥à¤ªà¥à¤²à¥‡à¤Ÿ डिफ़ाइन नहीं किया गया है)", +DlgTemplatesReplace : "मूल शबà¥à¤¦à¥‹à¤‚ को बदलें", + +// About Dialog +DlgAboutAboutTab : "FCKEditor के बारे में", +DlgAboutBrowserInfoTab : "बà¥à¤°à¤¾à¤‰à¥›à¤° के बारे में", +DlgAboutLicenseTab : "लाइसैनà¥à¤¸", +DlgAboutVersion : "वरà¥à¥›à¤¨", +DlgAboutInfo : "अधिक जानकारी के लिये यहाठजायें:", + +// Div Dialog +DlgDivGeneralTab : "सामानà¥à¤¯", +DlgDivAdvancedTab : "à¤à¤¡à¥à¤µà¤¾à¤¨à¥à¤¸à¥à¤¡", +DlgDivStyle : "सà¥à¤Ÿà¤¾à¤‡à¤²", +DlgDivInlineStyle : "इनलाइन सà¥à¤Ÿà¤¾à¤‡à¤²", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/hr.js b/www/js/FCKeditor/editor/lang/hr.js new file mode 100644 index 0000000..6939473 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/hr.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Croatian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Smanji trake s alatima", +ToolbarExpand : "ProÅ¡iri trake s alatima", + +// Toolbar Items and Context Menu +Save : "Snimi", +NewPage : "Nova stranica", +Preview : "Pregledaj", +Cut : "Izreži", +Copy : "Kopiraj", +Paste : "Zalijepi", +PasteText : "Zalijepi kao Äisti tekst", +PasteWord : "Zalijepi iz Worda", +Print : "IspiÅ¡i", +SelectAll : "Odaberi sve", +RemoveFormat : "Ukloni formatiranje", +InsertLinkLbl : "Link", +InsertLink : "Ubaci/promijeni link", +RemoveLink : "Ukloni link", +VisitLink : "Otvori link", +Anchor : "Ubaci/promijeni sidro", +AnchorDelete : "Ukloni sidro", +InsertImageLbl : "Slika", +InsertImage : "Ubaci/promijeni sliku", +InsertFlashLbl : "Flash", +InsertFlash : "Ubaci/promijeni Flash", +InsertTableLbl : "Tablica", +InsertTable : "Ubaci/promijeni tablicu", +InsertLineLbl : "Linija", +InsertLine : "Ubaci vodoravnu liniju", +InsertSpecialCharLbl: "Posebni karakteri", +InsertSpecialChar : "Ubaci posebne znakove", +InsertSmileyLbl : "SmjeÅ¡ko", +InsertSmiley : "Ubaci smjeÅ¡ka", +About : "O FCKeditoru", +Bold : "Podebljaj", +Italic : "Ukosi", +Underline : "Potcrtano", +StrikeThrough : "Precrtano", +Subscript : "Subscript", +Superscript : "Superscript", +LeftJustify : "Lijevo poravnanje", +CenterJustify : "SrediÅ¡nje poravnanje", +RightJustify : "Desno poravnanje", +BlockJustify : "Blok poravnanje", +DecreaseIndent : "Pomakni ulijevo", +IncreaseIndent : "Pomakni udesno", +Blockquote : "Blockquote", +CreateDiv : "Napravi Div kontejner", +EditDiv : "Uredi Div kontejner", +DeleteDiv : "Ukloni Div kontejner", +Undo : "PoniÅ¡ti", +Redo : "Ponovi", +NumberedListLbl : "BrojÄana lista", +NumberedList : "Ubaci/ukloni brojÄanu listu", +BulletedListLbl : "ObiÄna lista", +BulletedList : "Ubaci/ukloni obiÄnu listu", +ShowTableBorders : "Prikaži okvir tablice", +ShowDetails : "Prikaži detalje", +Style : "Stil", +FontFormat : "Format", +Font : "Font", +FontSize : "VeliÄina", +TextColor : "Boja teksta", +BGColor : "Boja pozadine", +Source : "Kôd", +Find : "PronaÄ‘i", +Replace : "Zamijeni", +SpellCheck : "Provjeri pravopis", +UniversalKeyboard : "Univerzalna tipkovnica", +PageBreakLbl : "Prijelom stranice", +PageBreak : "Ubaci prijelom stranice", + +Form : "Form", +Checkbox : "Checkbox", +RadioButton : "Radio Button", +TextField : "Text Field", +Textarea : "Textarea", +HiddenField : "Hidden Field", +Button : "Button", +SelectionField : "Selection Field", +ImageButton : "Image Button", + +FitWindow : "Povećaj veliÄinu editora", +ShowBlocks : "Prikaži blokove", + +// Context Menu +EditLink : "Promijeni link", +CellCM : "Ćelija", +RowCM : "Red", +ColumnCM : "Kolona", +InsertRowAfter : "Ubaci red poslije", +InsertRowBefore : "Ubaci red prije", +DeleteRows : "IzbriÅ¡i redove", +InsertColumnAfter : "Ubaci kolonu poslije", +InsertColumnBefore : "Ubaci kolonu prije", +DeleteColumns : "IzbriÅ¡i kolone", +InsertCellAfter : "Ubaci ćeliju poslije", +InsertCellBefore : "Ubaci ćeliju prije", +DeleteCells : "IzbriÅ¡i ćelije", +MergeCells : "Spoji ćelije", +MergeRight : "Spoji desno", +MergeDown : "Spoji dolje", +HorizontalSplitCell : "Podijeli ćeliju vodoravno", +VerticalSplitCell : "Podijeli ćeliju okomito", +TableDelete : "IzbriÅ¡i tablicu", +CellProperties : "Svojstva ćelije", +TableProperties : "Svojstva tablice", +ImageProperties : "Svojstva slike", +FlashProperties : "Flash svojstva", + +AnchorProp : "Svojstva sidra", +ButtonProp : "Image Button svojstva", +CheckboxProp : "Checkbox svojstva", +HiddenFieldProp : "Hidden Field svojstva", +RadioButtonProp : "Radio Button svojstva", +ImageButtonProp : "Image Button svojstva", +TextFieldProp : "Text Field svojstva", +SelectionFieldProp : "Selection svojstva", +TextareaProp : "Textarea svojstva", +FormProp : "Form svojstva", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "ObraÄ‘ujem XHTML. Molimo priÄekajte...", +Done : "ZavrÅ¡io", +PasteWordConfirm : "Tekst koji želite zalijepiti Äini se da je kopiran iz Worda. Želite li prije oÄistiti tekst?", +NotCompatiblePaste : "Ova naredba je dostupna samo u Internet Exploreru 5.5 ili novijem. Želite li nastaviti bez Äišćenja?", +UnknownToolbarItem : "Nepoznati Älan trake s alatima \"%1\"", +UnknownCommand : "Nepoznata naredba \"%1\"", +NotImplemented : "Naredba nije implementirana", +UnknownToolbarSet : "Traka s alatima \"%1\" ne postoji", +NoActiveX : "VaÅ¡e postavke pretraživaÄa mogle bi ograniÄiti neke od mogućnosti editora. Morate ukljuÄiti opciju \"Run ActiveX controls and plug-ins\" u postavkama. Ukoliko to ne uÄinite, moguće su razliite greÅ¡ke tijekom rada.", +BrowseServerBlocked : "PretraivaÄ nije moguće otvoriti. Provjerite da li je ukljuÄeno blokiranje pop-up prozora.", +DialogBlocked : "Nije moguće otvoriti novi prozor. Provjerite da li je ukljuÄeno blokiranje pop-up prozora.", +VisitLinkBlocked : "Nije moguće otvoriti novi prozor. Provjerite da li je ukljuÄeno blokiranje pop-up prozora.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "PoniÅ¡ti", +DlgBtnClose : "Zatvori", +DlgBtnBrowseServer : "Pretraži server", +DlgAdvancedTag : "Napredno", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Molimo unesite URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Smjer jezika", +DlgGenLangDirLtr : "S lijeva na desno (LTR)", +DlgGenLangDirRtl : "S desna na lijevo (RTL)", +DlgGenLangCode : "Kôd jezika", +DlgGenAccessKey : "Pristupna tipka", +DlgGenName : "Naziv", +DlgGenTabIndex : "Tab Indeks", +DlgGenLongDescr : "DugaÄki opis URL", +DlgGenClass : "Stylesheet klase", +DlgGenTitle : "Advisory naslov", +DlgGenContType : "Advisory vrsta sadržaja", +DlgGenLinkCharset : "Kodna stranica povezanih resursa", +DlgGenStyle : "Stil", + +// Image Dialog +DlgImgTitle : "Svojstva slika", +DlgImgInfoTab : "Info slike", +DlgImgBtnUpload : "PoÅ¡alji na server", +DlgImgURL : "URL", +DlgImgUpload : "PoÅ¡alji", +DlgImgAlt : "Alternativni tekst", +DlgImgWidth : "Å irina", +DlgImgHeight : "Visina", +DlgImgLockRatio : "ZakljuÄaj odnos", +DlgBtnResetSize : "ObriÅ¡i veliÄinu", +DlgImgBorder : "Okvir", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Poravnaj", +DlgImgAlignLeft : "Lijevo", +DlgImgAlignAbsBottom: "Abs dolje", +DlgImgAlignAbsMiddle: "Abs sredina", +DlgImgAlignBaseline : "Bazno", +DlgImgAlignBottom : "Dolje", +DlgImgAlignMiddle : "Sredina", +DlgImgAlignRight : "Desno", +DlgImgAlignTextTop : "Vrh teksta", +DlgImgAlignTop : "Vrh", +DlgImgPreview : "Pregledaj", +DlgImgAlertUrl : "Unesite URL slike", +DlgImgLinkTab : "Link", + +// Flash Dialog +DlgFlashTitle : "Flash svojstva", +DlgFlashChkPlay : "Auto Play", +DlgFlashChkLoop : "Ponavljaj", +DlgFlashChkMenu : "Omogući Flash izbornik", +DlgFlashScale : "Omjer", +DlgFlashScaleAll : "Prikaži sve", +DlgFlashScaleNoBorder : "Bez okvira", +DlgFlashScaleFit : "ToÄna veliÄina", + +// Link Dialog +DlgLnkWindowTitle : "Link", +DlgLnkInfoTab : "Link Info", +DlgLnkTargetTab : "Meta", + +DlgLnkType : "Link vrsta", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Sidro na ovoj stranici", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protokol", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Odaberi sidro", +DlgLnkAnchorByName : "Po nazivu sidra", +DlgLnkAnchorById : "Po Id elementa", +DlgLnkNoAnchors : "(Nema dostupnih sidra)", +DlgLnkEMail : "E-Mail adresa", +DlgLnkEMailSubject : "Naslov", +DlgLnkEMailBody : "Sadržaj poruke", +DlgLnkUpload : "PoÅ¡alji", +DlgLnkBtnUpload : "PoÅ¡alji na server", + +DlgLnkTarget : "Meta", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Novi prozor (_blank)", +DlgLnkTargetParent : "Roditeljski prozor (_parent)", +DlgLnkTargetSelf : "Isti prozor (_self)", +DlgLnkTargetTop : "VrÅ¡ni prozor (_top)", +DlgLnkTargetFrameName : "Ime ciljnog okvira", +DlgLnkPopWinName : "Naziv popup prozora", +DlgLnkPopWinFeat : "Mogućnosti popup prozora", +DlgLnkPopResize : "Promjenljive veliÄine", +DlgLnkPopLocation : "Traka za lokaciju", +DlgLnkPopMenu : "Izborna traka", +DlgLnkPopScroll : "Scroll traka", +DlgLnkPopStatus : "Statusna traka", +DlgLnkPopToolbar : "Traka s alatima", +DlgLnkPopFullScrn : "Cijeli ekran (IE)", +DlgLnkPopDependent : "Ovisno (Netscape)", +DlgLnkPopWidth : "Å irina", +DlgLnkPopHeight : "Visina", +DlgLnkPopLeft : "Lijeva pozicija", +DlgLnkPopTop : "Gornja pozicija", + +DlnLnkMsgNoUrl : "Molimo upiÅ¡ite URL link", +DlnLnkMsgNoEMail : "Molimo upiÅ¡ite e-mail adresu", +DlnLnkMsgNoAnchor : "Molimo odaberite sidro", +DlnLnkMsgInvPopName : "Ime popup prozora mora poÄeti sa slovom i ne smije sadržavati razmake", + +// Color Dialog +DlgColorTitle : "Odaberite boju", +DlgColorBtnClear : "ObriÅ¡i", +DlgColorHighlight : "Osvijetli", +DlgColorSelected : "Odaberi", + +// Smiley Dialog +DlgSmileyTitle : "Ubaci smjeÅ¡ka", + +// Special Character Dialog +DlgSpecialCharTitle : "Odaberite posebni karakter", + +// Table Dialog +DlgTableTitle : "Svojstva tablice", +DlgTableRows : "Redova", +DlgTableColumns : "Kolona", +DlgTableBorder : "VeliÄina okvira", +DlgTableAlign : "Poravnanje", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Lijevo", +DlgTableAlignCenter : "SrediÅ¡nje", +DlgTableAlignRight : "Desno", +DlgTableWidth : "Å irina", +DlgTableWidthPx : "piksela", +DlgTableWidthPc : "postotaka", +DlgTableHeight : "Visina", +DlgTableCellSpace : "Prostornost ćelija", +DlgTableCellPad : "Razmak ćelija", +DlgTableCaption : "Naslov", +DlgTableSummary : "Sažetak", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Svojstva ćelije", +DlgCellWidth : "Å irina", +DlgCellWidthPx : "piksela", +DlgCellWidthPc : "postotaka", +DlgCellHeight : "Visina", +DlgCellWordWrap : "Word Wrap", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Da", +DlgCellWordWrapNo : "Ne", +DlgCellHorAlign : "Vodoravno poravnanje", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Lijevo", +DlgCellHorAlignCenter : "SrediÅ¡nje", +DlgCellHorAlignRight: "Desno", +DlgCellVerAlign : "Okomito poravnanje", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Gornje", +DlgCellVerAlignMiddle : "SredniÅ¡nje", +DlgCellVerAlignBottom : "Donje", +DlgCellVerAlignBaseline : "Bazno", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Spajanje redova", +DlgCellCollSpan : "Spajanje kolona", +DlgCellBackColor : "Boja pozadine", +DlgCellBorderColor : "Boja okvira", +DlgCellBtnSelect : "Odaberi...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "PronaÄ‘i i zamijeni", + +// Find Dialog +DlgFindTitle : "PronaÄ‘i", +DlgFindFindBtn : "PronaÄ‘i", +DlgFindNotFoundMsg : "Traženi tekst nije pronaÄ‘en.", + +// Replace Dialog +DlgReplaceTitle : "Zamijeni", +DlgReplaceFindLbl : "PronaÄ‘i:", +DlgReplaceReplaceLbl : "Zamijeni s:", +DlgReplaceCaseChk : "Usporedi mala/velika slova", +DlgReplaceReplaceBtn : "Zamijeni", +DlgReplaceReplAllBtn : "Zamijeni sve", +DlgReplaceWordChk : "Usporedi cijele rijeÄi", + +// Paste Operations / Dialog +PasteErrorCut : "Sigurnosne postavke VaÅ¡eg pretraživaÄa ne dozvoljavaju operacije automatskog izrezivanja. Molimo koristite kraticu na tipkovnici (Ctrl+X).", +PasteErrorCopy : "Sigurnosne postavke VaÅ¡eg pretraživaÄa ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tipkovnici (Ctrl+C).", + +PasteAsText : "Zalijepi kao Äisti tekst", +PasteFromWord : "Zalijepi iz Worda", + +DlgPasteMsg2 : "Molimo zaljepite unutar doljnjeg okvira koristeći tipkovnicu (Ctrl+V) i kliknite OK.", +DlgPasteSec : "Zbog sigurnosnih postavki VaÅ¡eg pretraživaÄa, editor nema direktan pristup VaÅ¡em meÄ‘uspremniku. Potrebno je ponovno zalijepiti tekst u ovaj prozor.", +DlgPasteIgnoreFont : "Zanemari definiciju vrste fonta", +DlgPasteRemoveStyles : "Ukloni definicije stilova", + +// Color Picker +ColorAutomatic : "Automatski", +ColorMoreColors : "ViÅ¡e boja...", + +// Document Properties +DocProps : "Svojstva dokumenta", + +// Anchor Dialog +DlgAnchorTitle : "Svojstva sidra", +DlgAnchorName : "Ime sidra", +DlgAnchorErrorName : "Molimo unesite ime sidra", + +// Speller Pages Dialog +DlgSpellNotInDic : "Nije u rjeÄniku", +DlgSpellChangeTo : "Promijeni u", +DlgSpellBtnIgnore : "Zanemari", +DlgSpellBtnIgnoreAll : "Zanemari sve", +DlgSpellBtnReplace : "Zamijeni", +DlgSpellBtnReplaceAll : "Zamijeni sve", +DlgSpellBtnUndo : "Vrati", +DlgSpellNoSuggestions : "-Nema preporuke-", +DlgSpellProgress : "Provjera u tijeku...", +DlgSpellNoMispell : "Provjera zavrÅ¡ena: Nema greÅ¡aka", +DlgSpellNoChanges : "Provjera zavrÅ¡ena: Nije napravljena promjena", +DlgSpellOneChange : "Provjera zavrÅ¡ena: Jedna rijeÄ promjenjena", +DlgSpellManyChanges : "Provjera zavrÅ¡ena: Promijenjeno %1 rijeÄi", + +IeSpellDownload : "Provjera pravopisa nije instalirana. Želite li skinuti provjeru pravopisa?", + +// Button Dialog +DlgButtonText : "Tekst (vrijednost)", +DlgButtonType : "Vrsta", +DlgButtonTypeBtn : "Gumb", +DlgButtonTypeSbm : "PoÅ¡alji", +DlgButtonTypeRst : "PoniÅ¡ti", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Ime", +DlgCheckboxValue : "Vrijednost", +DlgCheckboxSelected : "Odabrano", + +// Form Dialog +DlgFormName : "Ime", +DlgFormAction : "Akcija", +DlgFormMethod : "Metoda", + +// Select Field Dialog +DlgSelectName : "Ime", +DlgSelectValue : "Vrijednost", +DlgSelectSize : "VeliÄina", +DlgSelectLines : "linija", +DlgSelectChkMulti : "Dozvoli viÅ¡estruki odabir", +DlgSelectOpAvail : "Dostupne opcije", +DlgSelectOpText : "Tekst", +DlgSelectOpValue : "Vrijednost", +DlgSelectBtnAdd : "Dodaj", +DlgSelectBtnModify : "Promijeni", +DlgSelectBtnUp : "Gore", +DlgSelectBtnDown : "Dolje", +DlgSelectBtnSetValue : "Postavi kao odabranu vrijednost", +DlgSelectBtnDelete : "ObriÅ¡i", + +// Textarea Dialog +DlgTextareaName : "Ime", +DlgTextareaCols : "Kolona", +DlgTextareaRows : "Redova", + +// Text Field Dialog +DlgTextName : "Ime", +DlgTextValue : "Vrijednost", +DlgTextCharWidth : "Å irina", +DlgTextMaxChars : "NajviÅ¡e karaktera", +DlgTextType : "Vrsta", +DlgTextTypeText : "Tekst", +DlgTextTypePass : "Å ifra", + +// Hidden Field Dialog +DlgHiddenName : "Ime", +DlgHiddenValue : "Vrijednost", + +// Bulleted List Dialog +BulletedListProp : "Svojstva liste", +NumberedListProp : "Svojstva brojÄane liste", +DlgLstStart : "PoÄetak", +DlgLstType : "Vrsta", +DlgLstTypeCircle : "Krug", +DlgLstTypeDisc : "Disk", +DlgLstTypeSquare : "Kvadrat", +DlgLstTypeNumbers : "Brojevi (1, 2, 3)", +DlgLstTypeLCase : "Mala slova (a, b, c)", +DlgLstTypeUCase : "Velika slova (A, B, C)", +DlgLstTypeSRoman : "Male rimske brojke (i, ii, iii)", +DlgLstTypeLRoman : "Velike rimske brojke (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Općenito", +DlgDocBackTab : "Pozadina", +DlgDocColorsTab : "Boje i margine", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Naslov stranice", +DlgDocLangDir : "Smjer jezika", +DlgDocLangDirLTR : "S lijeva na desno", +DlgDocLangDirRTL : "S desna na lijevo", +DlgDocLangCode : "Kôd jezika", +DlgDocCharSet : "Enkodiranje znakova", +DlgDocCharSetCE : "SrediÅ¡nja Europa", +DlgDocCharSetCT : "Tradicionalna kineska (Big5)", +DlgDocCharSetCR : "Ćirilica", +DlgDocCharSetGR : "GrÄka", +DlgDocCharSetJP : "Japanska", +DlgDocCharSetKR : "Koreanska", +DlgDocCharSetTR : "Turska", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Zapadna Europa", +DlgDocCharSetOther : "Ostalo enkodiranje znakova", + +DlgDocDocType : "Zaglavlje vrste dokumenta", +DlgDocDocTypeOther : "Ostalo zaglavlje vrste dokumenta", +DlgDocIncXHTML : "Ubaci XHTML deklaracije", +DlgDocBgColor : "Boja pozadine", +DlgDocBgImage : "URL slike pozadine", +DlgDocBgNoScroll : "Pozadine se ne pomiÄe", +DlgDocCText : "Tekst", +DlgDocCLink : "Link", +DlgDocCVisited : "Posjećeni link", +DlgDocCActive : "Aktivni link", +DlgDocMargins : "Margine stranice", +DlgDocMaTop : "Vrh", +DlgDocMaLeft : "Lijevo", +DlgDocMaRight : "Desno", +DlgDocMaBottom : "Dolje", +DlgDocMeIndex : "KljuÄne rijeÄi dokumenta (odvojene zarezom)", +DlgDocMeDescr : "Opis dokumenta", +DlgDocMeAuthor : "Autor", +DlgDocMeCopy : "Autorska prava", +DlgDocPreview : "Pregledaj", + +// Templates Dialog +Templates : "PredloÅ¡ci", +DlgTemplatesTitle : "PredloÅ¡ci sadržaja", +DlgTemplatesSelMsg : "Molimo odaberite predložak koji želite otvoriti
    (stvarni sadržaj će biti izgubljen):", +DlgTemplatesLoading : "UÄitavam listu predložaka. Molimo priÄekajte...", +DlgTemplatesNoTpl : "(Nema definiranih predložaka)", +DlgTemplatesReplace : "Zamijeni trenutne sadržaje", + +// About Dialog +DlgAboutAboutTab : "O FCKEditoru", +DlgAboutBrowserInfoTab : "Podaci o pretraživaÄu", +DlgAboutLicenseTab : "Licenca", +DlgAboutVersion : "inaÄica", +DlgAboutInfo : "Za viÅ¡e informacija posjetite", + +// Div Dialog +DlgDivGeneralTab : "Općenito", +DlgDivAdvancedTab : "Napredno", +DlgDivStyle : "Stil", +DlgDivInlineStyle : "Stil u redu", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/hu.js b/www/js/FCKeditor/editor/lang/hu.js new file mode 100644 index 0000000..2de0900 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/hu.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Hungarian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Eszköztár elrejtése", +ToolbarExpand : "Eszköztár megjelenítése", + +// Toolbar Items and Context Menu +Save : "Mentés", +NewPage : "Új oldal", +Preview : "ElÅ‘nézet", +Cut : "Kivágás", +Copy : "Másolás", +Paste : "Beillesztés", +PasteText : "Beillesztés formázás nélkül", +PasteWord : "Beillesztés Word-bÅ‘l", +Print : "Nyomtatás", +SelectAll : "Mindent kijelöl", +RemoveFormat : "Formázás eltávolítása", +InsertLinkLbl : "Hivatkozás", +InsertLink : "Hivatkozás beillesztése/módosítása", +RemoveLink : "Hivatkozás törlése", +VisitLink : "Open Link", //MISSING +Anchor : "Horgony beillesztése/szerkesztése", +AnchorDelete : "Horgony eltávolítása", +InsertImageLbl : "Kép", +InsertImage : "Kép beillesztése/módosítása", +InsertFlashLbl : "Flash", +InsertFlash : "Flash beillesztése, módosítása", +InsertTableLbl : "Táblázat", +InsertTable : "Táblázat beillesztése/módosítása", +InsertLineLbl : "Vonal", +InsertLine : "Elválasztóvonal beillesztése", +InsertSpecialCharLbl: "Speciális karakter", +InsertSpecialChar : "Speciális karakter beillesztése", +InsertSmileyLbl : "Hangulatjelek", +InsertSmiley : "Hangulatjelek beillesztése", +About : "FCKeditor névjegy", +Bold : "Félkövér", +Italic : "DÅ‘lt", +Underline : "Aláhúzott", +StrikeThrough : "Ãthúzott", +Subscript : "Alsó index", +Superscript : "FelsÅ‘ index", +LeftJustify : "Balra", +CenterJustify : "Középre", +RightJustify : "Jobbra", +BlockJustify : "Sorkizárt", +DecreaseIndent : "Behúzás csökkentése", +IncreaseIndent : "Behúzás növelése", +Blockquote : "Idézet blokk", +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Visszavonás", +Redo : "Ismétlés", +NumberedListLbl : "Számozás", +NumberedList : "Számozás beillesztése/törlése", +BulletedListLbl : "Felsorolás", +BulletedList : "Felsorolás beillesztése/törlése", +ShowTableBorders : "Táblázat szegély mutatása", +ShowDetails : "Részletek mutatása", +Style : "Stílus", +FontFormat : "Formátum", +Font : "Betűtípus", +FontSize : "Méret", +TextColor : "Betűszín", +BGColor : "Háttérszín", +Source : "Forráskód", +Find : "Keresés", +Replace : "Csere", +SpellCheck : "Helyesírás-ellenÅ‘rzés", +UniversalKeyboard : "Univerzális billentyűzet", +PageBreakLbl : "Oldaltörés", +PageBreak : "Oldaltörés beillesztése", + +Form : "Å°rlap", +Checkbox : "JelölÅ‘négyzet", +RadioButton : "Választógomb", +TextField : "SzövegmezÅ‘", +Textarea : "Szövegterület", +HiddenField : "RejtettmezÅ‘", +Button : "Gomb", +SelectionField : "LegördülÅ‘ lista", +ImageButton : "Képgomb", + +FitWindow : "Maximalizálás", +ShowBlocks : "Blokkok megjelenítése", + +// Context Menu +EditLink : "Hivatkozás módosítása", +CellCM : "Cella", +RowCM : "Sor", +ColumnCM : "Oszlop", +InsertRowAfter : "Sor beillesztése az aktuális sor mögé", +InsertRowBefore : "Sor beillesztése az aktuális sor elé", +DeleteRows : "Sorok törlése", +InsertColumnAfter : "Oszlop beillesztése az aktuális oszlop mögé", +InsertColumnBefore : "Oszlop beillesztése az aktuális oszlop elé", +DeleteColumns : "Oszlopok törlése", +InsertCellAfter : "Cella beillesztése az aktuális cella mögé", +InsertCellBefore : "Cella beillesztése az aktuális cella elé", +DeleteCells : "Cellák törlése", +MergeCells : "Cellák egyesítése", +MergeRight : "Cellák egyesítése jobbra", +MergeDown : "Cellák egyesítése lefelé", +HorizontalSplitCell : "Cellák szétválasztása vízszintesen", +VerticalSplitCell : "Cellák szétválasztása függÅ‘legesen", +TableDelete : "Táblázat törlése", +CellProperties : "Cella tulajdonságai", +TableProperties : "Táblázat tulajdonságai", +ImageProperties : "Kép tulajdonságai", +FlashProperties : "Flash tulajdonságai", + +AnchorProp : "Horgony tulajdonságai", +ButtonProp : "Gomb tulajdonságai", +CheckboxProp : "JelölÅ‘négyzet tulajdonságai", +HiddenFieldProp : "Rejtett mezÅ‘ tulajdonságai", +RadioButtonProp : "Választógomb tulajdonságai", +ImageButtonProp : "Képgomb tulajdonságai", +TextFieldProp : "SzövegmezÅ‘ tulajdonságai", +SelectionFieldProp : "LegördülÅ‘ lista tulajdonságai", +TextareaProp : "Szövegterület tulajdonságai", +FormProp : "Å°rlap tulajdonságai", + +FontFormats : "Normál;Formázott;Címsor;Fejléc 1;Fejléc 2;Fejléc 3;Fejléc 4;Fejléc 5;Fejléc 6;Bekezdés (DIV)", + +// Alerts and Messages +ProcessingXHTML : "XHTML feldolgozása. Kérem várjon...", +Done : "Kész", +PasteWordConfirm : "A beilleszteni kívánt szöveg Word-bÅ‘l van másolva. El kívánja távolítani a formázást a beillesztés elÅ‘tt?", +NotCompatiblePaste : "Ez a parancs csak Internet Explorer 5.5 verziótól használható. Megpróbálja beilleszteni a szöveget az eredeti formázással?", +UnknownToolbarItem : "Ismeretlen eszköztár elem \"%1\"", +UnknownCommand : "Ismeretlen parancs \"%1\"", +NotImplemented : "A parancs nem hajtható végre", +UnknownToolbarSet : "Az eszközkészlet \"%1\" nem létezik", +NoActiveX : "A böngészÅ‘ biztonsági beállításai korlátozzák a szerkesztÅ‘ lehetÅ‘ségeit. Engedélyezni kell ezt az opciót: \"Run ActiveX controls and plug-ins\". EttÅ‘l függetlenül elÅ‘fordulhatnak hibaüzenetek ill. bizonyos funkciók hiányozhatnak.", +BrowseServerBlocked : "Nem lehet megnyitni a fájlböngészÅ‘t. Bizonyosodjon meg róla, hogy a felbukkanó ablakok engedélyezve vannak.", +DialogBlocked : "Nem lehet megnyitni a párbeszédablakot. Bizonyosodjon meg róla, hogy a felbukkanó ablakok engedélyezve vannak.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "Rendben", +DlgBtnCancel : "Mégsem", +DlgBtnClose : "Bezárás", +DlgBtnBrowseServer : "Böngészés a szerveren", +DlgAdvancedTag : "További opciók", +DlgOpOther : "Egyéb", +DlgInfoTab : "Alaptulajdonságok", +DlgAlertUrl : "Illessze be a webcímet", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Azonosító", +DlgGenLangDir : "Ãrás iránya", +DlgGenLangDirLtr : "Balról jobbra", +DlgGenLangDirRtl : "Jobbról balra", +DlgGenLangCode : "Nyelv kódja", +DlgGenAccessKey : "Billentyűkombináció", +DlgGenName : "Név", +DlgGenTabIndex : "Tabulátor index", +DlgGenLongDescr : "Részletes leírás webcíme", +DlgGenClass : "Stíluskészlet", +DlgGenTitle : "Súgócimke", +DlgGenContType : "Súgó tartalomtípusa", +DlgGenLinkCharset : "Hivatkozott tartalom kódlapja", +DlgGenStyle : "Stílus", + +// Image Dialog +DlgImgTitle : "Kép tulajdonságai", +DlgImgInfoTab : "Alaptulajdonságok", +DlgImgBtnUpload : "Küldés a szerverre", +DlgImgURL : "Hivatkozás", +DlgImgUpload : "Feltöltés", +DlgImgAlt : "Buborék szöveg", +DlgImgWidth : "Szélesség", +DlgImgHeight : "Magasság", +DlgImgLockRatio : "Arány megtartása", +DlgBtnResetSize : "Eredeti méret", +DlgImgBorder : "Keret", +DlgImgHSpace : "Vízsz. táv", +DlgImgVSpace : "Függ. táv", +DlgImgAlign : "Igazítás", +DlgImgAlignLeft : "Bal", +DlgImgAlignAbsBottom: "Legaljára", +DlgImgAlignAbsMiddle: "Közepére", +DlgImgAlignBaseline : "Alapvonalhoz", +DlgImgAlignBottom : "Aljára", +DlgImgAlignMiddle : "Középre", +DlgImgAlignRight : "Jobbra", +DlgImgAlignTextTop : "Szöveg tetejére", +DlgImgAlignTop : "Tetejére", +DlgImgPreview : "ElÅ‘nézet", +DlgImgAlertUrl : "Töltse ki a kép webcímét", +DlgImgLinkTab : "Hivatkozás", + +// Flash Dialog +DlgFlashTitle : "Flash tulajdonságai", +DlgFlashChkPlay : "Automata lejátszás", +DlgFlashChkLoop : "Folyamatosan", +DlgFlashChkMenu : "Flash menü engedélyezése", +DlgFlashScale : "Méretezés", +DlgFlashScaleAll : "Mindent mutat", +DlgFlashScaleNoBorder : "Keret nélkül", +DlgFlashScaleFit : "Teljes kitöltés", + +// Link Dialog +DlgLnkWindowTitle : "Hivatkozás tulajdonságai", +DlgLnkInfoTab : "Alaptulajdonságok", +DlgLnkTargetTab : "Megjelenítés", + +DlgLnkType : "Hivatkozás típusa", +DlgLnkTypeURL : "Webcím", +DlgLnkTypeAnchor : "Horgony az oldalon", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protokoll", +DlgLnkProtoOther : "", +DlgLnkURL : "Webcím", +DlgLnkAnchorSel : "Horgony választása", +DlgLnkAnchorByName : "Horgony név szerint", +DlgLnkAnchorById : "Azonosító szerint", +DlgLnkNoAnchors : "(Nincs horgony a dokumentumban)", +DlgLnkEMail : "E-Mail cím", +DlgLnkEMailSubject : "Ãœzenet tárgya", +DlgLnkEMailBody : "Ãœzenet", +DlgLnkUpload : "Feltöltés", +DlgLnkBtnUpload : "Küldés a szerverre", + +DlgLnkTarget : "Tartalom megjelenítése", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Új ablakban (_blank)", +DlgLnkTargetParent : "SzülÅ‘ ablakban (_parent)", +DlgLnkTargetSelf : "Azonos ablakban (_self)", +DlgLnkTargetTop : "LegfelsÅ‘ ablakban (_top)", +DlgLnkTargetFrameName : "Keret neve", +DlgLnkPopWinName : "Felugró ablak neve", +DlgLnkPopWinFeat : "Felugró ablak jellemzÅ‘i", +DlgLnkPopResize : "MéretezhetÅ‘", +DlgLnkPopLocation : "Címsor", +DlgLnkPopMenu : "Menü sor", +DlgLnkPopScroll : "GördítÅ‘sáv", +DlgLnkPopStatus : "Ãllapotsor", +DlgLnkPopToolbar : "Eszköztár", +DlgLnkPopFullScrn : "Teljes képernyÅ‘ (csak IE)", +DlgLnkPopDependent : "SzülÅ‘höz kapcsolt (csak Netscape)", +DlgLnkPopWidth : "Szélesség", +DlgLnkPopHeight : "Magasság", +DlgLnkPopLeft : "Bal pozíció", +DlgLnkPopTop : "FelsÅ‘ pozíció", + +DlnLnkMsgNoUrl : "Adja meg a hivatkozás webcímét", +DlnLnkMsgNoEMail : "Adja meg az E-Mail címet", +DlnLnkMsgNoAnchor : "Válasszon egy horgonyt", +DlnLnkMsgInvPopName : "A felbukkanó ablak neve alfanumerikus karakterrel kezdôdjön, valamint ne tartalmazzon szóközt", + +// Color Dialog +DlgColorTitle : "Színválasztás", +DlgColorBtnClear : "Törlés", +DlgColorHighlight : "ElÅ‘nézet", +DlgColorSelected : "Kiválasztott", + +// Smiley Dialog +DlgSmileyTitle : "Hangulatjel beszúrása", + +// Special Character Dialog +DlgSpecialCharTitle : "Speciális karakter választása", + +// Table Dialog +DlgTableTitle : "Táblázat tulajdonságai", +DlgTableRows : "Sorok", +DlgTableColumns : "Oszlopok", +DlgTableBorder : "Szegélyméret", +DlgTableAlign : "Igazítás", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Balra", +DlgTableAlignCenter : "Középre", +DlgTableAlignRight : "Jobbra", +DlgTableWidth : "Szélesség", +DlgTableWidthPx : "képpont", +DlgTableWidthPc : "százalék", +DlgTableHeight : "Magasság", +DlgTableCellSpace : "Cella térköz", +DlgTableCellPad : "Cella belsÅ‘ margó", +DlgTableCaption : "Felirat", +DlgTableSummary : "Leírás", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Cella tulajdonságai", +DlgCellWidth : "Szélesség", +DlgCellWidthPx : "képpont", +DlgCellWidthPc : "százalék", +DlgCellHeight : "Magasság", +DlgCellWordWrap : "Sortörés", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Igen", +DlgCellWordWrapNo : "Nem", +DlgCellHorAlign : "Vízsz. igazítás", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Balra", +DlgCellHorAlignCenter : "Középre", +DlgCellHorAlignRight: "Jobbra", +DlgCellVerAlign : "Függ. igazítás", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Tetejére", +DlgCellVerAlignMiddle : "Középre", +DlgCellVerAlignBottom : "Aljára", +DlgCellVerAlignBaseline : "Egyvonalba", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Sorok egyesítése", +DlgCellCollSpan : "Oszlopok egyesítése", +DlgCellBackColor : "Háttérszín", +DlgCellBorderColor : "Szegélyszín", +DlgCellBtnSelect : "Kiválasztás...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Keresés és csere", + +// Find Dialog +DlgFindTitle : "Keresés", +DlgFindFindBtn : "Keresés", +DlgFindNotFoundMsg : "A keresett szöveg nem található.", + +// Replace Dialog +DlgReplaceTitle : "Csere", +DlgReplaceFindLbl : "Keresett szöveg:", +DlgReplaceReplaceLbl : "Csere erre:", +DlgReplaceCaseChk : "kis- és nagybetű megkülönböztetése", +DlgReplaceReplaceBtn : "Csere", +DlgReplaceReplAllBtn : "Az összes cseréje", +DlgReplaceWordChk : "csak ha ez a teljes szó", + +// Paste Operations / Dialog +PasteErrorCut : "A böngészÅ‘ biztonsági beállításai nem engedélyezik a szerkesztÅ‘nek, hogy végrehajtsa a kivágás műveletet. Használja az alábbi billentyűkombinációt (Ctrl+X).", +PasteErrorCopy : "A böngészÅ‘ biztonsági beállításai nem engedélyezik a szerkesztÅ‘nek, hogy végrehajtsa a másolás műveletet. Használja az alábbi billentyűkombinációt (Ctrl+X).", + +PasteAsText : "Beillesztés formázatlan szövegként", +PasteFromWord : "Beillesztés Word-bÅ‘l", + +DlgPasteMsg2 : "Másolja be az alábbi mezÅ‘be a Ctrl+V billentyűk lenyomásával, majd nyomjon Rendben-t.", +DlgPasteSec : "A böngészÅ‘ biztonsági beállításai miatt a szerkesztÅ‘ nem képes hozzáférni a vágólap adataihoz. Illeszd be újra ebben az ablakban.", +DlgPasteIgnoreFont : "Betű formázások megszüntetése", +DlgPasteRemoveStyles : "Stílusok eltávolítása", + +// Color Picker +ColorAutomatic : "Automatikus", +ColorMoreColors : "További színek...", + +// Document Properties +DocProps : "Dokumentum tulajdonságai", + +// Anchor Dialog +DlgAnchorTitle : "Horgony tulajdonságai", +DlgAnchorName : "Horgony neve", +DlgAnchorErrorName : "Kérem adja meg a horgony nevét", + +// Speller Pages Dialog +DlgSpellNotInDic : "Nincs a szótárban", +DlgSpellChangeTo : "Módosítás", +DlgSpellBtnIgnore : "Kihagyja", +DlgSpellBtnIgnoreAll : "Mindet kihagyja", +DlgSpellBtnReplace : "Csere", +DlgSpellBtnReplaceAll : "Összes cseréje", +DlgSpellBtnUndo : "Visszavonás", +DlgSpellNoSuggestions : "Nincs javaslat", +DlgSpellProgress : "Helyesírás-ellenÅ‘rzés folyamatban...", +DlgSpellNoMispell : "Helyesírás-ellenÅ‘rzés kész: Nem találtam hibát", +DlgSpellNoChanges : "Helyesírás-ellenÅ‘rzés kész: Nincs változtatott szó", +DlgSpellOneChange : "Helyesírás-ellenÅ‘rzés kész: Egy szó cserélve", +DlgSpellManyChanges : "Helyesírás-ellenÅ‘rzés kész: %1 szó cserélve", + +IeSpellDownload : "A helyesírás-ellenÅ‘rzÅ‘ nincs telepítve. Szeretné letölteni most?", + +// Button Dialog +DlgButtonText : "Szöveg (Érték)", +DlgButtonType : "Típus", +DlgButtonTypeBtn : "Gomb", +DlgButtonTypeSbm : "Küldés", +DlgButtonTypeRst : "Alaphelyzet", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Név", +DlgCheckboxValue : "Érték", +DlgCheckboxSelected : "Kiválasztott", + +// Form Dialog +DlgFormName : "Név", +DlgFormAction : "Adatfeldolgozást végzÅ‘ hivatkozás", +DlgFormMethod : "Adatküldés módja", + +// Select Field Dialog +DlgSelectName : "Név", +DlgSelectValue : "Érték", +DlgSelectSize : "Méret", +DlgSelectLines : "sor", +DlgSelectChkMulti : "több sor is kiválasztható", +DlgSelectOpAvail : "ElérhetÅ‘ opciók", +DlgSelectOpText : "Szöveg", +DlgSelectOpValue : "Érték", +DlgSelectBtnAdd : "Hozzáad", +DlgSelectBtnModify : "Módosít", +DlgSelectBtnUp : "Fel", +DlgSelectBtnDown : "Le", +DlgSelectBtnSetValue : "Legyen az alapértelmezett érték", +DlgSelectBtnDelete : "Töröl", + +// Textarea Dialog +DlgTextareaName : "Név", +DlgTextareaCols : "Karakterek száma egy sorban", +DlgTextareaRows : "Sorok száma", + +// Text Field Dialog +DlgTextName : "Név", +DlgTextValue : "Érték", +DlgTextCharWidth : "Megjelenített karakterek száma", +DlgTextMaxChars : "Maximális karakterszám", +DlgTextType : "Típus", +DlgTextTypeText : "Szöveg", +DlgTextTypePass : "Jelszó", + +// Hidden Field Dialog +DlgHiddenName : "Név", +DlgHiddenValue : "Érték", + +// Bulleted List Dialog +BulletedListProp : "Felsorolás tulajdonságai", +NumberedListProp : "Számozás tulajdonságai", +DlgLstStart : "Start", +DlgLstType : "Formátum", +DlgLstTypeCircle : "Kör", +DlgLstTypeDisc : "Lemez", +DlgLstTypeSquare : "Négyzet", +DlgLstTypeNumbers : "Számok (1, 2, 3)", +DlgLstTypeLCase : "Kisbetűk (a, b, c)", +DlgLstTypeUCase : "Nagybetűk (A, B, C)", +DlgLstTypeSRoman : "Kis római számok (i, ii, iii)", +DlgLstTypeLRoman : "Nagy római számok (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Ãltalános", +DlgDocBackTab : "Háttér", +DlgDocColorsTab : "Színek és margók", +DlgDocMetaTab : "Meta adatok", + +DlgDocPageTitle : "Oldalcím", +DlgDocLangDir : "Ãrás iránya", +DlgDocLangDirLTR : "Balról jobbra", +DlgDocLangDirRTL : "Jobbról balra", +DlgDocLangCode : "Nyelv kód", +DlgDocCharSet : "Karakterkódolás", +DlgDocCharSetCE : "Közép-Európai", +DlgDocCharSetCT : "Kínai Tradicionális (Big5)", +DlgDocCharSetCR : "Cyrill", +DlgDocCharSetGR : "Görög", +DlgDocCharSetJP : "Japán", +DlgDocCharSetKR : "Koreai", +DlgDocCharSetTR : "Török", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Nyugat-Európai", +DlgDocCharSetOther : "Más karakterkódolás", + +DlgDocDocType : "Dokumentum típus fejléc", +DlgDocDocTypeOther : "Más dokumentum típus fejléc", +DlgDocIncXHTML : "XHTML deklarációk beillesztése", +DlgDocBgColor : "Háttérszín", +DlgDocBgImage : "Háttérkép cím", +DlgDocBgNoScroll : "Nem gördíthetÅ‘ háttér", +DlgDocCText : "Szöveg", +DlgDocCLink : "Cím", +DlgDocCVisited : "Látogatott cím", +DlgDocCActive : "Aktív cím", +DlgDocMargins : "Oldal margók", +DlgDocMaTop : "FelsÅ‘", +DlgDocMaLeft : "Bal", +DlgDocMaRight : "Jobb", +DlgDocMaBottom : "Alsó", +DlgDocMeIndex : "Dokumentum keresÅ‘szavak (vesszÅ‘vel elválasztva)", +DlgDocMeDescr : "Dokumentum leírás", +DlgDocMeAuthor : "SzerzÅ‘", +DlgDocMeCopy : "SzerzÅ‘i jog", +DlgDocPreview : "ElÅ‘nézet", + +// Templates Dialog +Templates : "Sablonok", +DlgTemplatesTitle : "ElérhetÅ‘ sablonok", +DlgTemplatesSelMsg : "Válassza ki melyik sablon nyíljon meg a szerkesztÅ‘ben
    (a jelenlegi tartalom elveszik):", +DlgTemplatesLoading : "Sablon lista betöltése. Kis türelmet...", +DlgTemplatesNoTpl : "(Nincs sablon megadva)", +DlgTemplatesReplace : "Kicseréli a jelenlegi tartalmat", + +// About Dialog +DlgAboutAboutTab : "Névjegy", +DlgAboutBrowserInfoTab : "Böngésző információ", +DlgAboutLicenseTab : "Licensz", +DlgAboutVersion : "verzió", +DlgAboutInfo : "További információkért látogasson el ide:", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/is.js b/www/js/FCKeditor/editor/lang/is.js new file mode 100755 index 0000000..b639840 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/is.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Icelandic language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Fela verkstiku", +ToolbarExpand : "Sýna verkstiku", + +// Toolbar Items and Context Menu +Save : "Vista", +NewPage : "Ný síða", +Preview : "Forskoða", +Cut : "Klippa", +Copy : "Afrita", +Paste : "Líma", +PasteText : "Líma ósniðinn texta", +PasteWord : "Líma úr Word", +Print : "Prenta", +SelectAll : "Velja allt", +RemoveFormat : "Fjarlægja snið", +InsertLinkLbl : "Stikla", +InsertLink : "Stofna/breyta stiklu", +RemoveLink : "Fjarlægja stiklu", +VisitLink : "Opna stiklusíðu", +Anchor : "Stofna/breyta kaflamerki", +AnchorDelete : "Eyða kaflamerki", +InsertImageLbl : "Setja inn mynd", +InsertImage : "Setja inn/breyta mynd", +InsertFlashLbl : "Flash", +InsertFlash : "Setja inn/breyta Flash", +InsertTableLbl : "Tafla", +InsertTable : "Setja inn/breyta töflu", +InsertLineLbl : "Lína", +InsertLine : "Lóðrétt lína", +InsertSpecialCharLbl: "Merki", +InsertSpecialChar : "Setja inn merki", +InsertSmileyLbl : "Svipur", +InsertSmiley : "Setja upp svip", +About : "Um FCKeditor", +Bold : "Feitletrað", +Italic : "Skáletrað", +Underline : "Undirstrikað", +StrikeThrough : "Yfirstrikað", +Subscript : "Niðurskrifað", +Superscript : "Uppskrifað", +LeftJustify : "Vinstrijöfnun", +CenterJustify : "Miðja texta", +RightJustify : "Hægrijöfnun", +BlockJustify : "Jafna báðum megin", +DecreaseIndent : "Auka inndrátt", +IncreaseIndent : "Minnka inndrátt", +Blockquote : "Inndráttur", +CreateDiv : "Búa til DIV-hýsil", +EditDiv : "Breyta DIV-hýsli", +DeleteDiv : "Eyða DIV-hýsli", +Undo : "Afturkalla", +Redo : "Hætta við afturköllun", +NumberedListLbl : "Númeraður listi", +NumberedList : "Setja inn/fella númeraðan lista", +BulletedListLbl : "Punktalisti", +BulletedList : "Setja inn/fella punktalista", +ShowTableBorders : "Sýna töflugrind", +ShowDetails : "Sýna smáatriði", +Style : "Stílflokkur", +FontFormat : "Stílsnið", +Font : "Leturgerð ", +FontSize : "Leturstærð ", +TextColor : "Litur texta", +BGColor : "Bakgrunnslitur", +Source : "Kóði", +Find : "Leita", +Replace : "Skipta út", +SpellCheck : "Villuleit", +UniversalKeyboard : "Hnattrænt lyklaborð", +PageBreakLbl : "Síðuskil", +PageBreak : "Setja inn síðuskil", + +Form : "Setja inn innsláttarform", +Checkbox : "Setja inn hökunarreit", +RadioButton : "Setja inn valhnapp", +TextField : "Setja inn textareit", +Textarea : "Setja inn textasvæði", +HiddenField : "Setja inn falið svæði", +Button : "Setja inn hnapp", +SelectionField : "Setja inn lista", +ImageButton : "Setja inn myndahnapp", + +FitWindow : "Skoða ritil í fullri stærð", +ShowBlocks : "Sýna blokkir", + +// Context Menu +EditLink : "Breyta stiklu", +CellCM : "Reitur", +RowCM : "Röð", +ColumnCM : "Dálkur", +InsertRowAfter : "Skjóta inn röð fyrir neðan", +InsertRowBefore : "Skjóta inn röð fyrir ofan", +DeleteRows : "Eyða röð", +InsertColumnAfter : "Skjóta inn dálki hægra megin", +InsertColumnBefore : "Skjóta inn dálki vinstra megin", +DeleteColumns : "Fella dálk", +InsertCellAfter : "Skjóta inn reiti fyrir framan", +InsertCellBefore : "Skjóta inn reiti fyrir aftan", +DeleteCells : "Fella reit", +MergeCells : "Sameina reiti", +MergeRight : "Sameina til hægri", +MergeDown : "Sameina niður á við", +HorizontalSplitCell : "Kljúfa reit lárétt", +VerticalSplitCell : "Kljúfa reit lóðrétt", +TableDelete : "Fella töflu", +CellProperties : "Eigindi reits", +TableProperties : "Eigindi töflu", +ImageProperties : "Eigindi myndar", +FlashProperties : "Eigindi Flash", + +AnchorProp : "Eigindi kaflamerkis", +ButtonProp : "Eigindi hnapps", +CheckboxProp : "Eigindi markreits", +HiddenFieldProp : "Eigindi falins svæðis", +RadioButtonProp : "Eigindi valhnapps", +ImageButtonProp : "Eigindi myndahnapps", +TextFieldProp : "Eigindi textareits", +SelectionFieldProp : "Eigindi lista", +TextareaProp : "Eigindi textasvæðis", +FormProp : "Eigindi innsláttarforms", + +FontFormats : "Venjulegt letur;Forsniðið;Vistfang;Fyrirsögn 1;Fyrirsögn 2;Fyrirsögn 3;Fyrirsögn 4;Fyrirsögn 5;Fyrirsögn 6;Venjulegt (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Meðhöndla XHTML...", +Done : "Tilbúið", +PasteWordConfirm : "Textinn sem þú ætlar að líma virðist koma úr Word. Viltu hreinsa óþarfar Word-skipanir úr honum?", +NotCompatiblePaste : "Þessi aðgerð er bundin við Internet Explorer 5.5 og nýrri. Viltu líma textann án þess að hreinsa hann?", +UnknownToolbarItem : "Óþekktur hlutur í verkstiku \"%1\"!", +UnknownCommand : "Óþekkt skipanaheiti \"%1\"!", +NotImplemented : "Skipun ekki virkjuð!", +UnknownToolbarSet : "Verkstikan \"%1\" ekki til!", +NoActiveX : "Öryggisstillingarnar í vafranum þínum leyfa ekki alla möguleika ritilsins.
    Láttu vafrann leyfa Active-X og viðbætur til að komast hjá villum og takmörkunum.", +BrowseServerBlocked : "Ritillinn getur ekki opnað nauðsynlega hjálparglugga!
    Láttu hann leyfa þessari síðu að opna sprettiglugga.", +DialogBlocked : "Ekki var hægt að opna skipanaglugga!
    Nauðsynlegt er að leyfa síðunni að opna sprettiglugga.", +VisitLinkBlocked : "Ekki var hægt að opna nýjan glugga. Gangtu úr skugga um að engir sprettigluggabanar séu virkir.", + +// Dialogs +DlgBtnOK : "à lagi", +DlgBtnCancel : "Hætta við", +DlgBtnClose : "Loka", +DlgBtnBrowseServer : "Fletta í skjalasafni", +DlgAdvancedTag : "Tæknilegt", +DlgOpOther : "", +DlgInfoTab : "Upplýsingar", +DlgAlertUrl : "Sláðu inn slóð", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Auðkenni", +DlgGenLangDir : "Lesstefna", +DlgGenLangDirLtr : "Frá vinstri til hægri (LTR)", +DlgGenLangDirRtl : "Frá hægri til vinstri (RTL)", +DlgGenLangCode : "Tungumálakóði", +DlgGenAccessKey : "Skammvalshnappur", +DlgGenName : "Nafn", +DlgGenTabIndex : "Raðnúmer innsláttarreits", +DlgGenLongDescr : "Nánari lýsing", +DlgGenClass : "Stílsniðsflokkur", +DlgGenTitle : "Titill", +DlgGenContType : "Tegund innihalds", +DlgGenLinkCharset : "Táknróf", +DlgGenStyle : "Stíll", + +// Image Dialog +DlgImgTitle : "Eigindi myndar", +DlgImgInfoTab : "Almennt", +DlgImgBtnUpload : "Hlaða upp", +DlgImgURL : "Vefslóð", +DlgImgUpload : "Hlaða upp", +DlgImgAlt : "Baklægur texti", +DlgImgWidth : "Breidd", +DlgImgHeight : "Hæð", +DlgImgLockRatio : "Festa stærðarhlutfall", +DlgBtnResetSize : "Reikna stærð", +DlgImgBorder : "Rammi", +DlgImgHSpace : "Vinstri bil", +DlgImgVSpace : "Hægri bil", +DlgImgAlign : "Jöfnun", +DlgImgAlignLeft : "Vinstri", +DlgImgAlignAbsBottom: "Abs neðst", +DlgImgAlignAbsMiddle: "Abs miðjuð", +DlgImgAlignBaseline : "Grunnlína", +DlgImgAlignBottom : "Neðst", +DlgImgAlignMiddle : "Miðjuð", +DlgImgAlignRight : "Hægri", +DlgImgAlignTextTop : "Efri brún texta", +DlgImgAlignTop : "Efst", +DlgImgPreview : "Sýna dæmi", +DlgImgAlertUrl : "Sláðu inn slóðina að myndinni", +DlgImgLinkTab : "Stikla", + +// Flash Dialog +DlgFlashTitle : "Eigindi Flash", +DlgFlashChkPlay : "Sjálfvirk spilun", +DlgFlashChkLoop : "Endurtekning", +DlgFlashChkMenu : "Sýna Flash-valmynd", +DlgFlashScale : "Skali", +DlgFlashScaleAll : "Sýna allt", +DlgFlashScaleNoBorder : "Ãn ramma", +DlgFlashScaleFit : "Fella skala að stærð", + +// Link Dialog +DlgLnkWindowTitle : "Stikla", +DlgLnkInfoTab : "Almennt", +DlgLnkTargetTab : "Mark", + +DlgLnkType : "Stikluflokkur", +DlgLnkTypeURL : "Vefslóð", +DlgLnkTypeAnchor : "Bókamerki á þessari síðu", +DlgLnkTypeEMail : "Netfang", +DlgLnkProto : "Samskiptastaðall", +DlgLnkProtoOther : "", +DlgLnkURL : "Vefslóð", +DlgLnkAnchorSel : "Veldu akkeri", +DlgLnkAnchorByName : "Eftir akkerisnafni", +DlgLnkAnchorById : "Eftir auðkenni einingar", +DlgLnkNoAnchors : "", +DlgLnkEMail : "Netfang", +DlgLnkEMailSubject : "Efni", +DlgLnkEMailBody : "Meginmál", +DlgLnkUpload : "Senda upp", +DlgLnkBtnUpload : "Senda upp", + +DlgLnkTarget : "Mark", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nýr gluggi (_blank)", +DlgLnkTargetParent : "Yfirsettur rammi (_parent)", +DlgLnkTargetSelf : "Sami gluggi (_self)", +DlgLnkTargetTop : "Allur glugginn (_top)", +DlgLnkTargetFrameName : "Nafn markglugga", +DlgLnkPopWinName : "Nafn sprettiglugga", +DlgLnkPopWinFeat : "Eigindi sprettiglugga", +DlgLnkPopResize : "Skölun", +DlgLnkPopLocation : "Fanglína", +DlgLnkPopMenu : "Vallína", +DlgLnkPopScroll : "Skrunstikur", +DlgLnkPopStatus : "Stöðustika", +DlgLnkPopToolbar : "Verkfærastika", +DlgLnkPopFullScrn : "Heilskjár (IE)", +DlgLnkPopDependent : "Háð venslum (Netscape)", +DlgLnkPopWidth : "Breidd", +DlgLnkPopHeight : "Hæð", +DlgLnkPopLeft : "Fjarlægð frá vinstri", +DlgLnkPopTop : "Fjarlægð frá efri brún", + +DlnLnkMsgNoUrl : "Sláðu inn veffang stiklunnar!", +DlnLnkMsgNoEMail : "Sláðu inn netfang!", +DlnLnkMsgNoAnchor : "Veldu fyrst eitthvert bókamerki!", +DlnLnkMsgInvPopName : "Sprettisíðan verður að byrja á bókstaf (a-z) og má ekki innihalda stafabil", + +// Color Dialog +DlgColorTitle : "Velja lit", +DlgColorBtnClear : "Núllstilla", +DlgColorHighlight : "Litmerkja", +DlgColorSelected : "Valið", + +// Smiley Dialog +DlgSmileyTitle : "Velja svip", + +// Special Character Dialog +DlgSpecialCharTitle : "Velja tákn", + +// Table Dialog +DlgTableTitle : "Eigindi töflu", +DlgTableRows : "Raðir", +DlgTableColumns : "Dálkar", +DlgTableBorder : "Breidd ramma", +DlgTableAlign : "Jöfnun", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Vinstrijafnað", +DlgTableAlignCenter : "Miðjað", +DlgTableAlignRight : "Hægrijafnað", +DlgTableWidth : "Breidd", +DlgTableWidthPx : "myndeindir", +DlgTableWidthPc : "prósent", +DlgTableHeight : "Hæð", +DlgTableCellSpace : "Bil milli reita", +DlgTableCellPad : "Reitaspássía", +DlgTableCaption : "Titill", +DlgTableSummary : "Ãfram", +DlgTableHeaders : "Fyrirsagnir", +DlgTableHeadersNone : "Engar", +DlgTableHeadersColumn : "Fyrsti dálkur", +DlgTableHeadersRow : "Fyrsta röð", +DlgTableHeadersBoth : "Hvort tveggja", + +// Table Cell Dialog +DlgCellTitle : "Eigindi reits", +DlgCellWidth : "Breidd", +DlgCellWidthPx : "myndeindir", +DlgCellWidthPc : "prósent", +DlgCellHeight : "Hæð", +DlgCellWordWrap : "Línuskipting", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Já", +DlgCellWordWrapNo : "Nei", +DlgCellHorAlign : "Lárétt jöfnun", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Vinstrijafnað", +DlgCellHorAlignCenter : "Miðjað", +DlgCellHorAlignRight: "Hægrijafnað", +DlgCellVerAlign : "Lóðrétt jöfnun", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Efst", +DlgCellVerAlignMiddle : "Miðjað", +DlgCellVerAlignBottom : "Neðst", +DlgCellVerAlignBaseline : "Grunnlína", +DlgCellType : "Tegund reits", +DlgCellTypeData : "Gögn", +DlgCellTypeHeader : "Fyrirsögn", +DlgCellRowSpan : "Hæð í röðum talið", +DlgCellCollSpan : "Breidd í dálkum talið", +DlgCellBackColor : "Bakgrunnslitur", +DlgCellBorderColor : "Rammalitur", +DlgCellBtnSelect : "Veldu...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Finna og skipta", + +// Find Dialog +DlgFindTitle : "Finna", +DlgFindFindBtn : "Finna", +DlgFindNotFoundMsg : "Leitartexti fannst ekki!", + +// Replace Dialog +DlgReplaceTitle : "Skipta út", +DlgReplaceFindLbl : "Leita að:", +DlgReplaceReplaceLbl : "Skipta út fyrir:", +DlgReplaceCaseChk : "Gera greinarmun á¡ há¡- og lágstöfum", +DlgReplaceReplaceBtn : "Skipta út", +DlgReplaceReplAllBtn : "Skipta út allsstaðar", +DlgReplaceWordChk : "Aðeins heil orð", + +// Paste Operations / Dialog +PasteErrorCut : "Öryggisstillingar vafrans þíns leyfa ekki klippingu texta með músaraðgerð. Notaðu lyklaborðið í klippa (Ctrl+X).", +PasteErrorCopy : "Öryggisstillingar vafrans þíns leyfa ekki afritun texta með músaraðgerð. Notaðu lyklaborðið í afrita (Ctrl+C).", + +PasteAsText : "Líma sem ósniðinn texta", +PasteFromWord : "Líma úr Word", + +DlgPasteMsg2 : "Límdu í svæðið hér að neðan og (Ctrl+V) og smelltu á OK.", +DlgPasteSec : "Vegna öryggisstillinga í vafranum þínum fær ritillinn ekki beinan aðgang að klippuborðinu. Þú verður að líma innihaldið aftur inn í þennan glugga.", +DlgPasteIgnoreFont : "Hunsa leturskilgreiningar", +DlgPasteRemoveStyles : "Hunsa letureigindi", + +// Color Picker +ColorAutomatic : "Sjálfval", +ColorMoreColors : "Fleiri liti...", + +// Document Properties +DocProps : "Eigindi skjals", + +// Anchor Dialog +DlgAnchorTitle : "Eigindi bókamerkis", +DlgAnchorName : "Nafn bókamerkis", +DlgAnchorErrorName : "Sláðu inn nafn bókamerkis!", + +// Speller Pages Dialog +DlgSpellNotInDic : "Ekki í orðabókinni", +DlgSpellChangeTo : "Tillaga", +DlgSpellBtnIgnore : "Hunsa", +DlgSpellBtnIgnoreAll : "Hunsa allt", +DlgSpellBtnReplace : "Skipta", +DlgSpellBtnReplaceAll : "Skipta öllu", +DlgSpellBtnUndo : "Til baka", +DlgSpellNoSuggestions : "- engar tillögur -", +DlgSpellProgress : "Villuleit í gangi...", +DlgSpellNoMispell : "Villuleit lokið: Engin villa fannst", +DlgSpellNoChanges : "Villuleit lokið: Engu orði breytt", +DlgSpellOneChange : "Villuleit lokið: Einu orði breytt", +DlgSpellManyChanges : "Villuleit lokið: %1 orðum breytt", + +IeSpellDownload : "Villuleit ekki sett upp.
    Viltu setja hana upp?", + +// Button Dialog +DlgButtonText : "Texti", +DlgButtonType : "Gerð", +DlgButtonTypeBtn : "Hnappur", +DlgButtonTypeSbm : "Staðfesta", +DlgButtonTypeRst : "Hreinsa", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nafn", +DlgCheckboxValue : "Gildi", +DlgCheckboxSelected : "Valið", + +// Form Dialog +DlgFormName : "Nafn", +DlgFormAction : "Aðgerð", +DlgFormMethod : "Aðferð", + +// Select Field Dialog +DlgSelectName : "Nafn", +DlgSelectValue : "Gildi", +DlgSelectSize : "Stærð", +DlgSelectLines : "línur", +DlgSelectChkMulti : "Leyfa fleiri kosti", +DlgSelectOpAvail : "Kostir", +DlgSelectOpText : "Texti", +DlgSelectOpValue : "Gildi", +DlgSelectBtnAdd : "Bæta við", +DlgSelectBtnModify : "Breyta", +DlgSelectBtnUp : "Upp", +DlgSelectBtnDown : "Niður", +DlgSelectBtnSetValue : "Merkja sem valið", +DlgSelectBtnDelete : "Eyða", + +// Textarea Dialog +DlgTextareaName : "Nafn", +DlgTextareaCols : "Dálkar", +DlgTextareaRows : "Línur", + +// Text Field Dialog +DlgTextName : "Nafn", +DlgTextValue : "Gildi", +DlgTextCharWidth : "Breidd (leturtákn)", +DlgTextMaxChars : "Hámarksfjöldi leturtákna", +DlgTextType : "Gerð", +DlgTextTypeText : "Texti", +DlgTextTypePass : "Lykilorð", + +// Hidden Field Dialog +DlgHiddenName : "Nafn", +DlgHiddenValue : "Gildi", + +// Bulleted List Dialog +BulletedListProp : "Eigindi depillista", +NumberedListProp : "Eigindi tölusetts lista", +DlgLstStart : "Byrja", +DlgLstType : "Gerð", +DlgLstTypeCircle : "Hringur", +DlgLstTypeDisc : "Fylltur hringur", +DlgLstTypeSquare : "Ferningur", +DlgLstTypeNumbers : "Tölusett (1, 2, 3)", +DlgLstTypeLCase : "Lágstafir (a, b, c)", +DlgLstTypeUCase : "Hástafir (A, B, C)", +DlgLstTypeSRoman : "Rómverkar lágstafatölur (i, ii, iii)", +DlgLstTypeLRoman : "Rómverkar hástafatölur (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Almennt", +DlgDocBackTab : "Bakgrunnur", +DlgDocColorsTab : "Litir og rammar", +DlgDocMetaTab : "Lýsigögn", + +DlgDocPageTitle : "Titill síðu", +DlgDocLangDir : "Tungumál", +DlgDocLangDirLTR : "Vinstri til hægri (LTR)", +DlgDocLangDirRTL : "Hægri til vinstri (RTL)", +DlgDocLangCode : "Tungumálakóði", +DlgDocCharSet : "Letursett", +DlgDocCharSetCE : "Mið-evrópskt", +DlgDocCharSetCT : "Kínverskt, hefðbundið (Big5)", +DlgDocCharSetCR : "Kýrilskt", +DlgDocCharSetGR : "Grískt", +DlgDocCharSetJP : "Japanskt", +DlgDocCharSetKR : "Kóreskt", +DlgDocCharSetTR : "Tyrkneskt", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Vestur-evrópst", +DlgDocCharSetOther : "Annað letursett", + +DlgDocDocType : "Flokkur skjalategunda", +DlgDocDocTypeOther : "Annar flokkur skjalategunda", +DlgDocIncXHTML : "Fella inn XHTML lýsingu", +DlgDocBgColor : "Bakgrunnslitur", +DlgDocBgImage : "Slóð bakgrunnsmyndar", +DlgDocBgNoScroll : "Læstur bakgrunnur", +DlgDocCText : "Texti", +DlgDocCLink : "Stikla", +DlgDocCVisited : "Heimsótt stikla", +DlgDocCActive : "Virk stikla", +DlgDocMargins : "Hliðarspássía", +DlgDocMaTop : "Efst", +DlgDocMaLeft : "Vinstri", +DlgDocMaRight : "Hægri", +DlgDocMaBottom : "Neðst", +DlgDocMeIndex : "Lykilorð efnisorðaskrár (aðgreind með kommum)", +DlgDocMeDescr : "Lýsing skjals", +DlgDocMeAuthor : "Höfundur", +DlgDocMeCopy : "Höfundarréttur", +DlgDocPreview : "Sýna", + +// Templates Dialog +Templates : "Sniðmát", +DlgTemplatesTitle : "Innihaldssniðmát", +DlgTemplatesSelMsg : "Veldu sniðmát til að opna í ritlinum.
    (Núverandi innihald víkur fyrir því!):", +DlgTemplatesLoading : "Sæki lista yfir sniðmát...", +DlgTemplatesNoTpl : "(Ekkert sniðmát er skilgreint!)", +DlgTemplatesReplace : "Skipta út raunverulegu innihaldi", + +// About Dialog +DlgAboutAboutTab : "Um", +DlgAboutBrowserInfoTab : "Almennt", +DlgAboutLicenseTab : "Leyfi", +DlgAboutVersion : "útgáfa", +DlgAboutInfo : "Nánari upplýsinar, sjá:", + +// Div Dialog +DlgDivGeneralTab : "Almennt", +DlgDivAdvancedTab : "Sérhæft", +DlgDivStyle : "Stíll", +DlgDivInlineStyle : "Línulægur stíll", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/it.js b/www/js/FCKeditor/editor/lang/it.js new file mode 100644 index 0000000..cbb67ab --- /dev/null +++ b/www/js/FCKeditor/editor/lang/it.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Italian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Nascondi la barra degli strumenti", +ToolbarExpand : "Mostra la barra degli strumenti", + +// Toolbar Items and Context Menu +Save : "Salva", +NewPage : "Nuova pagina vuota", +Preview : "Anteprima", +Cut : "Taglia", +Copy : "Copia", +Paste : "Incolla", +PasteText : "Incolla come testo semplice", +PasteWord : "Incolla da Word", +Print : "Stampa", +SelectAll : "Seleziona tutto", +RemoveFormat : "Elimina formattazione", +InsertLinkLbl : "Collegamento", +InsertLink : "Inserisci/Modifica collegamento", +RemoveLink : "Elimina collegamento", +VisitLink : "Open Link", //MISSING +Anchor : "Inserisci/Modifica Ancora", +AnchorDelete : "Rimuovi Ancora", +InsertImageLbl : "Immagine", +InsertImage : "Inserisci/Modifica immagine", +InsertFlashLbl : "Oggetto Flash", +InsertFlash : "Inserisci/Modifica Oggetto Flash", +InsertTableLbl : "Tabella", +InsertTable : "Inserisci/Modifica tabella", +InsertLineLbl : "Riga orizzontale", +InsertLine : "Inserisci riga orizzontale", +InsertSpecialCharLbl: "Caratteri speciali", +InsertSpecialChar : "Inserisci carattere speciale", +InsertSmileyLbl : "Emoticon", +InsertSmiley : "Inserisci emoticon", +About : "Informazioni su FCKeditor", +Bold : "Grassetto", +Italic : "Corsivo", +Underline : "Sottolineato", +StrikeThrough : "Barrato", +Subscript : "Pedice", +Superscript : "Apice", +LeftJustify : "Allinea a sinistra", +CenterJustify : "Centra", +RightJustify : "Allinea a destra", +BlockJustify : "Giustifica", +DecreaseIndent : "Riduci rientro", +IncreaseIndent : "Aumenta rientro", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Annulla", +Redo : "Ripristina", +NumberedListLbl : "Elenco numerato", +NumberedList : "Inserisci/Modifica elenco numerato", +BulletedListLbl : "Elenco puntato", +BulletedList : "Inserisci/Modifica elenco puntato", +ShowTableBorders : "Mostra bordi tabelle", +ShowDetails : "Mostra dettagli", +Style : "Stile", +FontFormat : "Formato", +Font : "Font", +FontSize : "Dimensione", +TextColor : "Colore testo", +BGColor : "Colore sfondo", +Source : "Codice Sorgente", +Find : "Trova", +Replace : "Sostituisci", +SpellCheck : "Correttore ortografico", +UniversalKeyboard : "Tastiera universale", +PageBreakLbl : "Interruzione di pagina", +PageBreak : "Inserisci interruzione di pagina", + +Form : "Modulo", +Checkbox : "Checkbox", +RadioButton : "Radio Button", +TextField : "Campo di testo", +Textarea : "Area di testo", +HiddenField : "Campo nascosto", +Button : "Bottone", +SelectionField : "Menu di selezione", +ImageButton : "Bottone immagine", + +FitWindow : "Massimizza l'area dell'editor", +ShowBlocks : "Visualizza Blocchi", + +// Context Menu +EditLink : "Modifica collegamento", +CellCM : "Cella", +RowCM : "Riga", +ColumnCM : "Colonna", +InsertRowAfter : "Inserisci Riga Dopo", +InsertRowBefore : "Inserisci Riga Prima", +DeleteRows : "Elimina righe", +InsertColumnAfter : "Inserisci Colonna Dopo", +InsertColumnBefore : "Inserisci Colonna Prima", +DeleteColumns : "Elimina colonne", +InsertCellAfter : "Inserisci Cella Dopo", +InsertCellBefore : "Inserisci Cella Prima", +DeleteCells : "Elimina celle", +MergeCells : "Unisce celle", +MergeRight : "Unisci a Destra", +MergeDown : "Unisci in Basso", +HorizontalSplitCell : "Dividi Cella Orizzontalmente", +VerticalSplitCell : "Dividi Cella Verticalmente", +TableDelete : "Cancella Tabella", +CellProperties : "Proprietà cella", +TableProperties : "Proprietà tabella", +ImageProperties : "Proprietà immagine", +FlashProperties : "Proprietà Oggetto Flash", + +AnchorProp : "Proprietà ancora", +ButtonProp : "Proprietà bottone", +CheckboxProp : "Proprietà checkbox", +HiddenFieldProp : "Proprietà campo nascosto", +RadioButtonProp : "Proprietà radio button", +ImageButtonProp : "Proprietà bottone immagine", +TextFieldProp : "Proprietà campo di testo", +SelectionFieldProp : "Proprietà menu di selezione", +TextareaProp : "Proprietà area di testo", +FormProp : "Proprietà modulo", + +FontFormats : "Normale;Formattato;Indirizzo;Titolo 1;Titolo 2;Titolo 3;Titolo 4;Titolo 5;Titolo 6;Paragrafo (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Elaborazione XHTML in corso. Attendere prego...", +Done : "Completato", +PasteWordConfirm : "Il testo da incollare sembra provenire da Word. Desideri pulirlo prima di incollare?", +NotCompatiblePaste : "Questa funzione è disponibile solo per Internet Explorer 5.5 o superiore. Desideri incollare il testo senza pulirlo?", +UnknownToolbarItem : "Elemento della barra strumenti sconosciuto \"%1\"", +UnknownCommand : "Comando sconosciuto \"%1\"", +NotImplemented : "Comando non implementato", +UnknownToolbarSet : "La barra di strumenti \"%1\" non esiste", +NoActiveX : "Le impostazioni di sicurezza del tuo browser potrebbero limitare alcune funzionalità dell'editor. Devi abilitare l'opzione \"Esegui controlli e plug-in ActiveX\". Potresti avere errori e notare funzionalità mancanti.", +BrowseServerBlocked : "Non è possibile aprire la finestra di espolorazione risorse. Verifica che tutti i blocca popup siano bloccati.", +DialogBlocked : "Non è possibile aprire la finestra di dialogo. Verifica che tutti i blocca popup siano bloccati.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Annulla", +DlgBtnClose : "Chiudi", +DlgBtnBrowseServer : "Cerca sul server", +DlgAdvancedTag : "Avanzate", +DlgOpOther : "", +DlgInfoTab : "Info", +DlgAlertUrl : "Devi inserire l'URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Direzione scrittura", +DlgGenLangDirLtr : "Da Sinistra a Destra (LTR)", +DlgGenLangDirRtl : "Da Destra a Sinistra (RTL)", +DlgGenLangCode : "Codice Lingua", +DlgGenAccessKey : "Scorciatoia
    da tastiera", +DlgGenName : "Nome", +DlgGenTabIndex : "Ordine di tabulazione", +DlgGenLongDescr : "URL descrizione estesa", +DlgGenClass : "Nome classe CSS", +DlgGenTitle : "Titolo", +DlgGenContType : "Tipo della risorsa collegata", +DlgGenLinkCharset : "Set di caretteri della risorsa collegata", +DlgGenStyle : "Stile", + +// Image Dialog +DlgImgTitle : "Proprietà immagine", +DlgImgInfoTab : "Informazioni immagine", +DlgImgBtnUpload : "Invia al server", +DlgImgURL : "URL", +DlgImgUpload : "Carica", +DlgImgAlt : "Testo alternativo", +DlgImgWidth : "Larghezza", +DlgImgHeight : "Altezza", +DlgImgLockRatio : "Blocca rapporto", +DlgBtnResetSize : "Reimposta dimensione", +DlgImgBorder : "Bordo", +DlgImgHSpace : "HSpace", +DlgImgVSpace : "VSpace", +DlgImgAlign : "Allineamento", +DlgImgAlignLeft : "Sinistra", +DlgImgAlignAbsBottom: "In basso assoluto", +DlgImgAlignAbsMiddle: "Centrato assoluto", +DlgImgAlignBaseline : "Linea base", +DlgImgAlignBottom : "In Basso", +DlgImgAlignMiddle : "Centrato", +DlgImgAlignRight : "Destra", +DlgImgAlignTextTop : "In alto al testo", +DlgImgAlignTop : "In Alto", +DlgImgPreview : "Anteprima", +DlgImgAlertUrl : "Devi inserire l'URL per l'immagine", +DlgImgLinkTab : "Collegamento", + +// Flash Dialog +DlgFlashTitle : "Proprietà Oggetto Flash", +DlgFlashChkPlay : "Avvio Automatico", +DlgFlashChkLoop : "Cicla", +DlgFlashChkMenu : "Abilita Menu di Flash", +DlgFlashScale : "Ridimensiona", +DlgFlashScaleAll : "Mostra Tutto", +DlgFlashScaleNoBorder : "Senza Bordo", +DlgFlashScaleFit : "Dimensione Esatta", + +// Link Dialog +DlgLnkWindowTitle : "Collegamento", +DlgLnkInfoTab : "Informazioni collegamento", +DlgLnkTargetTab : "Destinazione", + +DlgLnkType : "Tipo di Collegamento", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "Ancora nella pagina", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "Protocollo", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Scegli Ancora", +DlgLnkAnchorByName : "Per Nome", +DlgLnkAnchorById : "Per id elemento", +DlgLnkNoAnchors : "(Nessuna ancora disponibile nel documento)", +DlgLnkEMail : "Indirizzo E-Mail", +DlgLnkEMailSubject : "Oggetto del messaggio", +DlgLnkEMailBody : "Corpo del messaggio", +DlgLnkUpload : "Carica", +DlgLnkBtnUpload : "Invia al Server", + +DlgLnkTarget : "Destinazione", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Nuova finestra (_blank)", +DlgLnkTargetParent : "Finestra padre (_parent)", +DlgLnkTargetSelf : "Stessa finestra (_self)", +DlgLnkTargetTop : "Finestra superiore (_top)", +DlgLnkTargetFrameName : "Nome del riquadro di destinazione", +DlgLnkPopWinName : "Nome finestra popup", +DlgLnkPopWinFeat : "Caratteristiche finestra popup", +DlgLnkPopResize : "Ridimensionabile", +DlgLnkPopLocation : "Barra degli indirizzi", +DlgLnkPopMenu : "Barra del menu", +DlgLnkPopScroll : "Barre di scorrimento", +DlgLnkPopStatus : "Barra di stato", +DlgLnkPopToolbar : "Barra degli strumenti", +DlgLnkPopFullScrn : "A tutto schermo (IE)", +DlgLnkPopDependent : "Dipendente (Netscape)", +DlgLnkPopWidth : "Larghezza", +DlgLnkPopHeight : "Altezza", +DlgLnkPopLeft : "Posizione da sinistra", +DlgLnkPopTop : "Posizione dall'alto", + +DlnLnkMsgNoUrl : "Devi inserire l'URL del collegamento", +DlnLnkMsgNoEMail : "Devi inserire un'indirizzo e-mail", +DlnLnkMsgNoAnchor : "Devi selezionare un'ancora", +DlnLnkMsgInvPopName : "Il nome del popup deve iniziare con una lettera, e non può contenere spazi", + +// Color Dialog +DlgColorTitle : "Seleziona colore", +DlgColorBtnClear : "Vuota", +DlgColorHighlight : "Evidenziato", +DlgColorSelected : "Selezionato", + +// Smiley Dialog +DlgSmileyTitle : "Inserisci emoticon", + +// Special Character Dialog +DlgSpecialCharTitle : "Seleziona carattere speciale", + +// Table Dialog +DlgTableTitle : "Proprietà tabella", +DlgTableRows : "Righe", +DlgTableColumns : "Colonne", +DlgTableBorder : "Dimensione bordo", +DlgTableAlign : "Allineamento", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "Sinistra", +DlgTableAlignCenter : "Centrato", +DlgTableAlignRight : "Destra", +DlgTableWidth : "Larghezza", +DlgTableWidthPx : "pixel", +DlgTableWidthPc : "percento", +DlgTableHeight : "Altezza", +DlgTableCellSpace : "Spaziatura celle", +DlgTableCellPad : "Padding celle", +DlgTableCaption : "Intestazione", +DlgTableSummary : "Indice", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "Proprietà cella", +DlgCellWidth : "Larghezza", +DlgCellWidthPx : "pixel", +DlgCellWidthPc : "percento", +DlgCellHeight : "Altezza", +DlgCellWordWrap : "A capo automatico", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Si", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "Allineamento orizzontale", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "Sinistra", +DlgCellHorAlignCenter : "Centrato", +DlgCellHorAlignRight: "Destra", +DlgCellVerAlign : "Allineamento verticale", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "In Alto", +DlgCellVerAlignMiddle : "Centrato", +DlgCellVerAlignBottom : "In Basso", +DlgCellVerAlignBaseline : "Linea base", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "Righe occupate", +DlgCellCollSpan : "Colonne occupate", +DlgCellBackColor : "Colore sfondo", +DlgCellBorderColor : "Colore bordo", +DlgCellBtnSelect : "Scegli...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Cerca e Sostituisci", + +// Find Dialog +DlgFindTitle : "Trova", +DlgFindFindBtn : "Trova", +DlgFindNotFoundMsg : "L'elemento cercato non è stato trovato.", + +// Replace Dialog +DlgReplaceTitle : "Sostituisci", +DlgReplaceFindLbl : "Trova:", +DlgReplaceReplaceLbl : "Sostituisci con:", +DlgReplaceCaseChk : "Maiuscole/minuscole", +DlgReplaceReplaceBtn : "Sostituisci", +DlgReplaceReplAllBtn : "Sostituisci tutto", +DlgReplaceWordChk : "Solo parole intere", + +// Paste Operations / Dialog +PasteErrorCut : "Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl+X).", +PasteErrorCopy : "Le impostazioni di sicurezza del browser non permettono di copiare automaticamente il testo. Usa la tastiera (Ctrl+C).", + +PasteAsText : "Incolla come testo semplice", +PasteFromWord : "Incolla da Word", + +DlgPasteMsg2 : "Incolla il testo all'interno dell'area sottostante usando la scorciatoia di tastiere (Ctrl+V) e premi OK.", +DlgPasteSec : "A causa delle impostazioni di sicurezza del browser,l'editor non è in grado di accedere direttamente agli appunti. E' pertanto necessario incollarli di nuovo in questa finestra.", +DlgPasteIgnoreFont : "Ignora le definizioni di Font", +DlgPasteRemoveStyles : "Rimuovi le definizioni di Stile", + +// Color Picker +ColorAutomatic : "Automatico", +ColorMoreColors : "Altri colori...", + +// Document Properties +DocProps : "Proprietà del Documento", + +// Anchor Dialog +DlgAnchorTitle : "Proprietà ancora", +DlgAnchorName : "Nome ancora", +DlgAnchorErrorName : "Inserici il nome dell'ancora", + +// Speller Pages Dialog +DlgSpellNotInDic : "Non nel dizionario", +DlgSpellChangeTo : "Cambia in", +DlgSpellBtnIgnore : "Ignora", +DlgSpellBtnIgnoreAll : "Ignora tutto", +DlgSpellBtnReplace : "Cambia", +DlgSpellBtnReplaceAll : "Cambia tutto", +DlgSpellBtnUndo : "Annulla", +DlgSpellNoSuggestions : "- Nessun suggerimento -", +DlgSpellProgress : "Controllo ortografico in corso", +DlgSpellNoMispell : "Controllo ortografico completato: nessun errore trovato", +DlgSpellNoChanges : "Controllo ortografico completato: nessuna parola cambiata", +DlgSpellOneChange : "Controllo ortografico completato: 1 parola cambiata", +DlgSpellManyChanges : "Controllo ortografico completato: %1 parole cambiate", + +IeSpellDownload : "Contollo ortografico non installato. Lo vuoi scaricare ora?", + +// Button Dialog +DlgButtonText : "Testo (Value)", +DlgButtonType : "Tipo", +DlgButtonTypeBtn : "Bottone", +DlgButtonTypeSbm : "Invio", +DlgButtonTypeRst : "Annulla", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Nome", +DlgCheckboxValue : "Valore", +DlgCheckboxSelected : "Selezionato", + +// Form Dialog +DlgFormName : "Nome", +DlgFormAction : "Azione", +DlgFormMethod : "Metodo", + +// Select Field Dialog +DlgSelectName : "Nome", +DlgSelectValue : "Valore", +DlgSelectSize : "Dimensione", +DlgSelectLines : "righe", +DlgSelectChkMulti : "Permetti selezione multipla", +DlgSelectOpAvail : "Opzioni disponibili", +DlgSelectOpText : "Testo", +DlgSelectOpValue : "Valore", +DlgSelectBtnAdd : "Aggiungi", +DlgSelectBtnModify : "Modifica", +DlgSelectBtnUp : "Su", +DlgSelectBtnDown : "Gi", +DlgSelectBtnSetValue : "Imposta come predefinito", +DlgSelectBtnDelete : "Rimuovi", + +// Textarea Dialog +DlgTextareaName : "Nome", +DlgTextareaCols : "Colonne", +DlgTextareaRows : "Righe", + +// Text Field Dialog +DlgTextName : "Nome", +DlgTextValue : "Valore", +DlgTextCharWidth : "Larghezza", +DlgTextMaxChars : "Numero massimo di caratteri", +DlgTextType : "Tipo", +DlgTextTypeText : "Testo", +DlgTextTypePass : "Password", + +// Hidden Field Dialog +DlgHiddenName : "Nome", +DlgHiddenValue : "Valore", + +// Bulleted List Dialog +BulletedListProp : "Proprietà lista puntata", +NumberedListProp : "Proprietà lista numerata", +DlgLstStart : "Inizio", +DlgLstType : "Tipo", +DlgLstTypeCircle : "Tondo", +DlgLstTypeDisc : "Disco", +DlgLstTypeSquare : "Quadrato", +DlgLstTypeNumbers : "Numeri (1, 2, 3)", +DlgLstTypeLCase : "Caratteri minuscoli (a, b, c)", +DlgLstTypeUCase : "Caratteri maiuscoli (A, B, C)", +DlgLstTypeSRoman : "Numeri Romani minuscoli (i, ii, iii)", +DlgLstTypeLRoman : "Numeri Romani maiuscoli (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Genarale", +DlgDocBackTab : "Sfondo", +DlgDocColorsTab : "Colori e margini", +DlgDocMetaTab : "Meta Data", + +DlgDocPageTitle : "Titolo pagina", +DlgDocLangDir : "Direzione scrittura", +DlgDocLangDirLTR : "Da Sinistra a Destra (LTR)", +DlgDocLangDirRTL : "Da Destra a Sinistra (RTL)", +DlgDocLangCode : "Codice Lingua", +DlgDocCharSet : "Set di caretteri", +DlgDocCharSetCE : "Europa Centrale", +DlgDocCharSetCT : "Cinese Tradizionale (Big5)", +DlgDocCharSetCR : "Cirillico", +DlgDocCharSetGR : "Greco", +DlgDocCharSetJP : "Giapponese", +DlgDocCharSetKR : "Coreano", +DlgDocCharSetTR : "Turco", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Europa Occidentale", +DlgDocCharSetOther : "Altro set di caretteri", + +DlgDocDocType : "Intestazione DocType", +DlgDocDocTypeOther : "Altra intestazione DocType", +DlgDocIncXHTML : "Includi dichiarazione XHTML", +DlgDocBgColor : "Colore di sfondo", +DlgDocBgImage : "Immagine di sfondo", +DlgDocBgNoScroll : "Sfondo fissato", +DlgDocCText : "Testo", +DlgDocCLink : "Collegamento", +DlgDocCVisited : "Collegamento visitato", +DlgDocCActive : "Collegamento attivo", +DlgDocMargins : "Margini", +DlgDocMaTop : "In Alto", +DlgDocMaLeft : "A Sinistra", +DlgDocMaRight : "A Destra", +DlgDocMaBottom : "In Basso", +DlgDocMeIndex : "Chiavi di indicizzazione documento (separate da virgola)", +DlgDocMeDescr : "Descrizione documento", +DlgDocMeAuthor : "Autore", +DlgDocMeCopy : "Copyright", +DlgDocPreview : "Anteprima", + +// Templates Dialog +Templates : "Modelli", +DlgTemplatesTitle : "Contenuto dei modelli", +DlgTemplatesSelMsg : "Seleziona il modello da aprire nell'editor
    (il contenuto attuale verrà eliminato):", +DlgTemplatesLoading : "Caricamento modelli in corso. Attendere prego...", +DlgTemplatesNoTpl : "(Nessun modello definito)", +DlgTemplatesReplace : "Cancella il contenuto corrente", + +// About Dialog +DlgAboutAboutTab : "Informazioni", +DlgAboutBrowserInfoTab : "Informazioni Browser", +DlgAboutLicenseTab : "Licenza", +DlgAboutVersion : "versione", +DlgAboutInfo : "Per maggiori informazioni visitare", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/ja.js b/www/js/FCKeditor/editor/lang/ja.js new file mode 100644 index 0000000..897cc11 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/ja.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Japanese language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "ツールãƒãƒ¼ã‚’éš ã™", +ToolbarExpand : "ツールãƒãƒ¼ã‚’表示", + +// Toolbar Items and Context Menu +Save : "ä¿å­˜", +NewPage : "æ–°ã—ã„ページ", +Preview : "プレビュー", +Cut : "切りå–ã‚Š", +Copy : "コピー", +Paste : "貼り付ã‘", +PasteText : "プレーンテキスト貼り付ã‘", +PasteWord : "ワード文章ã‹ã‚‰è²¼ã‚Šä»˜ã‘", +Print : "å°åˆ·", +SelectAll : "ã™ã¹ã¦é¸æŠž", +RemoveFormat : "フォーマット削除", +InsertLinkLbl : "リンク", +InsertLink : "リンク挿入/編集", +RemoveLink : "リンク削除", +VisitLink : "リンクを開ã", +Anchor : "アンカー挿入/編集", +AnchorDelete : "アンカー削除", +InsertImageLbl : "イメージ", +InsertImage : "イメージ挿入/編集", +InsertFlashLbl : "Flash", +InsertFlash : "Flash挿入/編集", +InsertTableLbl : "テーブル", +InsertTable : "テーブル挿入/編集", +InsertLineLbl : "ライン", +InsertLine : "横罫線", +InsertSpecialCharLbl: "特殊文字", +InsertSpecialChar : "特殊文字挿入", +InsertSmileyLbl : "絵文字", +InsertSmiley : "絵文字挿入", +About : "FCKeditorヘルプ", +Bold : "太字", +Italic : "斜体", +Underline : "下線", +StrikeThrough : "打ã¡æ¶ˆã—ç·š", +Subscript : "æ·»ãˆå­—", +Superscript : "上付ã文字", +LeftJustify : "å·¦æƒãˆ", +CenterJustify : "中央æƒãˆ", +RightJustify : "å³æƒãˆ", +BlockJustify : "両端æƒãˆ", +DecreaseIndent : "インデント解除", +IncreaseIndent : "インデント", +Blockquote : "ブロック引用", +CreateDiv : "Div 作æˆ", +EditDiv : "Div 編集", +DeleteDiv : "Div 削除", +Undo : "å…ƒã«æˆ»ã™", +Redo : "ã‚„ã‚Šç›´ã—", +NumberedListLbl : "段è½ç•ªå·", +NumberedList : "段è½ç•ªå·ã®è¿½åŠ /削除", +BulletedListLbl : "箇æ¡æ›¸ã", +BulletedList : "箇æ¡æ›¸ãã®è¿½åŠ /削除", +ShowTableBorders : "テーブルボーダー表示", +ShowDetails : "詳細表示", +Style : "スタイル", +FontFormat : "フォーマット", +Font : "フォント", +FontSize : "サイズ", +TextColor : "テキスト色", +BGColor : "背景色", +Source : "ソース", +Find : "検索", +Replace : "ç½®ãæ›ãˆ", +SpellCheck : "スペルãƒã‚§ãƒƒã‚¯", +UniversalKeyboard : "ユニãƒãƒ¼ã‚µãƒ«ãƒ»ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰", +PageBreakLbl : "改ページ", +PageBreak : "改ページ挿入", + +Form : "フォーム", +Checkbox : "ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹", +RadioButton : "ラジオボタン", +TextField : "1行テキスト", +Textarea : "テキストエリア", +HiddenField : "ä¸å¯è¦–フィールド", +Button : "ボタン", +SelectionField : "é¸æŠžãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰", +ImageButton : "ç”»åƒãƒœã‚¿ãƒ³", + +FitWindow : "エディタサイズを最大ã«ã—ã¾ã™", +ShowBlocks : "ブロック表示", + +// Context Menu +EditLink : "リンク編集", +CellCM : "セル", +RowCM : "è¡Œ", +ColumnCM : "カラム", +InsertRowAfter : "列ã®å¾Œã«æŒ¿å…¥", +InsertRowBefore : "列ã®å‰ã«æŒ¿å…¥", +DeleteRows : "行削除", +InsertColumnAfter : "カラムã®å¾Œã«æŒ¿å…¥", +InsertColumnBefore : "カラムã®å‰ã«æŒ¿å…¥", +DeleteColumns : "列削除", +InsertCellAfter : "セルã®å¾Œã«æŒ¿å…¥", +InsertCellBefore : "セルã®å‰ã«æŒ¿å…¥", +DeleteCells : "セル削除", +MergeCells : "セルçµåˆ", +MergeRight : "å³ã«çµåˆ", +MergeDown : "下ã«çµåˆ", +HorizontalSplitCell : "セルを水平方å‘分割", +VerticalSplitCell : "セルを垂直方å‘ã«åˆ†å‰²", +TableDelete : "テーブル削除", +CellProperties : "セル プロパティ", +TableProperties : "テーブル プロパティ", +ImageProperties : "イメージ プロパティ", +FlashProperties : "Flash プロパティ", + +AnchorProp : "アンカー プロパティ", +ButtonProp : "ボタン プロパティ", +CheckboxProp : "ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ プロパティ", +HiddenFieldProp : "ä¸å¯è¦–フィールド プロパティ", +RadioButtonProp : "ラジオボタン プロパティ", +ImageButtonProp : "ç”»åƒãƒœã‚¿ãƒ³ プロパティ", +TextFieldProp : "1行テキスト プロパティ", +SelectionFieldProp : "é¸æŠžãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ プロパティ", +TextareaProp : "テキストエリア プロパティ", +FormProp : "フォーム プロパティ", + +FontFormats : "標準;書å¼ä»˜ã;アドレス;見出㗠1;見出㗠2;見出㗠3;見出㗠4;見出㗠5;見出㗠6;標準 (DIV)", + +// Alerts and Messages +ProcessingXHTML : "XHTML処ç†ä¸­. ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...", +Done : "完了", +PasteWordConfirm : "貼り付ã‘ã‚’è¡Œã†ãƒ†ã‚­ã‚¹ãƒˆã¯ã€ãƒ¯ãƒ¼ãƒ‰æ–‡ç« ã‹ã‚‰ã‚³ãƒ”ーã•ã‚Œã‚ˆã†ã¨ã—ã¦ã„ã¾ã™ã€‚貼り付ã‘ã‚‹å‰ã«ã‚¯ãƒªãƒ¼ãƒ‹ãƒ³ã‚°ã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ", +NotCompatiblePaste : "ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆãƒ»ã‚¨ã‚¯ã‚¹ãƒ—ローラーãƒãƒ¼ã‚¸ãƒ§ãƒ³5.5以上ã§åˆ©ç”¨å¯èƒ½ã§ã™ã€‚クリーニングã—ãªã„ã§è²¼ã‚Šä»˜ã‘ã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ", +UnknownToolbarItem : "未知ã®ãƒ„ールãƒãƒ¼é …ç›® \"%1\"", +UnknownCommand : "未知ã®ã‚³ãƒžãƒ³ãƒ‰å \"%1\"", +NotImplemented : "コマンドã¯ã‚¤ãƒ³ãƒ—リメントã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚", +UnknownToolbarSet : "ツールãƒãƒ¼è¨­å®š \"%1\" 存在ã—ã¾ã›ã‚“。", +NoActiveX : "エラーã€è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãªã©ãŒç™ºç”Ÿã—ãŸå ´åˆã€ãƒ–ラウザーã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£è¨­å®šã«ã‚ˆã‚Šã‚¨ãƒ‡ã‚£ã‚¿ã®ã„ãã¤ã‹ã®æ©Ÿèƒ½ãŒåˆ¶é™ã•ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚セキュリティ設定ã®ã‚ªãƒ—ションã§\"ActiveXコントロールã¨ãƒ—ラグインã®å®Ÿè¡Œ\"を有効ã«ã™ã‚‹ã«ã—ã¦ãã ã•ã„。", +BrowseServerBlocked : "サーãƒãƒ¼ãƒ–ラウザーを開ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ãƒãƒƒãƒ—アップ・ブロック機能ãŒç„¡åŠ¹ã«ãªã£ã¦ã„ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。", +DialogBlocked : "ダイアログウィンドウを開ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ãƒãƒƒãƒ—アップ・ブロック機能ãŒç„¡åŠ¹ã«ãªã£ã¦ã„ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。", +VisitLinkBlocked : "æ–°ã—ã„ウィンドウを開ãã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ãƒãƒƒãƒ—アップ・ブロック機能ãŒç„¡åŠ¹ã«ãªã£ã¦ã„ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "キャンセル", +DlgBtnClose : "é–‰ã˜ã‚‹", +DlgBtnBrowseServer : "サーãƒãƒ¼ãƒ–ラウザー", +DlgAdvancedTag : "高度ãªè¨­å®š", +DlgOpOther : "<ãã®ä»–>", +DlgInfoTab : "情報", +DlgAlertUrl : "URLを挿入ã—ã¦ãã ã•ã„", + +// General Dialogs Labels +DlgGenNotSet : "<ãªã—>", +DlgGenId : "Id", +DlgGenLangDir : "文字表記ã®æ–¹å‘", +DlgGenLangDirLtr : "å·¦ã‹ã‚‰å³ (LTR)", +DlgGenLangDirRtl : "å³ã‹ã‚‰å·¦ (RTL)", +DlgGenLangCode : "言語コード", +DlgGenAccessKey : "アクセスキー", +DlgGenName : "Name属性", +DlgGenTabIndex : "タブインデックス", +DlgGenLongDescr : "longdesc属性(長文説明)", +DlgGenClass : "スタイルシートクラス", +DlgGenTitle : "Title属性", +DlgGenContType : "Content Type属性", +DlgGenLinkCharset : "リンクcharset属性", +DlgGenStyle : "スタイルシート", + +// Image Dialog +DlgImgTitle : "イメージ プロパティ", +DlgImgInfoTab : "イメージ 情報", +DlgImgBtnUpload : "サーãƒãƒ¼ã«é€ä¿¡", +DlgImgURL : "URL", +DlgImgUpload : "アップロード", +DlgImgAlt : "代替テキスト", +DlgImgWidth : "å¹…", +DlgImgHeight : "高ã•", +DlgImgLockRatio : "ロック比率", +DlgBtnResetSize : "サイズリセット", +DlgImgBorder : "ボーダー", +DlgImgHSpace : "横間隔", +DlgImgVSpace : "縦間隔", +DlgImgAlign : "è¡Œæƒãˆ", +DlgImgAlignLeft : "å·¦", +DlgImgAlignAbsBottom: "下部(絶対的)", +DlgImgAlignAbsMiddle: "中央(絶対的)", +DlgImgAlignBaseline : "ベースライン", +DlgImgAlignBottom : "下", +DlgImgAlignMiddle : "中央", +DlgImgAlignRight : "å³", +DlgImgAlignTextTop : "テキスト上部", +DlgImgAlignTop : "上", +DlgImgPreview : "プレビュー", +DlgImgAlertUrl : "イメージã®URLを入力ã—ã¦ãã ã•ã„。", +DlgImgLinkTab : "リンク", + +// Flash Dialog +DlgFlashTitle : "Flash プロパティ", +DlgFlashChkPlay : "å†ç”Ÿ", +DlgFlashChkLoop : "ループå†ç”Ÿ", +DlgFlashChkMenu : "Flashメニューå¯èƒ½", +DlgFlashScale : "拡大縮å°è¨­å®š", +DlgFlashScaleAll : "ã™ã¹ã¦è¡¨ç¤º", +DlgFlashScaleNoBorder : "外ãŒè¦‹ãˆãªã„様ã«æ‹¡å¤§", +DlgFlashScaleFit : "上下左å³ã«ãƒ•ã‚£ãƒƒãƒˆ", + +// Link Dialog +DlgLnkWindowTitle : "ãƒã‚¤ãƒ‘ーリンク", +DlgLnkInfoTab : "ãƒã‚¤ãƒ‘ーリンク 情報", +DlgLnkTargetTab : "ターゲット", + +DlgLnkType : "リンクタイプ", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "ã“ã®ãƒšãƒ¼ã‚¸ã®ã‚¢ãƒ³ã‚«ãƒ¼", +DlgLnkTypeEMail : "E-Mail", +DlgLnkProto : "プロトコル", +DlgLnkProtoOther : "<ãã®ä»–>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "アンカーをé¸æŠž", +DlgLnkAnchorByName : "アンカーå", +DlgLnkAnchorById : "エレメントID", +DlgLnkNoAnchors : "(ドキュメントã«ãŠã„ã¦åˆ©ç”¨å¯èƒ½ãªã‚¢ãƒ³ã‚«ãƒ¼ã¯ã‚ã‚Šã¾ã›ã‚“。)", +DlgLnkEMail : "E-Mail アドレス", +DlgLnkEMailSubject : "件å", +DlgLnkEMailBody : "本文", +DlgLnkUpload : "アップロード", +DlgLnkBtnUpload : "サーãƒãƒ¼ã«é€ä¿¡", + +DlgLnkTarget : "ターゲット", +DlgLnkTargetFrame : "<フレーム>", +DlgLnkTargetPopup : "<ãƒãƒƒãƒ—アップウィンドウ>", +DlgLnkTargetBlank : "æ–°ã—ã„ウィンドウ (_blank)", +DlgLnkTargetParent : "親ウィンドウ (_parent)", +DlgLnkTargetSelf : "åŒã˜ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ (_self)", +DlgLnkTargetTop : "最上ä½ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ (_top)", +DlgLnkTargetFrameName : "目的ã®ãƒ•ãƒ¬ãƒ¼ãƒ å", +DlgLnkPopWinName : "ãƒãƒƒãƒ—アップウィンドウå", +DlgLnkPopWinFeat : "ãƒãƒƒãƒ—アップウィンドウ特徴", +DlgLnkPopResize : "リサイズå¯èƒ½", +DlgLnkPopLocation : "ロケーションãƒãƒ¼", +DlgLnkPopMenu : "メニューãƒãƒ¼", +DlgLnkPopScroll : "スクロールãƒãƒ¼", +DlgLnkPopStatus : "ステータスãƒãƒ¼", +DlgLnkPopToolbar : "ツールãƒãƒ¼", +DlgLnkPopFullScrn : "全画é¢ãƒ¢ãƒ¼ãƒ‰(IE)", +DlgLnkPopDependent : "é–‹ã„ãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«é€£å‹•ã—ã¦é–‰ã˜ã‚‹ (Netscape)", +DlgLnkPopWidth : "å¹…", +DlgLnkPopHeight : "高ã•", +DlgLnkPopLeft : "左端ã‹ã‚‰ã®åº§æ¨™ã§æŒ‡å®š", +DlgLnkPopTop : "上端ã‹ã‚‰ã®åº§æ¨™ã§æŒ‡å®š", + +DlnLnkMsgNoUrl : "リンクURLを入力ã—ã¦ãã ã•ã„。", +DlnLnkMsgNoEMail : "メールアドレスを入力ã—ã¦ãã ã•ã„。", +DlnLnkMsgNoAnchor : "アンカーをé¸æŠžã—ã¦ãã ã•ã„。", +DlnLnkMsgInvPopName : "ãƒãƒƒãƒ—・アップåã¯è‹±å­—ã§å§‹ã¾ã‚‹æ–‡å­—ã§æŒ‡å®šã—ã¦ãã ã„。ãƒãƒƒãƒ—・アップåã«ã‚¹ãƒšãƒ¼ã‚¹ã¯å«ã‚ã¾ã›ã‚“", + +// Color Dialog +DlgColorTitle : "色é¸æŠž", +DlgColorBtnClear : "クリア", +DlgColorHighlight : "ãƒã‚¤ãƒ©ã‚¤ãƒˆ", +DlgColorSelected : "é¸æŠžè‰²", + +// Smiley Dialog +DlgSmileyTitle : "顔文字挿入", + +// Special Character Dialog +DlgSpecialCharTitle : "特殊文字é¸æŠž", + +// Table Dialog +DlgTableTitle : "テーブル プロパティ", +DlgTableRows : "è¡Œ", +DlgTableColumns : "列", +DlgTableBorder : "ボーダーサイズ", +DlgTableAlign : "キャプションã®æ•´åˆ—", +DlgTableAlignNotSet : "<ãªã—>", +DlgTableAlignLeft : "å·¦", +DlgTableAlignCenter : "中央", +DlgTableAlignRight : "å³", +DlgTableWidth : "テーブル幅", +DlgTableWidthPx : "ピクセル", +DlgTableWidthPc : "パーセント", +DlgTableHeight : "テーブル高ã•", +DlgTableCellSpace : "セル内余白", +DlgTableCellPad : "セル内間隔", +DlgTableCaption : "キャプショï¾", +DlgTableSummary : "テーブル目的/構造", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "セル プロパティ", +DlgCellWidth : "å¹…", +DlgCellWidthPx : "ピクセル", +DlgCellWidthPc : "パーセント", +DlgCellHeight : "高ã•", +DlgCellWordWrap : "折り返ã—", +DlgCellWordWrapNotSet : "<ãªã—>", +DlgCellWordWrapYes : "Yes", +DlgCellWordWrapNo : "No", +DlgCellHorAlign : "セル横ã®æ•´åˆ—", +DlgCellHorAlignNotSet : "<ãªã—>", +DlgCellHorAlignLeft : "å·¦", +DlgCellHorAlignCenter : "中央", +DlgCellHorAlignRight: "å³", +DlgCellVerAlign : "セル縦ã®æ•´åˆ—", +DlgCellVerAlignNotSet : "<ãªã—>", +DlgCellVerAlignTop : "上", +DlgCellVerAlignMiddle : "中央", +DlgCellVerAlignBottom : "下", +DlgCellVerAlignBaseline : "ベースライン", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "縦幅(行数)", +DlgCellCollSpan : "横幅(列数)", +DlgCellBackColor : "背景色", +DlgCellBorderColor : "ボーダーカラー", +DlgCellBtnSelect : "é¸æŠž...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "検索ã—ã¦ç½®æ›", + +// Find Dialog +DlgFindTitle : "検索", +DlgFindFindBtn : "検索", +DlgFindNotFoundMsg : "指定ã•ã‚ŒãŸæ–‡å­—列ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚", + +// Replace Dialog +DlgReplaceTitle : "ç½®ãæ›ãˆ", +DlgReplaceFindLbl : "検索ã™ã‚‹æ–‡å­—列:", +DlgReplaceReplaceLbl : "ç½®æ›ãˆã™ã‚‹æ–‡å­—列:", +DlgReplaceCaseChk : "部分一致", +DlgReplaceReplaceBtn : "ç½®æ›ãˆ", +DlgReplaceReplAllBtn : "ã™ã¹ã¦ç½®æ›ãˆ", +DlgReplaceWordChk : "å˜èªžå˜ä½ã§ä¸€è‡´", + +// Paste Operations / Dialog +PasteErrorCut : "ブラウザーã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£è¨­å®šã«ã‚ˆã‚Šã‚¨ãƒ‡ã‚£ã‚¿ã®åˆ‡ã‚Šå–ã‚Šæ“作ãŒè‡ªå‹•ã§å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。実行ã™ã‚‹ã«ã¯æ‰‹å‹•ã§ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã®(Ctrl+X)を使用ã—ã¦ãã ã•ã„。", +PasteErrorCopy : "ブラウザーã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£è¨­å®šã«ã‚ˆã‚Šã‚¨ãƒ‡ã‚£ã‚¿ã®ã‚³ãƒ”ーæ“作ãŒè‡ªå‹•ã§å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。実行ã™ã‚‹ã«ã¯æ‰‹å‹•ã§ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã®(Ctrl+C)を使用ã—ã¦ãã ã•ã„。", + +PasteAsText : "プレーンテキスト貼り付ã‘", +PasteFromWord : "ワード文章ã‹ã‚‰è²¼ã‚Šä»˜ã‘", + +DlgPasteMsg2 : "キーボード(Ctrl+V)を使用ã—ã¦ã€æ¬¡ã®å…¥åŠ›ã‚¨ãƒªã‚¢å†…ã§è²¼ã£ã¦ã€OKを押ã—ã¦ãã ã•ã„。", +DlgPasteSec : "ブラウザã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£è¨­å®šã«ã‚ˆã‚Šã€ã‚¨ãƒ‡ã‚£ã‚¿ã¯ã‚¯ãƒªãƒƒãƒ—ボード・データã«ç›´æŽ¥ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。ã“ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯è²¼ã‚Šä»˜ã‘æ“作を行ã†åº¦ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚", +DlgPasteIgnoreFont : "Fontã‚¿ã‚°ã®Face属性を無視ã—ã¾ã™ã€‚", +DlgPasteRemoveStyles : "スタイル定義を削除ã—ã¾ã™ã€‚", + +// Color Picker +ColorAutomatic : "自動", +ColorMoreColors : "ãã®ä»–ã®è‰²...", + +// Document Properties +DocProps : "文書 プロパティ", + +// Anchor Dialog +DlgAnchorTitle : "アンカー プロパティ", +DlgAnchorName : "アンカーå", +DlgAnchorErrorName : "アンカーåã‚’å¿…ãšå…¥åŠ›ã—ã¦ãã ã•ã„。", + +// Speller Pages Dialog +DlgSpellNotInDic : "辞書ã«ã‚ã‚Šã¾ã›ã‚“", +DlgSpellChangeTo : "変更", +DlgSpellBtnIgnore : "無視", +DlgSpellBtnIgnoreAll : "ã™ã¹ã¦ç„¡è¦–", +DlgSpellBtnReplace : "ç½®æ›", +DlgSpellBtnReplaceAll : "ã™ã¹ã¦ç½®æ›", +DlgSpellBtnUndo : "ã‚„ã‚Šç›´ã—", +DlgSpellNoSuggestions : "- 該当ãªã— -", +DlgSpellProgress : "スペルãƒã‚§ãƒƒã‚¯å‡¦ç†ä¸­...", +DlgSpellNoMispell : "スペルãƒã‚§ãƒƒã‚¯å®Œäº†: スペルã®èª¤ã‚Šã¯ã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸ", +DlgSpellNoChanges : "スペルãƒã‚§ãƒƒã‚¯å®Œäº†: 語å¥ã¯å¤‰æ›´ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ", +DlgSpellOneChange : "スペルãƒã‚§ãƒƒã‚¯å®Œäº†: 1語å¥å¤‰æ›´ã•ã‚Œã¾ã—ãŸ", +DlgSpellManyChanges : "スペルãƒã‚§ãƒƒã‚¯å®Œäº†: %1 語å¥å¤‰æ›´ã•ã‚Œã¾ã—ãŸ", + +IeSpellDownload : "スペルãƒã‚§ãƒƒã‚«ãƒ¼ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。今ã™ãダウンロードã—ã¾ã™ã‹?", + +// Button Dialog +DlgButtonText : "テキスト (値)", +DlgButtonType : "タイプ", +DlgButtonTypeBtn : "ボタン", +DlgButtonTypeSbm : "é€ä¿¡", +DlgButtonTypeRst : "リセット", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "åå‰", +DlgCheckboxValue : "値", +DlgCheckboxSelected : "é¸æŠžæ¸ˆã¿", + +// Form Dialog +DlgFormName : "フォームå", +DlgFormAction : "アクション", +DlgFormMethod : "メソッド", + +// Select Field Dialog +DlgSelectName : "åå‰", +DlgSelectValue : "値", +DlgSelectSize : "サイズ", +DlgSelectLines : "è¡Œ", +DlgSelectChkMulti : "複数項目é¸æŠžã‚’許å¯", +DlgSelectOpAvail : "利用å¯èƒ½ãªã‚ªãƒ—ション", +DlgSelectOpText : "é¸æŠžé …ç›®å", +DlgSelectOpValue : "é¸æŠžé …目値", +DlgSelectBtnAdd : "追加", +DlgSelectBtnModify : "編集", +DlgSelectBtnUp : "上ã¸", +DlgSelectBtnDown : "下ã¸", +DlgSelectBtnSetValue : "é¸æŠžã—ãŸå€¤ã‚’設定", +DlgSelectBtnDelete : "削除", + +// Textarea Dialog +DlgTextareaName : "åå‰", +DlgTextareaCols : "列", +DlgTextareaRows : "è¡Œ", + +// Text Field Dialog +DlgTextName : "åå‰", +DlgTextValue : "値", +DlgTextCharWidth : "サイズ", +DlgTextMaxChars : "最大長", +DlgTextType : "タイプ", +DlgTextTypeText : "テキスト", +DlgTextTypePass : "パスワード入力", + +// Hidden Field Dialog +DlgHiddenName : "åå‰", +DlgHiddenValue : "値", + +// Bulleted List Dialog +BulletedListProp : "箇æ¡æ›¸ã プロパティ", +NumberedListProp : "段è½ç•ªå· プロパティ", +DlgLstStart : "開始文字", +DlgLstType : "タイプ", +DlgLstTypeCircle : "白丸", +DlgLstTypeDisc : "黒丸", +DlgLstTypeSquare : "四角", +DlgLstTypeNumbers : "アラビア数字 (1, 2, 3)", +DlgLstTypeLCase : "英字å°æ–‡å­— (a, b, c)", +DlgLstTypeUCase : "英字大文字 (A, B, C)", +DlgLstTypeSRoman : "ローマ数字å°æ–‡å­— (i, ii, iii)", +DlgLstTypeLRoman : "ローマ数字大文字 (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "全般", +DlgDocBackTab : "背景", +DlgDocColorsTab : "色ã¨ãƒžãƒ¼ã‚¸ãƒ³", +DlgDocMetaTab : "メタデータ", + +DlgDocPageTitle : "ページタイトル", +DlgDocLangDir : "言語文字表記ã®æ–¹å‘", +DlgDocLangDirLTR : "å·¦ã‹ã‚‰å³ã«è¡¨è¨˜(LTR)", +DlgDocLangDirRTL : "å³ã‹ã‚‰å·¦ã«è¡¨è¨˜(RTL)", +DlgDocLangCode : "言語コード", +DlgDocCharSet : "文字セット符å·åŒ–", +DlgDocCharSetCE : "Central European", +DlgDocCharSetCT : "Chinese Traditional (Big5)", +DlgDocCharSetCR : "Cyrillic", +DlgDocCharSetGR : "Greek", +DlgDocCharSetJP : "Japanese", +DlgDocCharSetKR : "Korean", +DlgDocCharSetTR : "Turkish", +DlgDocCharSetUN : "Unicode (UTF-8)", +DlgDocCharSetWE : "Western European", +DlgDocCharSetOther : "ä»–ã®æ–‡å­—セット符å·åŒ–", + +DlgDocDocType : "文書タイプヘッダー", +DlgDocDocTypeOther : "ãã®ä»–文書タイプヘッダー", +DlgDocIncXHTML : "XHTML宣言をインクルード", +DlgDocBgColor : "背景色", +DlgDocBgImage : "èƒŒæ™¯ç”»åƒ URL", +DlgDocBgNoScroll : "スクロールã—ãªã„背景", +DlgDocCText : "テキスト", +DlgDocCLink : "リンク", +DlgDocCVisited : "アクセス済ã¿ãƒªãƒ³ã‚¯", +DlgDocCActive : "アクセス中リンク", +DlgDocMargins : "ページ・マージン", +DlgDocMaTop : "上部", +DlgDocMaLeft : "å·¦", +DlgDocMaRight : "å³", +DlgDocMaBottom : "下部", +DlgDocMeIndex : "文書ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰(カンマ区切り)", +DlgDocMeDescr : "文書ã®æ¦‚è¦", +DlgDocMeAuthor : "文書ã®ä½œè€…", +DlgDocMeCopy : "文書ã®è‘—作権", +DlgDocPreview : "プレビュー", + +// Templates Dialog +Templates : "テンプレート(雛形)", +DlgTemplatesTitle : "テンプレート内容", +DlgTemplatesSelMsg : "エディターã§ä½¿ç”¨ã™ã‚‹ãƒ†ãƒ³ãƒ—レートをé¸æŠžã—ã¦ãã ã•ã„。
    (ç¾åœ¨ã®ã‚¨ãƒ‡ã‚£ã‚¿ã®å†…容ã¯å¤±ã‚ã‚Œã¾ã™):", +DlgTemplatesLoading : "テンプレート一覧読ã¿è¾¼ã¿ä¸­. ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„...", +DlgTemplatesNoTpl : "(テンプレートãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“)", +DlgTemplatesReplace : "ç¾åœ¨ã®ã‚¨ãƒ‡ã‚£ã‚¿ã®å†…容ã¨ç½®æ›ãˆã‚’ã—ã¾ã™", + +// About Dialog +DlgAboutAboutTab : "ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±", +DlgAboutBrowserInfoTab : "ブラウザ情報", +DlgAboutLicenseTab : "ライセンス", +DlgAboutVersion : "ãƒãƒ¼ã‚¸ãƒ§ãƒ³", +DlgAboutInfo : "より詳ã—ã„情報ã¯ã“ã¡ã‚‰ã§", + +// Div Dialog +DlgDivGeneralTab : "全般", +DlgDivAdvancedTab : "高度ãªè¨­å®š", +DlgDivStyle : "スタイル", +DlgDivInlineStyle : "インラインスタイル", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/km.js b/www/js/FCKeditor/editor/lang/km.js new file mode 100644 index 0000000..1185388 --- /dev/null +++ b/www/js/FCKeditor/editor/lang/km.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Khmer language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "បង្រួមរបាឧបរកណáŸ", +ToolbarExpand : "ពង្រីករបាឧបរណáŸ", + +// Toolbar Items and Context Menu +Save : "រក្សាទុក", +NewPage : "ទំពáŸážšážáŸ’មី", +Preview : "មើលសាកល្បង", +Cut : "កាážáŸ‹áž™áž€", +Copy : "ចំលងយក", +Paste : "ចំលងដាក់", +PasteText : "ចំលងដាក់ជាអážáŸ’ážáž”ទធម្មážáž¶", +PasteWord : "ចំលងដាក់ពី Word", +Print : "បោះពុម្ភ", +SelectAll : "ជ្រើសរើសទាំងអស់", +RemoveFormat : "លប់ចោល ការរចនា", +InsertLinkLbl : "ឈ្នាប់", +InsertLink : "បន្ážáŸ‚ម/កែប្រែ ឈ្នាប់", +RemoveLink : "លប់ឈ្នាប់", +VisitLink : "Open Link", //MISSING +Anchor : "បន្ážáŸ‚ម/កែប្រែ យុážáŸ’កា", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "រូបភាព", +InsertImage : "បន្ážáŸ‚ម/កែប្រែ រូបភាព", +InsertFlashLbl : "Flash", +InsertFlash : "បន្ážáŸ‚ម/កែប្រែ Flash", +InsertTableLbl : "ážáž¶ážšáž¶áž„", +InsertTable : "បន្ážáŸ‚ម/កែប្រែ ážáž¶ážšáž¶áž„", +InsertLineLbl : "បន្ទាážáŸ‹", +InsertLine : "បន្ážáŸ‚មបន្ទាážáŸ‹áž•áŸ’ážáŸáž€", +InsertSpecialCharLbl: "អក្សរពិសáŸážŸ", +InsertSpecialChar : "បន្ážáŸ‚មអក្សរពិសáŸážŸ", +InsertSmileyLbl : "រូបភាព", +InsertSmiley : "បន្ážáŸ‚ម រូបភាព", +About : "អំពី FCKeditor", +Bold : "អក្សរដិážáž’ំ", +Italic : "អក្សរផ្ážáŸáž€", +Underline : "ដិážáž”ន្ទាážáŸ‹áž–ីក្រោមអក្សរ", +StrikeThrough : "ដិážáž”ន្ទាážáŸ‹áž–ាក់កណ្ážáž¶áž›áž¢áž€áŸ’សរ", +Subscript : "អក្សរážáž¼áž…ក្រោម", +Superscript : "អក្សរážáž¼áž…លើ", +LeftJustify : "ážáŸ†ážšáž¹áž˜áž†áŸ’ážœáŸáž„", +CenterJustify : "ážáŸ†ážšáž¹áž˜áž€ážŽáŸ’ážáž¶áž›", +RightJustify : "ážáŸ†ážšáž¹áž˜ážŸáŸ’ážáž¶áŸ†", +BlockJustify : "ážáŸ†ážšáž¹áž˜ážŸáž„ážáž¶áž„", +DecreaseIndent : "បន្ážáž™áž€áž¶ážšáž…ូលបន្ទាážáŸ‹", +IncreaseIndent : "បន្ážáŸ‚មការចូលបន្ទាážáŸ‹", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "សារឡើងវិញ", +Redo : "ធ្វើឡើងវិញ", +NumberedListLbl : "បញ្ជីជាអក្សរ", +NumberedList : "បន្ážáŸ‚ម/លប់ បញ្ជីជាអក្សរ", +BulletedListLbl : "បញ្ជីជារង្វង់មូល", +BulletedList : "បន្ážáŸ‚ម/លប់ បញ្ជីជារង្វង់មូល", +ShowTableBorders : "បង្ហាញស៊ុមážáž¶ážšáž¶áž„", +ShowDetails : "បង្ហាញពិស្ážáž¶ážš", +Style : "ម៉ូáž", +FontFormat : "រចនា", +Font : "ហ្វុង", +FontSize : "ទំហំ", +TextColor : "ពណ៌អក្សរ", +BGColor : "ពណ៌ផ្ទៃážáž¶áž„ក្រោយ", +Source : "កូáž", +Find : "ស្វែងរក", +Replace : "ជំនួស", +SpellCheck : "áž–áž·áž“áž·ážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធ", +UniversalKeyboard : "ក្ážáž¶ážšáž–ុម្ភអក្សរសកល", +PageBreakLbl : "ការផ្ážáž¶áž…់ទំពáŸážš", +PageBreak : "បន្ážáŸ‚ម ការផ្ážáž¶áž…់ទំពáŸážš", + +Form : "បែបបទ", +Checkbox : "ប្រអប់ជ្រើសរើស", +RadioButton : "ប៉ូážáž»áž“រង្វង់មូល", +TextField : "ជួរសរសáŸážšáž¢ážáŸ’ážáž”áž‘", +Textarea : "ážáŸ†áž”ន់សរសáŸážšáž¢ážáŸ’ážáž”áž‘", +HiddenField : "ជួរលាក់", +Button : "ប៉ូážáž»áž“", +SelectionField : "ជួរជ្រើសរើស", +ImageButton : "ប៉ូážáž»áž“រូបភាព", + +FitWindow : "Maximize the editor size", //MISSING +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "កែប្រែឈ្នាប់", +CellCM : "Cell", //MISSING +RowCM : "Row", //MISSING +ColumnCM : "Column", //MISSING +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "លប់ជួរផ្ážáŸáž€", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "លប់ជួរឈរ", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "លប់សែល", +MergeCells : "បញ្ជូលសែល", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "លប់ážáž¶ážšáž¶áž„", +CellProperties : "ការកំណážáŸ‹ážŸáŸ‚áž›", +TableProperties : "ការកំណážáŸ‹ážáž¶ážšáž¶áž„", +ImageProperties : "ការកំណážáŸ‹ážšáž¼áž”ភាព", +FlashProperties : "ការកំណážáŸ‹ Flash", + +AnchorProp : "ការកំណážáŸ‹áž™áž»ážáŸ’កា", +ButtonProp : "ការកំណážáŸ‹ ប៉ូážáž»áž“", +CheckboxProp : "ការកំណážáŸ‹áž”្រអប់ជ្រើសរើស", +HiddenFieldProp : "ការកំណážáŸ‹áž‡áž½ážšáž›áž¶áž€áŸ‹", +RadioButtonProp : "ការកំណážáŸ‹áž”៉ូážáž»áž“រង្វង់", +ImageButtonProp : "ការកំណážáŸ‹áž”៉ូážáž»áž“រូបភាព", +TextFieldProp : "ការកំណážáŸ‹áž‡áž½ážšáž¢ážáŸ’ážáž”áž‘", +SelectionFieldProp : "ការកំណážáŸ‹áž‡áž½ážšáž‡áŸ’រើសរើស", +TextareaProp : "ការកំណážáŸ‹áž€áž“្លែងសរសáŸážšáž¢ážáŸ’ážáž”áž‘", +FormProp : "ការកំណážáŸ‹áž”ែបបទ", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", + +// Alerts and Messages +ProcessingXHTML : "កំពុងដំណើរការ XHTML ។ សូមរងចាំ...", +Done : "ចប់រួចរាល់", +PasteWordConfirm : "អážáŸ’ážáž”ទដែលលោកអ្នកបំរុងចំលងដាក់ ហាក់បីដូចជាážáŸ’រូវចំលងមកពីកម្មវិធី​Word​។ ážáž¾áž›áŸ„កអ្នកចង់សំអាážáž˜áž»áž“ចំលងអážáŸ’ážáž”ទដាក់ទáŸ?", +NotCompatiblePaste : "ពាក្យបញ្ជានáŸáŸ‡áž”្រើបានážáŸ‚ជាមួយ Internet Explorer កំរិហ5.5 រឺ លើសនáŸáŸ‡ ។ ážáž¾áž›áŸ„កអ្នកចង់ចំលងដាក់ដោយមិនចាំបាច់សំអាážáž‘áŸ?", +UnknownToolbarItem : "ážœážáŸ’ážáž»áž›áž¾ážšáž”ាឧបរកណ០មិនស្គាល់ \"%1\"", +UnknownCommand : "ឈ្មោះពាក្យបញ្ជា មិនស្គាល់ \"%1\"", +NotImplemented : "ពាក្យបញ្ជា មិនបានអនុវážáŸ’áž", +UnknownToolbarSet : "របាឧបរកណ០\"%1\" ពុំមាន ។", +NoActiveX : "ការកំណážáŸ‹ážŸáž»ážœážáŸ’ážáž—ាពរបស់កម្មវិធីរុករករបស់លោកអ្នក áž“áŸáŸ‡â€‹áž¢áž¶áž…ធ្វើអោយលោកអ្នកមិនអាចប្រើមុážáž„ារážáŸ’លះរបស់កម្មវិធីážáž¶áž€áŸ‹ážáŸ‚ងអážáŸ’ážáž”áž‘áž“áŸáŸ‡ ។ លោកអ្នកážáŸ’រូវកំណážáŸ‹áž¢áŸ„áž™ \"ActiveX និង​កម្មវិធីជំនួយក្នុង (plug-ins)\" អោយដំណើរការ ។ លោកអ្នកអាចជួបប្រទះនឹង បញ្ហា ព្រមជាមួយនឹងការបាážáŸ‹áž”ង់មុážáž„ារណាមួយរបស់កម្មវិធីážáž¶áž€áŸ‹ážáŸ‚ងអážáŸ’ážáž”áž‘áž“áŸáŸ‡ ។", +BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING +DialogBlocked : "វីនដូវមិនអាចបើកបានទ០។ សូមពិនិážáŸ’យចំពោះកម្មវិធីបិទ វីនដូវលោហ(popup) ážáž¶ážáž¾ážœáž¶ážŠáŸ†ážŽáž¾ážšáž€áž¶ážšážšážºáž‘០។", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "យល់ព្រម", +DlgBtnCancel : "មិនយល់ព្រម", +DlgBtnClose : "បិទ", +DlgBtnBrowseServer : "មើល", +DlgAdvancedTag : "កំរិážážáŸ’ពស់", +DlgOpOther : "<ផ្សáŸáž„ទៅáž>", +DlgInfoTab : "áž–ážáŸŒáž˜áž¶áž“", +DlgAlertUrl : "សូមសរសáŸážš URL", + +// General Dialogs Labels +DlgGenNotSet : "<មិនមែន>", +DlgGenId : "Id", +DlgGenLangDir : "ទិសដៅភាសា", +DlgGenLangDirLtr : "ពីឆ្វáŸáž„ទៅស្ážáž¶áŸ†(LTR)", +DlgGenLangDirRtl : "ពីស្ážáž¶áŸ†áž‘ៅឆ្វáŸáž„(RTL)", +DlgGenLangCode : "áž›áŸážáž€áž¼ážáž—ាសា", +DlgGenAccessKey : "ឃី សំរាប់ចូល", +DlgGenName : "ឈ្មោះ", +DlgGenTabIndex : "áž›áŸáž Tab", +DlgGenLongDescr : "អធិប្បាយ URL វែង", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "ចំណងជើង ប្រឹក្សា", +DlgGenContType : "ប្រភáŸáž‘អážáŸ’ážáž”áž‘ ប្រឹក្សា", +DlgGenLinkCharset : "áž›áŸážáž€áž¼ážáž¢áž€áŸ’សររបស់ឈ្នាប់", +DlgGenStyle : "ម៉ូáž", + +// Image Dialog +DlgImgTitle : "ការកំណážáŸ‹ážšáž¼áž”ភាព", +DlgImgInfoTab : "áž–ážáŸŒáž˜áž¶áž“អំពីរូបភាព", +DlgImgBtnUpload : "បញ្ជូនទៅកាន់ម៉ាស៊ីនផ្ážáž›áŸ‹ážŸáŸážœáž¶", +DlgImgURL : "URL", +DlgImgUpload : "ទាញយក", +DlgImgAlt : "អážáŸ’ážáž”ទជំនួស", +DlgImgWidth : "ទទឹង", +DlgImgHeight : "កំពស់", +DlgImgLockRatio : "អážáŸ’រាឡុក", +DlgBtnResetSize : "កំណážáŸ‹áž‘ំហំឡើងវិញ", +DlgImgBorder : "ស៊ុម", +DlgImgHSpace : "គំលាážáž‘ទឹង", +DlgImgVSpace : "គំលាážáž”ណ្ážáŸ„áž™", +DlgImgAlign : "កំណážáŸ‹áž‘ីážáž¶áŸ†áž„", +DlgImgAlignLeft : "ážáž¶áž„ឆ្វង", +DlgImgAlignAbsBottom: "Abs Bottom", //MISSING +DlgImgAlignAbsMiddle: "Abs Middle", //MISSING +DlgImgAlignBaseline : "បន្ទាážáŸ‹áž‡áž¶áž˜áž¼áž›ážŠáŸ’ឋាន", +DlgImgAlignBottom : "ážáž¶áž„ក្រោម", +DlgImgAlignMiddle : "កណ្ážáž¶áž›", +DlgImgAlignRight : "ážáž¶áž„ស្ážáž¶áŸ†", +DlgImgAlignTextTop : "លើអážáŸ’ážáž”áž‘", +DlgImgAlignTop : "ážáž¶áž„លើ", +DlgImgPreview : "មើលសាកល្បង", +DlgImgAlertUrl : "សូមសរសáŸážšáž„ាសáŸáž™ážŠáŸ’ឋានរបស់រូបភាព", +DlgImgLinkTab : "ឈ្នាប់", + +// Flash Dialog +DlgFlashTitle : "ការកំណážáŸ‹ Flash", +DlgFlashChkPlay : "áž›áŸáž„ដោយស្វáŸáž™áž”្រវážáŸ’áž", +DlgFlashChkLoop : "ចំនួនដង", +DlgFlashChkMenu : "បង្ហាញ មឺនុយរបស់ Flash", +DlgFlashScale : "ទំហំ", +DlgFlashScaleAll : "បង្ហាញទាំងអស់", +DlgFlashScaleNoBorder : "មិនបង្ហាញស៊ុម", +DlgFlashScaleFit : "ážáŸ’រូវល្មម", + +// Link Dialog +DlgLnkWindowTitle : "ឈ្នាប់", +DlgLnkInfoTab : "áž–ážáŸŒáž˜áž¶áž“អំពីឈ្នាប់", +DlgLnkTargetTab : "គោលដៅ", + +DlgLnkType : "ប្រភáŸáž‘ឈ្នាប់", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "យុážáŸ’កានៅក្នុងទំពáŸážšáž“áŸáŸ‡", +DlgLnkTypeEMail : "អ៊ីមែល", +DlgLnkProto : "ប្រូážáž¼áž€áž¼áž›", +DlgLnkProtoOther : "<ផ្សáŸáž„ទៀáž>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "ជ្រើសរើសយុážáŸ’កា", +DlgLnkAnchorByName : "ážáž¶áž˜ážˆáŸ’មោះរបស់យុážáŸ’កា", +DlgLnkAnchorById : "ážáž¶áž˜ Id", +DlgLnkNoAnchors : "(No anchors available in the document)", //MISSING +DlgLnkEMail : "អ៊ីមែល", +DlgLnkEMailSubject : "ចំណងជើងអážáŸ’ážáž”áž‘", +DlgLnkEMailBody : "អážáŸ’ážáž”áž‘", +DlgLnkUpload : "ទាញយក", +DlgLnkBtnUpload : "ទាញយក", + +DlgLnkTarget : "គោលដៅ", +DlgLnkTargetFrame : "<ហ្វ្រáŸáž˜>", +DlgLnkTargetPopup : "<វីនដូវ លោáž>", +DlgLnkTargetBlank : "វីនដូវážáŸ’មី (_blank)", +DlgLnkTargetParent : "វីនដូវម០(_parent)", +DlgLnkTargetSelf : "វីនដូវដដែល (_self)", +DlgLnkTargetTop : "វីនដូវនៅលើគáŸ(_top)", +DlgLnkTargetFrameName : "ឈ្មោះហ្រ្វáŸáž˜ážŠáŸ‚លជាគោលដៅ", +DlgLnkPopWinName : "ឈ្មោះវីនដូវលោáž", +DlgLnkPopWinFeat : "លក្ážážŽáŸ‡ážšáž”ស់វីនដូលលោáž", +DlgLnkPopResize : "ទំហំអាចផ្លាស់ប្ážáž¼ážš", +DlgLnkPopLocation : "របា ទីážáž¶áŸ†áž„", +DlgLnkPopMenu : "របា មឺនុយ", +DlgLnkPopScroll : "របា ទាញ", +DlgLnkPopStatus : "របា áž–ážáŸŒáž˜áž¶áž“", +DlgLnkPopToolbar : "របា ឩបករណáŸ", +DlgLnkPopFullScrn : "អáŸáž€áŸ’រុងពáŸáž‰(IE)", +DlgLnkPopDependent : "អាស្រáŸáž™áž›áž¾ (Netscape)", +DlgLnkPopWidth : "ទទឹង", +DlgLnkPopHeight : "កំពស់", +DlgLnkPopLeft : "ទីážáž¶áŸ†áž„ážáž¶áž„ឆ្វáŸáž„", +DlgLnkPopTop : "ទីážáž¶áŸ†áž„ážáž¶áž„លើ", + +DlnLnkMsgNoUrl : "សូមសរសáŸážš អាសáŸáž™ážŠáŸ’ឋាន URL", +DlnLnkMsgNoEMail : "សូមសរសáŸážš អាសáŸáž™ážŠáŸ’ឋាន អ៊ីមែល", +DlnLnkMsgNoAnchor : "សូមជ្រើសរើស យុážáŸ’កា", +DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING + +// Color Dialog +DlgColorTitle : "ជ្រើសរើស ពណ៌", +DlgColorBtnClear : "លប់", +DlgColorHighlight : "ផាážáŸ‹áž–ណ៌", +DlgColorSelected : "បានជ្រើសរើស", + +// Smiley Dialog +DlgSmileyTitle : "បញ្ជូលរូបភាព", + +// Special Character Dialog +DlgSpecialCharTitle : "ážáž¼áž¢áž€áŸ’សរពិសáŸážŸ", + +// Table Dialog +DlgTableTitle : "ការកំណážáŸ‹ ážáž¶ážšáž¶áž„", +DlgTableRows : "ជួរផ្ážáŸáž€", +DlgTableColumns : "ជួរឈរ", +DlgTableBorder : "ទំហំស៊ុម", +DlgTableAlign : "ការកំណážáŸ‹áž‘ីážáž¶áŸ†áž„", +DlgTableAlignNotSet : "<មិនកំណážáŸ‹>", +DlgTableAlignLeft : "ážáž¶áž„ឆ្វáŸáž„", +DlgTableAlignCenter : "កណ្ážáž¶áž›", +DlgTableAlignRight : "ážáž¶áž„ស្ážáž¶áŸ†", +DlgTableWidth : "ទទឹង", +DlgTableWidthPx : "ភីកសែល", +DlgTableWidthPc : "ភាគរយ", +DlgTableHeight : "កំពស់", +DlgTableCellSpace : "គំលាážážŸáŸ‚áž›", +DlgTableCellPad : "គែមសែល", +DlgTableCaption : "ចំណងជើង", +DlgTableSummary : "សáŸáž…ក្ážáž¸ážŸáž„្ážáŸáž”", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "ការកំណážáŸ‹ សែល", +DlgCellWidth : "ទទឹង", +DlgCellWidthPx : "ភីកសែល", +DlgCellWidthPc : "ភាគរយ", +DlgCellHeight : "កំពស់", +DlgCellWordWrap : "បង្ហាញអážáŸ’ážáž”ទទាំងអស់", +DlgCellWordWrapNotSet : "<មិនកំណážáŸ‹>", +DlgCellWordWrapYes : "បាទ(ចា)", +DlgCellWordWrapNo : "áž‘áŸ", +DlgCellHorAlign : "ážáŸ†ážšáž¹áž˜áž•áŸ’ážáŸáž€", +DlgCellHorAlignNotSet : "<មិនកំណážáŸ‹>", +DlgCellHorAlignLeft : "ážáž¶áž„ឆ្វáŸáž„", +DlgCellHorAlignCenter : "កណ្ážáž¶áž›", +DlgCellHorAlignRight: "Right", //MISSING +DlgCellVerAlign : "ážáŸ†ážšáž¹áž˜ážˆážš", +DlgCellVerAlignNotSet : "<មិនកណážáŸ‹>", +DlgCellVerAlignTop : "ážáž¶áž„លើ", +DlgCellVerAlignMiddle : "កណ្ážáž¶áž›", +DlgCellVerAlignBottom : "ážáž¶áž„ក្រោម", +DlgCellVerAlignBaseline : "បន្ទាážáŸ‹áž‡áž¶áž˜áž¼áž›ážŠáŸ’ឋាន", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "បញ្ជូលជួរផ្ážáŸáž€", +DlgCellCollSpan : "បញ្ជូលជួរឈរ", +DlgCellBackColor : "ពណ៌ផ្នែកážáž¶áž„ក្រោម", +DlgCellBorderColor : "ពណ៌ស៊ុម", +DlgCellBtnSelect : "ជ្រើសរើស...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Find and Replace", //MISSING + +// Find Dialog +DlgFindTitle : "ស្វែងរក", +DlgFindFindBtn : "ស្វែងរក", +DlgFindNotFoundMsg : "ពាក្យនáŸáŸ‡ រកមិនឃើញទ០។", + +// Replace Dialog +DlgReplaceTitle : "ជំនួស", +DlgReplaceFindLbl : "ស្វែងរកអ្វី:", +DlgReplaceReplaceLbl : "ជំនួសជាមួយ:", +DlgReplaceCaseChk : "ករណ៉ážáŸ’រូវរក", +DlgReplaceReplaceBtn : "ជំនួស", +DlgReplaceReplAllBtn : "ជំនួសទាំងអស់", +DlgReplaceWordChk : "ážáŸ’រូវពាក្យទាំងអស់", + +// Paste Operations / Dialog +PasteErrorCut : "ការកំណážáŸ‹ážŸáž»ážœážáŸ’ážáž—ាពរបស់កម្មវិធីរុករករបស់លោកអ្នក áž“áŸáŸ‡â€‹áž˜áž·áž“អាចធ្វើកម្មវិធីážáž¶áž€áŸ‹ážáŸ‚ងអážáŸ’ážáž”áž‘ កាážáŸ‹áž¢ážáŸ’ážáž”ទយកដោយស្វáŸáž™áž”្រវážáŸ’ážáž”ានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនáŸáŸ‡ (Ctrl+X) ។", +PasteErrorCopy : "ការកំណážáŸ‹ážŸáž»ážœážáŸ’ážáž—ាពរបស់កម្មវិធីរុករករបស់លោកអ្នក áž“áŸáŸ‡â€‹áž˜áž·áž“អាចធ្វើកម្មវិធីážáž¶áž€áŸ‹ážáŸ‚ងអážáŸ’ážáž”áž‘ ចំលងអážáŸ’ážáž”ទយកដោយស្វáŸáž™áž”្រវážáŸ’ážáž”ានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនáŸáŸ‡ (Ctrl+C)។", + +PasteAsText : "ចំលងដាក់អážáŸ’ážáž”ទធម្មážáž¶", +PasteFromWord : "ចំលងពាក្យពីកម្មវិធី Word", + +DlgPasteMsg2 : "សូមចំលងអážáŸ’ážáž”ទទៅដាក់ក្នុងប្រអប់ដូចážáž¶áž„ក្រោមដោយប្រើប្រាស់ ឃី ​(Ctrl+V) ហើយចុច OK ។", +DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING +DlgPasteIgnoreFont : "មិនគិážáž¢áŸ†áž–ីប្រភáŸáž‘ពុម្ភអក្សរ", +DlgPasteRemoveStyles : "លប់ម៉ូáž", + +// Color Picker +ColorAutomatic : "ស្វáŸáž™áž”្រវážáŸ’áž", +ColorMoreColors : "ពណ៌ផ្សáŸáž„ទៀáž..", + +// Document Properties +DocProps : "ការកំណážáŸ‹ ឯកសារ", + +// Anchor Dialog +DlgAnchorTitle : "ការកំណážáŸ‹áž…ំណងជើងយុទ្ធážáŸ’កា", +DlgAnchorName : "ឈ្មោះយុទ្ធážáŸ’កា", +DlgAnchorErrorName : "សូមសរសáŸážš ឈ្មោះយុទ្ធážáŸ’កា", + +// Speller Pages Dialog +DlgSpellNotInDic : "គ្មានក្នុងវចនានុក្រម", +DlgSpellChangeTo : "ផ្លាស់ប្ážáž¼ážšáž‘ៅ", +DlgSpellBtnIgnore : "មិនផ្លាស់ប្ážáž¼ážš", +DlgSpellBtnIgnoreAll : "មិនផ្លាស់ប្ážáž¼ážš ទាំងអស់", +DlgSpellBtnReplace : "ជំនួស", +DlgSpellBtnReplaceAll : "ជំនួសទាំងអស់", +DlgSpellBtnUndo : "សារឡើងវិញ", +DlgSpellNoSuggestions : "- គ្មានសំណើរ -", +DlgSpellProgress : "កំពុងពិនិážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធ...", +DlgSpellNoMispell : "ការពិនិážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធបានចប់: គ្មានកំហុស", +DlgSpellNoChanges : "ការពិនិážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធបានចប់: ពុំមានផ្លាស់ប្ážáž¼ážš", +DlgSpellOneChange : "ការពិនិážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធបានចប់: ពាក្យមួយážáŸ’រូចបានផ្លាស់ប្ážáž¼ážš", +DlgSpellManyChanges : "ការពិនិážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធបានចប់: %1 ពាក្យបានផ្លាស់ប្ážáž¼ážš", + +IeSpellDownload : "ពុំមានកម្មវិធីពិនិážáŸ’យអក្ážážšáž¶ážœáž·ážšáž»áž‘្ធ ។ ážáž¾áž…ង់ទាញយកពីណា?", + +// Button Dialog +DlgButtonText : "អážáŸ’ážáž”áž‘(ážáŸ†áž›áŸƒ)", +DlgButtonType : "ប្រភáŸáž‘", +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "ឈ្មោះ", +DlgCheckboxValue : "ážáŸ†áž›áŸƒ", +DlgCheckboxSelected : "បានជ្រើសរើស", + +// Form Dialog +DlgFormName : "ឈ្មោះ", +DlgFormAction : "សកម្មភាព", +DlgFormMethod : "វិធី", + +// Select Field Dialog +DlgSelectName : "ឈ្មោះ", +DlgSelectValue : "ážáŸ†áž›áŸƒ", +DlgSelectSize : "ទំហំ", +DlgSelectLines : "បន្ទាážáŸ‹", +DlgSelectChkMulti : "អនុញ្ញាážáž¢áŸ„យជ្រើសរើសច្រើន", +DlgSelectOpAvail : "ការកំណážáŸ‹áž‡áŸ’រើសរើស ដែលអាចកំណážáŸ‹áž”ាន", +DlgSelectOpText : "ពាក្យ", +DlgSelectOpValue : "ážáŸ†áž›áŸƒ", +DlgSelectBtnAdd : "បន្ážáŸ‚ម", +DlgSelectBtnModify : "ផ្លាស់ប្ážáž¼ážš", +DlgSelectBtnUp : "លើ", +DlgSelectBtnDown : "ក្រោម", +DlgSelectBtnSetValue : "Set as selected value", //MISSING +DlgSelectBtnDelete : "លប់", + +// Textarea Dialog +DlgTextareaName : "ឈ្មោះ", +DlgTextareaCols : "ជូរឈរ", +DlgTextareaRows : "ជូរផ្ážáŸáž€", + +// Text Field Dialog +DlgTextName : "ឈ្មោះ", +DlgTextValue : "ážáŸ†áž›áŸƒ", +DlgTextCharWidth : "ទទឹង អក្សរ", +DlgTextMaxChars : "អក្សរអážáž·áž”រិមា", +DlgTextType : "ប្រភáŸáž‘", +DlgTextTypeText : "ពាក្យ", +DlgTextTypePass : "ពាក្យសំងាážáŸ‹", + +// Hidden Field Dialog +DlgHiddenName : "ឈ្មោះ", +DlgHiddenValue : "ážáŸ†áž›áŸƒ", + +// Bulleted List Dialog +BulletedListProp : "កំណážáŸ‹áž”ញ្ជីរង្វង់", +NumberedListProp : "កំណážáŸ‹áž”ញ្áŸáž‡áž¸áž›áŸáž", +DlgLstStart : "Start", //MISSING +DlgLstType : "ប្រភáŸáž‘", +DlgLstTypeCircle : "រង្វង់", +DlgLstTypeDisc : "Disc", +DlgLstTypeSquare : "ការáŸ", +DlgLstTypeNumbers : "áž›áŸáž(1, 2, 3)", +DlgLstTypeLCase : "អក្សរážáž¼áž…(a, b, c)", +DlgLstTypeUCase : "អក្សរធំ(A, B, C)", +DlgLstTypeSRoman : "អក្សរឡាážáž¶áŸ†áž„ážáž¼áž…(i, ii, iii)", +DlgLstTypeLRoman : "អក្សរឡាážáž¶áŸ†áž„ធំ(I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "ទូទៅ", +DlgDocBackTab : "ផ្នែកážáž¶áž„ក្រោយ", +DlgDocColorsTab : "ទំពáŸážšâ€‹áž“áž·áž„ ស៊ុម", +DlgDocMetaTab : "ទិន្ននáŸáž™áž˜áŸ", + +DlgDocPageTitle : "ចំណងជើងទំពáŸážš", +DlgDocLangDir : "ទិសដៅសរសáŸážšáž—ាសា", +DlgDocLangDirLTR : "ពីឆ្វáŸáž„ទៅស្ដាំ(LTR)", +DlgDocLangDirRTL : "ពីស្ដាំទៅឆ្វáŸáž„(RTL)", +DlgDocLangCode : "áž›áŸážáž€áž¼ážáž—ាសា", +DlgDocCharSet : "កំណážáŸ‹áž›áŸážáž€áž¼ážáž—ាសា", +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "កំណážáŸ‹áž›áŸážáž€áž¼ážáž—ាសាផ្សáŸáž„ទៀáž", + +DlgDocDocType : "ប្រភáŸáž‘ក្បាលទំពáŸážš", +DlgDocDocTypeOther : "ប្រភáŸáž‘ក្បាលទំពáŸážšáž•áŸ’សáŸáž„ទៀáž", +DlgDocIncXHTML : "បញ្ជូល XHTML", +DlgDocBgColor : "ពណ៌ážáž¶áž„ក្រោម", +DlgDocBgImage : "URL របស់រូបភាពážáž¶áž„ក្រោម", +DlgDocBgNoScroll : "ទំពáŸážšáž€áŸ’រោមមិនប្ážáž¼ážš", +DlgDocCText : "អážáŸ’ážáž”áž‘", +DlgDocCLink : "ឈ្នាប់", +DlgDocCVisited : "ឈ្នាប់មើលហើយ", +DlgDocCActive : "ឈ្នាប់កំពុងមើល", +DlgDocMargins : "ស៊ុមទំពáŸážš", +DlgDocMaTop : "លើ", +DlgDocMaLeft : "ឆ្វáŸáž„", +DlgDocMaRight : "ស្ដាំ", +DlgDocMaBottom : "ក្រោម", +DlgDocMeIndex : "ពាក្យនៅក្នុងឯកសារ (ផ្ážáž¶áž…់ពីគ្នាដោយក្បៀស)", +DlgDocMeDescr : "សáŸáž…ក្ážáž¸áž¢ážáŸ’ážáž¶áž’ិប្បាយអំពីឯកសារ", +DlgDocMeAuthor : "អ្នកនិពន្ធ", +DlgDocMeCopy : "រក្សាសិទ្ធិáŸ", +DlgDocPreview : "មើលសាកល្បង", + +// Templates Dialog +Templates : "ឯកសារគំរូ", +DlgTemplatesTitle : "ឯកសារគំរូ របស់អážáŸ’ážáž“áŸáž™", +DlgTemplatesSelMsg : "សូមជ្រើសរើសឯកសារគំរូ ដើម្បីបើកនៅក្នុងកម្មវិធីážáž¶áž€áŸ‹ážáŸ‚ងអážáŸ’ážáž”áž‘
    (អážáŸ’ážáž”ទនឹងបាážáŸ‹áž”ង់):", +DlgTemplatesLoading : "កំពុងអានបញ្ជីឯកសារគំរូ ។ សូមរងចាំ...", +DlgTemplatesNoTpl : "(ពុំមានឯកសារគំរូážáŸ’រូវបានកំណážáŸ‹)", +DlgTemplatesReplace : "Replace actual contents", //MISSING + +// About Dialog +DlgAboutAboutTab : "អំពី", +DlgAboutBrowserInfoTab : "ព៌ážáž˜áž¶áž“កម្មវិធីរុករក", +DlgAboutLicenseTab : "License", //MISSING +DlgAboutVersion : "ជំនាន់", +DlgAboutInfo : "សំរាប់ព៌ážáž˜áž¶áž“ផ្សáŸáž„ទៀហសូមទាក់ទង", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/ko.js b/www/js/FCKeditor/editor/lang/ko.js new file mode 100644 index 0000000..6bc49ce --- /dev/null +++ b/www/js/FCKeditor/editor/lang/ko.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Korean language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "툴바 ê°ì¶”기", +ToolbarExpand : "툴바 ë³´ì´ê¸°", + +// Toolbar Items and Context Menu +Save : "저장하기", +NewPage : "새 문서", +Preview : "미리보기", +Cut : "잘ë¼ë‚´ê¸°", +Copy : "복사하기", +Paste : "붙여넣기", +PasteText : "í…스트로 붙여넣기", +PasteWord : "MS Word 형ì‹ì—ì„œ 붙여넣기", +Print : "ì¸ì‡„하기", +SelectAll : "ì „ì²´ì„ íƒ", +RemoveFormat : "í¬ë§· 지우기", +InsertLinkLbl : "ë§í¬", +InsertLink : "ë§í¬ 삽입/변경", +RemoveLink : "ë§í¬ ì‚­ì œ", +VisitLink : "Open Link", //MISSING +Anchor : "책갈피 삽입/변경", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "ì´ë¯¸ì§€", +InsertImage : "ì´ë¯¸ì§€ 삽입/변경", +InsertFlashLbl : "플래쉬", +InsertFlash : "플래쉬 삽입/변경", +InsertTableLbl : "í‘œ", +InsertTable : "í‘œ 삽입/변경", +InsertLineLbl : "수í‰ì„ ", +InsertLine : "수í‰ì„  삽입", +InsertSpecialCharLbl: "íŠ¹ìˆ˜ë¬¸ìž ì‚½ìž…", +InsertSpecialChar : "íŠ¹ìˆ˜ë¬¸ìž ì‚½ìž…", +InsertSmileyLbl : "ì•„ì´ì½˜", +InsertSmiley : "ì•„ì´ì½˜ 삽입", +About : "FCKeditorì— ëŒ€í•˜ì—¬", +Bold : "진하게", +Italic : "ì´í…”릭", +Underline : "밑줄", +StrikeThrough : "취소선", +Subscript : "아래 첨ìž", +Superscript : "위 첨ìž", +LeftJustify : "왼쪽 ì •ë ¬", +CenterJustify : "ê°€ìš´ë° ì •ë ¬", +RightJustify : "오른쪽 ì •ë ¬", +BlockJustify : "양쪽 맞춤", +DecreaseIndent : "내어쓰기", +IncreaseIndent : "들여쓰기", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "취소", +Redo : "재실행", +NumberedListLbl : "순서있는 목ë¡", +NumberedList : "순서있는 목ë¡", +BulletedListLbl : "순서없는 목ë¡", +BulletedList : "순서없는 목ë¡", +ShowTableBorders : "í‘œ í…Œë‘리 보기", +ShowDetails : "문서기호 보기", +Style : "스타ì¼", +FontFormat : "í¬ë§·", +Font : "í°íŠ¸", +FontSize : "ê¸€ìž í¬ê¸°", +TextColor : "ê¸€ìž ìƒ‰ìƒ", +BGColor : "ë°°ê²½ 색ìƒ", +Source : "소스", +Find : "찾기", +Replace : "바꾸기", +SpellCheck : "ì² ìžê²€ì‚¬", +UniversalKeyboard : "다국어 입력기", +PageBreakLbl : "Page Break", //MISSING +PageBreak : "Insert Page Break", //MISSING + +Form : "í¼", +Checkbox : "ì²´í¬ë°•ìŠ¤", +RadioButton : "ë¼ë””오버튼", +TextField : "입력필드", +Textarea : "ìž…ë ¥ì˜ì—­", +HiddenField : "숨김필드", +Button : "버튼", +SelectionField : "펼침목ë¡", +ImageButton : "ì´ë¯¸ì§€ë²„튼", + +FitWindow : "ì—디터 최대화", +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "ë§í¬ 수정", +CellCM : "ì…€/칸(Cell)", +RowCM : "í–‰(Row)", +ColumnCM : "ì—´(Column)", +InsertRowAfter : "ë’¤ì— í–‰ 삽입", +InsertRowBefore : "ì•žì— í–‰ 삽입", +DeleteRows : "가로줄 ì‚­ì œ", +InsertColumnAfter : "ë’¤ì— ì—´ 삽입", +InsertColumnBefore : "ì•žì— ì—´ 삽입", +DeleteColumns : "세로줄 ì‚­ì œ", +InsertCellAfter : "ë’¤ì— ì…€/칸 삽입", +InsertCellBefore : "ì•žì— ì…€/칸 삽입", +DeleteCells : "ì…€ ì‚­ì œ", +MergeCells : "ì…€ 합치기", +MergeRight : "오른쪽 뭉치기", +MergeDown : "왼쪽 뭉치기", +HorizontalSplitCell : "ìˆ˜í‰ ë‚˜ëˆ„ê¸°", +VerticalSplitCell : "ìˆ˜ì§ ë‚˜ëˆ„ê¸°", +TableDelete : "í‘œ ì‚­ì œ", +CellProperties : "ì…€ ì†ì„±", +TableProperties : "í‘œ ì†ì„±", +ImageProperties : "ì´ë¯¸ì§€ ì†ì„±", +FlashProperties : "플래쉬 ì†ì„±", + +AnchorProp : "책갈피 ì†ì„±", +ButtonProp : "버튼 ì†ì„±", +CheckboxProp : "ì²´í¬ë°•ìŠ¤ ì†ì„±", +HiddenFieldProp : "숨김필드 ì†ì„±", +RadioButtonProp : "ë¼ë””오버튼 ì†ì„±", +ImageButtonProp : "ì´ë¯¸ì§€ë²„튼 ì†ì„±", +TextFieldProp : "입력필드 ì†ì„±", +SelectionFieldProp : "íŽ¼ì¹¨ëª©ë¡ ì†ì„±", +TextareaProp : "ìž…ë ¥ì˜ì—­ ì†ì„±", +FormProp : "í¼ ì†ì„±", + +FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6", + +// Alerts and Messages +ProcessingXHTML : "XHTML 처리중. 잠시만 기다려주십시요.", +Done : "완료", +PasteWordConfirm : "붙여넣기 í•  í…스트는 MS Wordì—ì„œ 복사한 것입니다. 붙여넣기 ì „ì— MS Word í¬ë©§ì„ 삭제하시겠습니까?", +NotCompatiblePaste : "ì´ ëª…ë ¹ì€ ì¸í„°ë„·ìµìŠ¤í”Œë¡œëŸ¬ 5.5 버전 ì´ìƒì—서만 ìž‘ë™í•©ë‹ˆë‹¤. í¬ë©§ì„ 삭제하지 ì•Šê³  붙여넣기 하시겠습니까?", +UnknownToolbarItem : "알수없는 툴바입니다. : \"%1\"", +UnknownCommand : "알수없는 기능입니다. : \"%1\"", +NotImplemented : "ê¸°ëŠ¥ì´ ì‹¤í–‰ë˜ì§€ 않았습니다.", +UnknownToolbarSet : "툴바 ì„¤ì •ì´ ì—†ìŠµë‹ˆë‹¤. : \"%1\"", +NoActiveX : "ë¸ŒëŸ¬ìš°ì €ì˜ ë³´ì•ˆ 설정으로 ì¸í•´ 몇몇 ê¸°ëŠ¥ì˜ ìž‘ë™ì— 장애가 ìžˆì„ ìˆ˜ 있습니다. \"액티브-액스 기능과 플러그 ì¸\" ì˜µì…˜ì„ í—ˆìš©í•˜ì—¬ 주시지 않으면 오류가 ë°œìƒí•  수 있습니다.", +BrowseServerBlocked : "브러우저 요소가 열리지 않습니다. íŒì—…차단 ì„¤ì •ì´ êº¼ì ¸ìžˆëŠ”ì§€ 확ì¸í•˜ì—¬ 주십시오.", +DialogBlocked : "윈ë„ìš° ëŒ€í™”ì°½ì„ ì—´ 수 없습니다. íŒì—…차단 ì„¤ì •ì´ êº¼ì ¸ìžˆëŠ”ì§€ 확ì¸í•˜ì—¬ 주십시오.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "예", +DlgBtnCancel : "아니오", +DlgBtnClose : "닫기", +DlgBtnBrowseServer : "서버 보기", +DlgAdvancedTag : "ìžì„¸ížˆ", +DlgOpOther : "<기타>", +DlgInfoTab : "ì •ë³´", +DlgAlertUrl : "URLì„ ìž…ë ¥í•˜ì‹­ì‹œìš”", + +// General Dialogs Labels +DlgGenNotSet : "<설정ë˜ì§€ ì•ŠìŒ>", +DlgGenId : "ID", +DlgGenLangDir : "쓰기 ë°©í–¥", +DlgGenLangDirLtr : "왼쪽ì—ì„œ 오른쪽 (LTR)", +DlgGenLangDirRtl : "오른쪽ì—ì„œ 왼쪽 (RTL)", +DlgGenLangCode : "언어 코드", +DlgGenAccessKey : "엑세스 키", +DlgGenName : "Name", +DlgGenTabIndex : "탭 순서", +DlgGenLongDescr : "URL 설명", +DlgGenClass : "Stylesheet Classes", +DlgGenTitle : "Advisory Title", +DlgGenContType : "Advisory Content Type", +DlgGenLinkCharset : "Linked Resource Charset", +DlgGenStyle : "Style", + +// Image Dialog +DlgImgTitle : "ì´ë¯¸ì§€ 설정", +DlgImgInfoTab : "ì´ë¯¸ì§€ ì •ë³´", +DlgImgBtnUpload : "서버로 전송", +DlgImgURL : "URL", +DlgImgUpload : "업로드", +DlgImgAlt : "ì´ë¯¸ì§€ 설명", +DlgImgWidth : "너비", +DlgImgHeight : "높ì´", +DlgImgLockRatio : "비율 유지", +DlgBtnResetSize : "ì›ëž˜ í¬ê¸°ë¡œ", +DlgImgBorder : "í…Œë‘리", +DlgImgHSpace : "수í‰ì—¬ë°±", +DlgImgVSpace : "수ì§ì—¬ë°±", +DlgImgAlign : "ì •ë ¬", +DlgImgAlignLeft : "왼쪽", +DlgImgAlignAbsBottom: "줄아래(Abs Bottom)", +DlgImgAlignAbsMiddle: "줄중간(Abs Middle)", +DlgImgAlignBaseline : "기준선", +DlgImgAlignBottom : "아래", +DlgImgAlignMiddle : "중간", +DlgImgAlignRight : "오른쪽", +DlgImgAlignTextTop : "글ìžìƒë‹¨", +DlgImgAlignTop : "위", +DlgImgPreview : "미리보기", +DlgImgAlertUrl : "ì´ë¯¸ì§€ URLì„ ìž…ë ¥í•˜ì‹­ì‹œìš”", +DlgImgLinkTab : "ë§í¬", + +// Flash Dialog +DlgFlashTitle : "플래쉬 등ë¡ì •ë³´", +DlgFlashChkPlay : "ìžë™ìž¬ìƒ", +DlgFlashChkLoop : "반복", +DlgFlashChkMenu : "플래쉬메뉴 가능", +DlgFlashScale : "ì˜ì—­", +DlgFlashScaleAll : "모ë‘보기", +DlgFlashScaleNoBorder : "경계선없ìŒ", +DlgFlashScaleFit : "ì˜ì—­ìžë™ì¡°ì ˆ", + +// Link Dialog +DlgLnkWindowTitle : "ë§í¬", +DlgLnkInfoTab : "ë§í¬ ì •ë³´", +DlgLnkTargetTab : "타겟", + +DlgLnkType : "ë§í¬ 종류", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "책갈피", +DlgLnkTypeEMail : "ì´ë©”ì¼", +DlgLnkProto : "프로토콜", +DlgLnkProtoOther : "<기타>", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "책갈피 ì„ íƒ", +DlgLnkAnchorByName : "책갈피 ì´ë¦„", +DlgLnkAnchorById : "책갈피 ID", +DlgLnkNoAnchors : "(ë¬¸ì„œì— ì±…ê°ˆí”¼ê°€ 없습니다.)", +DlgLnkEMail : "ì´ë©”ì¼ ì£¼ì†Œ", +DlgLnkEMailSubject : "제목", +DlgLnkEMailBody : "ë‚´ìš©", +DlgLnkUpload : "업로드", +DlgLnkBtnUpload : "서버로 전송", + +DlgLnkTarget : "타겟", +DlgLnkTargetFrame : "<프레임>", +DlgLnkTargetPopup : "<íŒì—…ì°½>", +DlgLnkTargetBlank : "새 ì°½ (_blank)", +DlgLnkTargetParent : "부모 ì°½ (_parent)", +DlgLnkTargetSelf : "현재 ì°½ (_self)", +DlgLnkTargetTop : "최 ìƒìœ„ ì°½ (_top)", +DlgLnkTargetFrameName : "타겟 프레임 ì´ë¦„", +DlgLnkPopWinName : "íŒì—…ì°½ ì´ë¦„", +DlgLnkPopWinFeat : "íŒì—…ì°½ 설정", +DlgLnkPopResize : "í¬ê¸°ì¡°ì •", +DlgLnkPopLocation : "주소표시줄", +DlgLnkPopMenu : "메뉴바", +DlgLnkPopScroll : "스í¬ë¡¤ë°”", +DlgLnkPopStatus : "ìƒíƒœë°”", +DlgLnkPopToolbar : "툴바", +DlgLnkPopFullScrn : "전체화면 (IE)", +DlgLnkPopDependent : "Dependent (Netscape)", +DlgLnkPopWidth : "너비", +DlgLnkPopHeight : "높ì´", +DlgLnkPopLeft : "왼쪽 위치", +DlgLnkPopTop : "윗쪽 위치", + +DlnLnkMsgNoUrl : "ë§í¬ URLì„ ìž…ë ¥í•˜ì‹­ì‹œìš”.", +DlnLnkMsgNoEMail : "ì´ë©”ì¼ì£¼ì†Œë¥¼ 입력하십시요.", +DlnLnkMsgNoAnchor : "ì±…ê°ˆí”¼ëª…ì„ ìž…ë ¥í•˜ì‹­ì‹œìš”.", +DlnLnkMsgInvPopName : "íŒì—…ì°½ì˜ íƒ€ì´í‹€ì€ ê³µë°±ì„ í—ˆìš©í•˜ì§€ 않습니다.", + +// Color Dialog +DlgColorTitle : "ìƒ‰ìƒ ì„ íƒ", +DlgColorBtnClear : "지우기", +DlgColorHighlight : "현재", +DlgColorSelected : "ì„ íƒë¨", + +// Smiley Dialog +DlgSmileyTitle : "ì•„ì´ì½˜ 삽입", + +// Special Character Dialog +DlgSpecialCharTitle : "íŠ¹ìˆ˜ë¬¸ìž ì„ íƒ", + +// Table Dialog +DlgTableTitle : "í‘œ 설정", +DlgTableRows : "가로줄", +DlgTableColumns : "세로줄", +DlgTableBorder : "í…Œë‘리 í¬ê¸°", +DlgTableAlign : "ì •ë ¬", +DlgTableAlignNotSet : "<설정ë˜ì§€ ì•ŠìŒ>", +DlgTableAlignLeft : "왼쪽", +DlgTableAlignCenter : "가운ë°", +DlgTableAlignRight : "오른쪽", +DlgTableWidth : "너비", +DlgTableWidthPx : "픽셀", +DlgTableWidthPc : "í¼ì„¼íŠ¸", +DlgTableHeight : "높ì´", +DlgTableCellSpace : "ì…€ 간격", +DlgTableCellPad : "ì…€ 여백", +DlgTableCaption : "캡션", +DlgTableSummary : "요약", +DlgTableHeaders : "Headers", //MISSING +DlgTableHeadersNone : "None", //MISSING +DlgTableHeadersColumn : "First column", //MISSING +DlgTableHeadersRow : "First Row", //MISSING +DlgTableHeadersBoth : "Both", //MISSING + +// Table Cell Dialog +DlgCellTitle : "ì…€ 설정", +DlgCellWidth : "너비", +DlgCellWidthPx : "픽셀", +DlgCellWidthPc : "í¼ì„¼íŠ¸", +DlgCellHeight : "높ì´", +DlgCellWordWrap : "워드랩", +DlgCellWordWrapNotSet : "<설정ë˜ì§€ ì•ŠìŒ>", +DlgCellWordWrapYes : "예", +DlgCellWordWrapNo : "아니오", +DlgCellHorAlign : "ìˆ˜í‰ ì •ë ¬", +DlgCellHorAlignNotSet : "<설정ë˜ì§€ ì•ŠìŒ>", +DlgCellHorAlignLeft : "왼쪽", +DlgCellHorAlignCenter : "가운ë°", +DlgCellHorAlignRight: "오른쪽", +DlgCellVerAlign : "ìˆ˜ì§ ì •ë ¬", +DlgCellVerAlignNotSet : "<설정ë˜ì§€ ì•ŠìŒ>", +DlgCellVerAlignTop : "위", +DlgCellVerAlignMiddle : "중간", +DlgCellVerAlignBottom : "아래", +DlgCellVerAlignBaseline : "기준선", +DlgCellType : "Cell Type", //MISSING +DlgCellTypeData : "Data", //MISSING +DlgCellTypeHeader : "Header", //MISSING +DlgCellRowSpan : "세로 합치기", +DlgCellCollSpan : "가로 합치기", +DlgCellBackColor : "ë°°ê²½ 색ìƒ", +DlgCellBorderColor : "í…Œë‘리 색ìƒ", +DlgCellBtnSelect : "ì„ íƒ", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "찾기 & 바꾸기", + +// Find Dialog +DlgFindTitle : "찾기", +DlgFindFindBtn : "찾기", +DlgFindNotFoundMsg : "문ìžì—´ì„ ì°¾ì„ ìˆ˜ 없습니다.", + +// Replace Dialog +DlgReplaceTitle : "바꾸기", +DlgReplaceFindLbl : "ì°¾ì„ ë¬¸ìžì—´:", +DlgReplaceReplaceLbl : "바꿀 문ìžì—´:", +DlgReplaceCaseChk : "ëŒ€ì†Œë¬¸ìž êµ¬ë¶„", +DlgReplaceReplaceBtn : "바꾸기", +DlgReplaceReplAllBtn : "ëª¨ë‘ ë°”ê¾¸ê¸°", +DlgReplaceWordChk : "온전한 단어", + +// Paste Operations / Dialog +PasteErrorCut : "브ë¼ìš°ì €ì˜ ë³´ì•ˆì„¤ì •ë•Œë¬¸ì— ìž˜ë¼ë‚´ê¸° ê¸°ëŠ¥ì„ ì‹¤í–‰í•  수 없습니다. 키보드 ëª…ë ¹ì„ ì‚¬ìš©í•˜ì‹­ì‹œìš”. (Ctrl+X).", +PasteErrorCopy : "브ë¼ìš°ì €ì˜ ë³´ì•ˆì„¤ì •ë•Œë¬¸ì— ë³µì‚¬í•˜ê¸° ê¸°ëŠ¥ì„ ì‹¤í–‰í•  수 없습니다. 키보드 ëª…ë ¹ì„ ì‚¬ìš©í•˜ì‹­ì‹œìš”. (Ctrl+C).", + +PasteAsText : "í…스트로 붙여넣기", +PasteFromWord : "MS Word 형ì‹ì—ì„œ 붙여넣기", + +DlgPasteMsg2 : "í‚¤ë³´ë“œì˜ (Ctrl+V) 를 ì´ìš©í•´ì„œ ìƒìžì•ˆì— 붙여넣고 OK 를 누르세요.", +DlgPasteSec : "브러우저 보안 설정으로 ì¸í•´, í´ë¦½ë³´ë“œì˜ ìžë£Œë¥¼ ì§ì ‘ 접근할 수 없습니다. ì´ ì°½ì— ë‹¤ì‹œ 붙여넣기 하십시오.", +DlgPasteIgnoreFont : "í°íŠ¸ 설정 무시", +DlgPasteRemoveStyles : "ìŠ¤íƒ€ì¼ ì •ì˜ ì œê±°", + +// Color Picker +ColorAutomatic : "기본색ìƒ", +ColorMoreColors : "색ìƒì„ íƒ...", + +// Document Properties +DocProps : "문서 ì†ì„±", + +// Anchor Dialog +DlgAnchorTitle : "책갈피 ì†ì„±", +DlgAnchorName : "책갈피 ì´ë¦„", +DlgAnchorErrorName : "책갈피 ì´ë¦„ì„ ìž…ë ¥í•˜ì‹­ì‹œìš”.", + +// Speller Pages Dialog +DlgSpellNotInDic : "ì‚¬ì „ì— ì—†ëŠ” 단어", +DlgSpellChangeTo : "변경할 단어", +DlgSpellBtnIgnore : "건너뜀", +DlgSpellBtnIgnoreAll : "ëª¨ë‘ ê±´ë„ˆëœ€", +DlgSpellBtnReplace : "변경", +DlgSpellBtnReplaceAll : "ëª¨ë‘ ë³€ê²½", +DlgSpellBtnUndo : "취소", +DlgSpellNoSuggestions : "- 추천단어 ì—†ìŒ -", +DlgSpellProgress : "ì² ìžê²€ì‚¬ë¥¼ 진행중입니다...", +DlgSpellNoMispell : "ì² ìžê²€ì‚¬ 완료: ìž˜ëª»ëœ ì² ìžê°€ 없습니다.", +DlgSpellNoChanges : "ì² ìžê²€ì‚¬ 완료: ë³€ê²½ëœ ë‹¨ì–´ê°€ 없습니다.", +DlgSpellOneChange : "ì² ìžê²€ì‚¬ 완료: 단어가 변경ë˜ì—ˆìŠµë‹ˆë‹¤.", +DlgSpellManyChanges : "ì² ìžê²€ì‚¬ 완료: %1 단어가 변경ë˜ì—ˆìŠµë‹ˆë‹¤.", + +IeSpellDownload : "ì² ìž ê²€ì‚¬ê¸°ê°€ 철치ë˜ì§€ 않았습니다. 지금 다운로드하시겠습니까?", + +// Button Dialog +DlgButtonText : "버튼글ìž(ê°’)", +DlgButtonType : "버튼종류", +DlgButtonTypeBtn : "Button", //MISSING +DlgButtonTypeSbm : "Submit", //MISSING +DlgButtonTypeRst : "Reset", //MISSING + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "ì´ë¦„", +DlgCheckboxValue : "ê°’", +DlgCheckboxSelected : "ì„ íƒë¨", + +// Form Dialog +DlgFormName : "í¼ì´ë¦„", +DlgFormAction : "실행경로(Action)", +DlgFormMethod : "방법(Method)", + +// Select Field Dialog +DlgSelectName : "ì´ë¦„", +DlgSelectValue : "ê°’", +DlgSelectSize : "세로í¬ê¸°", +DlgSelectLines : "줄", +DlgSelectChkMulti : "여러항목 ì„ íƒ í—ˆìš©", +DlgSelectOpAvail : "ì„ íƒì˜µì…˜", +DlgSelectOpText : "ì´ë¦„", +DlgSelectOpValue : "ê°’", +DlgSelectBtnAdd : "추가", +DlgSelectBtnModify : "변경", +DlgSelectBtnUp : "위로", +DlgSelectBtnDown : "아래로", +DlgSelectBtnSetValue : "ì„ íƒëœê²ƒìœ¼ë¡œ 설정", +DlgSelectBtnDelete : "ì‚­ì œ", + +// Textarea Dialog +DlgTextareaName : "ì´ë¦„", +DlgTextareaCols : "칸수", +DlgTextareaRows : "줄수", + +// Text Field Dialog +DlgTextName : "ì´ë¦„", +DlgTextValue : "ê°’", +DlgTextCharWidth : "ê¸€ìž ë„ˆë¹„", +DlgTextMaxChars : "최대 글ìžìˆ˜", +DlgTextType : "종류", +DlgTextTypeText : "문ìžì—´", +DlgTextTypePass : "비밀번호", + +// Hidden Field Dialog +DlgHiddenName : "ì´ë¦„", +DlgHiddenValue : "ê°’", + +// Bulleted List Dialog +BulletedListProp : "순서없는 ëª©ë¡ ì†ì„±", +NumberedListProp : "순서있는 ëª©ë¡ ì†ì„±", +DlgLstStart : "Start", //MISSING +DlgLstType : "종류", +DlgLstTypeCircle : "ì›(Circle)", +DlgLstTypeDisc : "Disc", //MISSING +DlgLstTypeSquare : "네모ì (Square)", +DlgLstTypeNumbers : "번호 (1, 2, 3)", +DlgLstTypeLCase : "ì†Œë¬¸ìž (a, b, c)", +DlgLstTypeUCase : "ëŒ€ë¬¸ìž (A, B, C)", +DlgLstTypeSRoman : "ë¡œë§ˆìž ìˆ˜ë¬¸ìž (i, ii, iii)", +DlgLstTypeLRoman : "ë¡œë§ˆìž ëŒ€ë¬¸ìž (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "ì¼ë°˜", +DlgDocBackTab : "ë°°ê²½", +DlgDocColorsTab : "ìƒ‰ìƒ ë° ì—¬ë°±", +DlgDocMetaTab : "메타ë°ì´í„°", + +DlgDocPageTitle : "페ì´ì§€ëª…", +DlgDocLangDir : "ë¬¸ìž ì“°ê¸°ë°©í–¥", +DlgDocLangDirLTR : "왼쪽ì—ì„œ 오른쪽 (LTR)", +DlgDocLangDirRTL : "오른쪽ì—ì„œ 왼쪽 (RTL)", +DlgDocLangCode : "언어코드", +DlgDocCharSet : "ìºë¦­í„°ì…‹ ì¸ì½”딩", +DlgDocCharSetCE : "Central European", //MISSING +DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING +DlgDocCharSetCR : "Cyrillic", //MISSING +DlgDocCharSetGR : "Greek", //MISSING +DlgDocCharSetJP : "Japanese", //MISSING +DlgDocCharSetKR : "Korean", //MISSING +DlgDocCharSetTR : "Turkish", //MISSING +DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING +DlgDocCharSetWE : "Western European", //MISSING +DlgDocCharSetOther : "다른 ìºë¦­í„°ì…‹ ì¸ì½”딩", + +DlgDocDocType : "문서 헤드", +DlgDocDocTypeOther : "다른 문서헤드", +DlgDocIncXHTML : "XHTML ë¬¸ì„œì •ì˜ í¬í•¨", +DlgDocBgColor : "배경색ìƒ", +DlgDocBgImage : "ë°°ê²½ì´ë¯¸ì§€ URL", +DlgDocBgNoScroll : "스í¬ë¡¤ë˜ì§€ì•ŠëŠ” ë°°ê²½", +DlgDocCText : "í…스트", +DlgDocCLink : "ë§í¬", +DlgDocCVisited : "방문한 ë§í¬(Visited)", +DlgDocCActive : "í™œì„±í™”ëœ ë§í¬(Active)", +DlgDocMargins : "페ì´ì§€ 여백", +DlgDocMaTop : "위", +DlgDocMaLeft : "왼쪽", +DlgDocMaRight : "오른쪽", +DlgDocMaBottom : "아래", +DlgDocMeIndex : "문서 키워드 (콤마로 구분)", +DlgDocMeDescr : "문서 설명", +DlgDocMeAuthor : "작성ìž", +DlgDocMeCopy : "저작권", +DlgDocPreview : "미리보기", + +// Templates Dialog +Templates : "템플릿", +DlgTemplatesTitle : "ë‚´ìš© 템플릿", +DlgTemplatesSelMsg : "ì—디터ì—ì„œ 사용할 í…œí”Œë¦¿ì„ ì„ íƒí•˜ì‹­ì‹œìš”.
    (지금까지 ìž‘ì„±ëœ ë‚´ìš©ì€ ì‚¬ë¼ì§‘니다.):", +DlgTemplatesLoading : "템플릿 목ë¡ì„ 불러오는중입니다. 잠시만 기다려주십시요.", +DlgTemplatesNoTpl : "(í…œí”Œë¦¿ì´ ì—†ìŠµë‹ˆë‹¤.)", +DlgTemplatesReplace : "현재 ë‚´ìš© 바꾸기", + +// About Dialog +DlgAboutAboutTab : "About", +DlgAboutBrowserInfoTab : "브ë¼ìš°ì € ì •ë³´", +DlgAboutLicenseTab : "License", //MISSING +DlgAboutVersion : "버전", +DlgAboutInfo : "ë” ë§Žì€ ì •ë³´ë¥¼ 보시려면 ë‹¤ìŒ ì‚¬ì´íŠ¸ë¡œ 가십시오.", + +// Div Dialog +DlgDivGeneralTab : "General", //MISSING +DlgDivAdvancedTab : "Advanced", //MISSING +DlgDivStyle : "Style", //MISSING +DlgDivInlineStyle : "Inline Style", //MISSING + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/lt.js b/www/js/FCKeditor/editor/lang/lt.js new file mode 100644 index 0000000..93d810e --- /dev/null +++ b/www/js/FCKeditor/editor/lang/lt.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Lithuanian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "Sutraukti mygtukų juostÄ…", +ToolbarExpand : "IÅ¡plÄ—sti mygtukų juostÄ…", + +// Toolbar Items and Context Menu +Save : "IÅ¡saugoti", +NewPage : "Naujas puslapis", +Preview : "PeržiÅ«ra", +Cut : "IÅ¡kirpti", +Copy : "Kopijuoti", +Paste : "Ä®dÄ—ti", +PasteText : "Ä®dÄ—ti kaip grynÄ… tekstÄ…", +PasteWord : "Ä®dÄ—ti iÅ¡ Word", +Print : "Spausdinti", +SelectAll : "PažymÄ—ti viskÄ…", +RemoveFormat : "Panaikinti formatÄ…", +InsertLinkLbl : "Nuoroda", +InsertLink : "Ä®terpti/taisyti nuorodÄ…", +RemoveLink : "Panaikinti nuorodÄ…", +VisitLink : "Atidaryti nuorodÄ…", +Anchor : "Ä®terpti/modifikuoti žymÄ™", +AnchorDelete : "Naikinti žymÄ™", +InsertImageLbl : "Vaizdas", +InsertImage : "Ä®terpti/taisyti vaizdÄ…", +InsertFlashLbl : "Flash", +InsertFlash : "Ä®terpti/taisyti Flash", +InsertTableLbl : "LentelÄ—", +InsertTable : "Ä®terpti/taisyti lentelÄ™", +InsertLineLbl : "Linija", +InsertLine : "Ä®terpti horizontaliÄ… linijÄ…", +InsertSpecialCharLbl: "Spec. simbolis", +InsertSpecialChar : "Ä®terpti specialų simbolį", +InsertSmileyLbl : "Veideliai", +InsertSmiley : "Ä®terpti veidelį", +About : "Apie FCKeditor", +Bold : "Pusjuodis", +Italic : "Kursyvas", +Underline : "Pabrauktas", +StrikeThrough : "Perbrauktas", +Subscript : "Apatinis indeksas", +Superscript : "VirÅ¡utinis indeksas", +LeftJustify : "Lygiuoti kairÄ™", +CenterJustify : "Centruoti", +RightJustify : "Lygiuoti deÅ¡inÄ™", +BlockJustify : "Lygiuoti abi puses", +DecreaseIndent : "Sumažinti įtraukÄ…", +IncreaseIndent : "Padidinti įtraukÄ…", +Blockquote : "Citata", +CreateDiv : "Sukurti Div elementÄ…", +EditDiv : "Reaguoti Div elementÄ…", +DeleteDiv : "Å alinti Div elementÄ…", +Undo : "AtÅ¡aukti", +Redo : "Atstatyti", +NumberedListLbl : "Numeruotas sÄ…raÅ¡as", +NumberedList : "Ä®terpti/Panaikinti numeruotÄ… sÄ…raÅ¡Ä…", +BulletedListLbl : "Suženklintas sÄ…raÅ¡as", +BulletedList : "Ä®terpti/Panaikinti suženklintÄ… sÄ…raÅ¡Ä…", +ShowTableBorders : "Rodyti lentelÄ—s rÄ—mus", +ShowDetails : "Rodyti detales", +Style : "Stilius", +FontFormat : "Å rifto formatas", +Font : "Å riftas", +FontSize : "Å rifto dydis", +TextColor : "Teksto spalva", +BGColor : "Fono spalva", +Source : "Å altinis", +Find : "Rasti", +Replace : "Pakeisti", +SpellCheck : "RaÅ¡ybos tikrinimas", +UniversalKeyboard : "Universali klaviatÅ«ra", +PageBreakLbl : "Puslapių skirtukas", +PageBreak : "Ä®terpti puslapių skirtukÄ…", + +Form : "Forma", +Checkbox : "Žymimasis langelis", +RadioButton : "Žymimoji akutÄ—", +TextField : "Teksto laukas", +Textarea : "Teksto sritis", +HiddenField : "Nerodomas laukas", +Button : "Mygtukas", +SelectionField : "Atrankos laukas", +ImageButton : "Vaizdinis mygtukas", + +FitWindow : "Padidinti redaktorių", +ShowBlocks : "Rodyti blokus", + +// Context Menu +EditLink : "Taisyti nuorodÄ…", +CellCM : "Langelis", +RowCM : "EilutÄ—", +ColumnCM : "Stulpelis", +InsertRowAfter : "Ä®terpti eilutÄ™ po", +InsertRowBefore : "Ä®terpti eilutÄ™ prieÅ¡", +DeleteRows : "Å alinti eilutes", +InsertColumnAfter : "Ä®terpti stulpelį po", +InsertColumnBefore : "Ä®terpti stulpelį prieÅ¡", +DeleteColumns : "Å alinti stulpelius", +InsertCellAfter : "Ä®terpti langelį po", +InsertCellBefore : "Ä®terpti langelį prieÅ¡", +DeleteCells : "Å alinti langelius", +MergeCells : "Sujungti langelius", +MergeRight : "Sujungti su deÅ¡ine", +MergeDown : "Sujungti su apaÄia", +HorizontalSplitCell : "Skaidyti langelį horizontaliai", +VerticalSplitCell : "Skaidyti langelį vertikaliai", +TableDelete : "Å alinti lentelÄ™", +CellProperties : "Langelio savybÄ—s", +TableProperties : "LentelÄ—s savybÄ—s", +ImageProperties : "Vaizdo savybÄ—s", +FlashProperties : "Flash savybÄ—s", + +AnchorProp : "ŽymÄ—s savybÄ—s", +ButtonProp : "Mygtuko savybÄ—s", +CheckboxProp : "Žymimojo langelio savybÄ—s", +HiddenFieldProp : "Nerodomo lauko savybÄ—s", +RadioButtonProp : "Žymimosios akutÄ—s savybÄ—s", +ImageButtonProp : "Vaizdinio mygtuko savybÄ—s", +TextFieldProp : "Teksto lauko savybÄ—s", +SelectionFieldProp : "Atrankos lauko savybÄ—s", +TextareaProp : "Teksto srities savybÄ—s", +FormProp : "Formos savybÄ—s", + +FontFormats : "Normalus;Formuotas;Kreipinio;AntraÅ¡tinis 1;AntraÅ¡tinis 2;AntraÅ¡tinis 3;AntraÅ¡tinis 4;AntraÅ¡tinis 5;AntraÅ¡tinis 6", + +// Alerts and Messages +ProcessingXHTML : "Apdorojamas XHTML. PraÅ¡ome palaukti...", +Done : "Baigta", +PasteWordConfirm : "Ä®dedamas tekstas yra panaÅ¡us į kopijÄ… iÅ¡ Word. Ar JÅ«s norite prieÅ¡ įdÄ—jimÄ… iÅ¡valyti jį?", +NotCompatiblePaste : "Å i komanda yra prieinama tik per Internet Explorer 5.5 ar aukÅ¡tesnÄ™ versijÄ…. Ar JÅ«s norite įterpti be valymo?", +UnknownToolbarItem : "Nežinomas mygtukų juosta elementas \"%1\"", +UnknownCommand : "Nežinomas komandos vardas \"%1\"", +NotImplemented : "Komanda nÄ—ra įgyvendinta", +UnknownToolbarSet : "Mygtukų juostos rinkinys \"%1\" neegzistuoja", +NoActiveX : "JÅ«sų narÅ¡yklÄ—s saugumo nuostatos gali riboti kai kurias redaktoriaus savybes. JÅ«s turite aktyvuoti opcijÄ… \"Run ActiveX controls and plug-ins\". Kitu atveju Jums bus praneÅ¡ama apie klaidas ir trÅ«kstamas savybes.", +BrowseServerBlocked : "Neįmanoma atidaryti naujo narÅ¡yklÄ—s lango. Ä®sitikinkite, kad iÅ¡kylanÄių langų blokavimo programos neveiksnios.", +DialogBlocked : "Neįmanoma atidaryti dialogo lango. Ä®sitikinkite, kad iÅ¡kylanÄių langų blokavimo programos neveiksnios.", +VisitLinkBlocked : "Neįmanoma atidaryti naujo lango. Ä®sitikinkite, kad iÅ¡kylanÄių langų blokavimo programos neveiksnios.", + +// Dialogs +DlgBtnOK : "OK", +DlgBtnCancel : "Nutraukti", +DlgBtnClose : "Uždaryti", +DlgBtnBrowseServer : "NarÅ¡yti po serverį", +DlgAdvancedTag : "Papildomas", +DlgOpOther : "", +DlgInfoTab : "Informacija", +DlgAlertUrl : "PraÅ¡ome įraÅ¡yti URL", + +// General Dialogs Labels +DlgGenNotSet : "", +DlgGenId : "Id", +DlgGenLangDir : "Teksto kryptis", +DlgGenLangDirLtr : "IÅ¡ kairÄ—s į deÅ¡inÄ™ (LTR)", +DlgGenLangDirRtl : "IÅ¡ deÅ¡inÄ—s į kairÄ™ (RTL)", +DlgGenLangCode : "Kalbos kodas", +DlgGenAccessKey : "Prieigos raktas", +DlgGenName : "Vardas", +DlgGenTabIndex : "Tabuliavimo indeksas", +DlgGenLongDescr : "Ilgas apraÅ¡ymas URL", +DlgGenClass : "Stilių lentelÄ—s klasÄ—s", +DlgGenTitle : "KonsultacinÄ— antraÅ¡tÄ—", +DlgGenContType : "Konsultacinio turinio tipas", +DlgGenLinkCharset : "Susietų iÅ¡teklių simbolių lentelÄ—", +DlgGenStyle : "Stilius", + +// Image Dialog +DlgImgTitle : "Vaizdo savybÄ—s", +DlgImgInfoTab : "Vaizdo informacija", +DlgImgBtnUpload : "Siųsti į serverį", +DlgImgURL : "URL", +DlgImgUpload : "Nusiųsti", +DlgImgAlt : "Alternatyvus Tekstas", +DlgImgWidth : "Plotis", +DlgImgHeight : "AukÅ¡tis", +DlgImgLockRatio : "IÅ¡laikyti proporcijÄ…", +DlgBtnResetSize : "Atstatyti dydį", +DlgImgBorder : "RÄ—melis", +DlgImgHSpace : "Hor.ErdvÄ—", +DlgImgVSpace : "Vert.ErdvÄ—", +DlgImgAlign : "Lygiuoti", +DlgImgAlignLeft : "KairÄ™", +DlgImgAlignAbsBottom: "AbsoliuÄiÄ… apaÄiÄ…", +DlgImgAlignAbsMiddle: "Absoliutų vidurį", +DlgImgAlignBaseline : "ApatinÄ™ linijÄ…", +DlgImgAlignBottom : "ApaÄiÄ…", +DlgImgAlignMiddle : "Vidurį", +DlgImgAlignRight : "DeÅ¡inÄ™", +DlgImgAlignTextTop : "Teksto virÅ¡Å«nÄ™", +DlgImgAlignTop : "VirÅ¡Å«nÄ™", +DlgImgPreview : "PeržiÅ«ra", +DlgImgAlertUrl : "PraÅ¡ome įvesti vaizdo URL", +DlgImgLinkTab : "Nuoroda", + +// Flash Dialog +DlgFlashTitle : "Flash savybÄ—s", +DlgFlashChkPlay : "Automatinis paleidimas", +DlgFlashChkLoop : "Ciklas", +DlgFlashChkMenu : "Leisti Flash meniu", +DlgFlashScale : "Mastelis", +DlgFlashScaleAll : "Rodyti visÄ…", +DlgFlashScaleNoBorder : "Be rÄ—melio", +DlgFlashScaleFit : "Tikslus atitikimas", + +// Link Dialog +DlgLnkWindowTitle : "Nuoroda", +DlgLnkInfoTab : "Nuorodos informacija", +DlgLnkTargetTab : "Paskirtis", + +DlgLnkType : "Nuorodos tipas", +DlgLnkTypeURL : "URL", +DlgLnkTypeAnchor : "ŽymÄ— Å¡iame puslapyje", +DlgLnkTypeEMail : "El.paÅ¡tas", +DlgLnkProto : "Protokolas", +DlgLnkProtoOther : "", +DlgLnkURL : "URL", +DlgLnkAnchorSel : "Pasirinkite žymÄ™", +DlgLnkAnchorByName : "Pagal žymÄ—s vardÄ…", +DlgLnkAnchorById : "Pagal žymÄ—s Id", +DlgLnkNoAnchors : "(Å iame dokumente žymių nÄ—ra)", +DlgLnkEMail : "El.paÅ¡to adresas", +DlgLnkEMailSubject : "ŽinutÄ—s tema", +DlgLnkEMailBody : "ŽinutÄ—s turinys", +DlgLnkUpload : "Siųsti", +DlgLnkBtnUpload : "Siųsti į serverį", + +DlgLnkTarget : "Paskirties vieta", +DlgLnkTargetFrame : "", +DlgLnkTargetPopup : "", +DlgLnkTargetBlank : "Naujas langas (_blank)", +DlgLnkTargetParent : "Pirminis langas (_parent)", +DlgLnkTargetSelf : "Tas pats langas (_self)", +DlgLnkTargetTop : "Svarbiausias langas (_top)", +DlgLnkTargetFrameName : "Paskirties kadro vardas", +DlgLnkPopWinName : "Paskirties lango vardas", +DlgLnkPopWinFeat : "IÅ¡skleidžiamo lango savybÄ—s", +DlgLnkPopResize : "KeiÄiamas dydis", +DlgLnkPopLocation : "Adreso juosta", +DlgLnkPopMenu : "Meniu juosta", +DlgLnkPopScroll : "Slinkties juostos", +DlgLnkPopStatus : "BÅ«senos juosta", +DlgLnkPopToolbar : "Mygtukų juosta", +DlgLnkPopFullScrn : "Visas ekranas (IE)", +DlgLnkPopDependent : "Priklausomas (Netscape)", +DlgLnkPopWidth : "Plotis", +DlgLnkPopHeight : "AukÅ¡tis", +DlgLnkPopLeft : "KairÄ— pozicija", +DlgLnkPopTop : "VirÅ¡utinÄ— pozicija", + +DlnLnkMsgNoUrl : "PraÅ¡ome įvesti nuorodos URL", +DlnLnkMsgNoEMail : "PraÅ¡ome įvesti el.paÅ¡to adresÄ…", +DlnLnkMsgNoAnchor : "PraÅ¡ome pasirinkti žymÄ™", +DlnLnkMsgInvPopName : "IÅ¡Å¡okanÄio lango pavadinimas privalo prasidÄ—ti lotyniÅ¡ka raide ir negali turÄ—ti tarpų", + +// Color Dialog +DlgColorTitle : "Pasirinkite spalvÄ…", +DlgColorBtnClear : "Trinti", +DlgColorHighlight : "ParyÅ¡kinta", +DlgColorSelected : "PažymÄ—ta", + +// Smiley Dialog +DlgSmileyTitle : "Ä®terpti veidelį", + +// Special Character Dialog +DlgSpecialCharTitle : "Pasirinkite specialų simbolį", + +// Table Dialog +DlgTableTitle : "LentelÄ—s savybÄ—s", +DlgTableRows : "EilutÄ—s", +DlgTableColumns : "Stulpeliai", +DlgTableBorder : "RÄ—melio dydis", +DlgTableAlign : "Lygiuoti", +DlgTableAlignNotSet : "", +DlgTableAlignLeft : "KairÄ™", +DlgTableAlignCenter : "CentrÄ…", +DlgTableAlignRight : "DeÅ¡inÄ™", +DlgTableWidth : "Plotis", +DlgTableWidthPx : "taÅ¡kais", +DlgTableWidthPc : "procentais", +DlgTableHeight : "AukÅ¡tis", +DlgTableCellSpace : "Tarpas tarp langelių", +DlgTableCellPad : "Trapas nuo langelio rÄ—mo iki teksto", +DlgTableCaption : "AntraÅ¡tÄ—", +DlgTableSummary : "Santrauka", +DlgTableHeaders : "AntraÅ¡tÄ—s", +DlgTableHeadersNone : "NÄ—ra", +DlgTableHeadersColumn : "Pirmas stulpelis", +DlgTableHeadersRow : "Pirma eilutÄ—", +DlgTableHeadersBoth : "Abu", + +// Table Cell Dialog +DlgCellTitle : "Langelio savybÄ—s", +DlgCellWidth : "Plotis", +DlgCellWidthPx : "taÅ¡kais", +DlgCellWidthPc : "procentais", +DlgCellHeight : "AukÅ¡tis", +DlgCellWordWrap : "Teksto laužymas", +DlgCellWordWrapNotSet : "", +DlgCellWordWrapYes : "Taip", +DlgCellWordWrapNo : "Ne", +DlgCellHorAlign : "Horizontaliai lygiuoti", +DlgCellHorAlignNotSet : "", +DlgCellHorAlignLeft : "KairÄ™", +DlgCellHorAlignCenter : "CentrÄ…", +DlgCellHorAlignRight: "DeÅ¡inÄ™", +DlgCellVerAlign : "Vertikaliai lygiuoti", +DlgCellVerAlignNotSet : "", +DlgCellVerAlignTop : "Viršų", +DlgCellVerAlignMiddle : "Vidurį", +DlgCellVerAlignBottom : "ApaÄiÄ…", +DlgCellVerAlignBaseline : "ApatinÄ™ linijÄ…", +DlgCellType : "Langelio tipas", +DlgCellTypeData : "Duomenys", +DlgCellTypeHeader : "AntraÅ¡tÄ—", +DlgCellRowSpan : "EiluÄių apjungimas", +DlgCellCollSpan : "Stulpelių apjungimas", +DlgCellBackColor : "Fono spalva", +DlgCellBorderColor : "RÄ—melio spalva", +DlgCellBtnSelect : "PažymÄ—ti...", + +// Find and Replace Dialog +DlgFindAndReplaceTitle : "Surasti ir pakeisti", + +// Find Dialog +DlgFindTitle : "PaieÅ¡ka", +DlgFindFindBtn : "Surasti", +DlgFindNotFoundMsg : "Nurodytas tekstas nerastas.", + +// Replace Dialog +DlgReplaceTitle : "Pakeisti", +DlgReplaceFindLbl : "Surasti tekstÄ…:", +DlgReplaceReplaceLbl : "Pakeisti tekstu:", +DlgReplaceCaseChk : "Skirti didžiÄ…sias ir mažąsias raides", +DlgReplaceReplaceBtn : "Pakeisti", +DlgReplaceReplAllBtn : "Pakeisti viskÄ…", +DlgReplaceWordChk : "Atitikti pilnÄ… žodį", + +// Paste Operations / Dialog +PasteErrorCut : "JÅ«sų narÅ¡yklÄ—s saugumo nustatymai neleidžia redaktoriui automatiÅ¡kai įvykdyti iÅ¡kirpimo operacijų. Tam praÅ¡ome naudoti klaviatÅ«rÄ… (Ctrl+X).", +PasteErrorCopy : "JÅ«sų narÅ¡yklÄ—s saugumo nustatymai neleidžia redaktoriui automatiÅ¡kai įvykdyti kopijavimo operacijų. Tam praÅ¡ome naudoti klaviatÅ«rÄ… (Ctrl+C).", + +PasteAsText : "Ä®dÄ—ti kaip grynÄ… tekstÄ…", +PasteFromWord : "Ä®dÄ—ti iÅ¡ Word", + +DlgPasteMsg2 : "Žemiau esanÄiame įvedimo lauke įdÄ—kite tekstÄ…, naudodami klaviatÅ«rÄ… (Ctrl+V) ir paspauskite mygtukÄ… OK.", +DlgPasteSec : "DÄ—l jÅ«sų narÅ¡yklÄ—s saugumo nustatymų, redaktorius negali tiesiogiai pasiekti laikinosios atminties. Jums reikia nukopijuoti dar kartÄ… į šį langÄ….", +DlgPasteIgnoreFont : "Ignoruoti Å¡riftų nustatymus", +DlgPasteRemoveStyles : "PaÅ¡alinti stilių nustatymus", + +// Color Picker +ColorAutomatic : "Automatinis", +ColorMoreColors : "Daugiau spalvų...", + +// Document Properties +DocProps : "Dokumento savybÄ—s", + +// Anchor Dialog +DlgAnchorTitle : "ŽymÄ—s savybÄ—s", +DlgAnchorName : "ŽymÄ—s vardas", +DlgAnchorErrorName : "PraÅ¡ome įvesti žymÄ—s vardÄ…", + +// Speller Pages Dialog +DlgSpellNotInDic : "Žodyne nerastas", +DlgSpellChangeTo : "Pakeisti į", +DlgSpellBtnIgnore : "Ignoruoti", +DlgSpellBtnIgnoreAll : "Ignoruoti visus", +DlgSpellBtnReplace : "Pakeisti", +DlgSpellBtnReplaceAll : "Pakeisti visus", +DlgSpellBtnUndo : "AtÅ¡aukti", +DlgSpellNoSuggestions : "- NÄ—ra pasiÅ«lymų -", +DlgSpellProgress : "Vyksta raÅ¡ybos tikrinimas...", +DlgSpellNoMispell : "RaÅ¡ybos tikrinimas baigtas: Nerasta raÅ¡ybos klaidų", +DlgSpellNoChanges : "RaÅ¡ybos tikrinimas baigtas: NÄ—ra pakeistų žodžių", +DlgSpellOneChange : "RaÅ¡ybos tikrinimas baigtas: Vienas žodis pakeistas", +DlgSpellManyChanges : "RaÅ¡ybos tikrinimas baigtas: Pakeista %1 žodžių", + +IeSpellDownload : "RaÅ¡ybos tikrinimas neinstaliuotas. Ar JÅ«s norite jį dabar atsisiųsti?", + +// Button Dialog +DlgButtonText : "Tekstas (ReikÅ¡mÄ—)", +DlgButtonType : "Tipas", +DlgButtonTypeBtn : "Mygtukas", +DlgButtonTypeSbm : "Siųsti", +DlgButtonTypeRst : "IÅ¡valyti", + +// Checkbox and Radio Button Dialogs +DlgCheckboxName : "Vardas", +DlgCheckboxValue : "ReikÅ¡mÄ—", +DlgCheckboxSelected : "PažymÄ—tas", + +// Form Dialog +DlgFormName : "Vardas", +DlgFormAction : "Veiksmas", +DlgFormMethod : "Metodas", + +// Select Field Dialog +DlgSelectName : "Vardas", +DlgSelectValue : "ReikÅ¡mÄ—", +DlgSelectSize : "Dydis", +DlgSelectLines : "eiluÄių", +DlgSelectChkMulti : "Leisti daugeriopÄ… atrankÄ…", +DlgSelectOpAvail : "Galimos parinktys", +DlgSelectOpText : "Tekstas", +DlgSelectOpValue : "ReikÅ¡mÄ—", +DlgSelectBtnAdd : "Ä®traukti", +DlgSelectBtnModify : "Modifikuoti", +DlgSelectBtnUp : "AukÅ¡tyn", +DlgSelectBtnDown : "Žemyn", +DlgSelectBtnSetValue : "Laikyti pažymÄ—ta reikÅ¡me", +DlgSelectBtnDelete : "Trinti", + +// Textarea Dialog +DlgTextareaName : "Vardas", +DlgTextareaCols : "Ilgis", +DlgTextareaRows : "Plotis", + +// Text Field Dialog +DlgTextName : "Vardas", +DlgTextValue : "ReikÅ¡mÄ—", +DlgTextCharWidth : "Ilgis simboliais", +DlgTextMaxChars : "Maksimalus simbolių skaiÄius", +DlgTextType : "Tipas", +DlgTextTypeText : "Tekstas", +DlgTextTypePass : "Slaptažodis", + +// Hidden Field Dialog +DlgHiddenName : "Vardas", +DlgHiddenValue : "ReikÅ¡mÄ—", + +// Bulleted List Dialog +BulletedListProp : "Suženklinto sÄ…raÅ¡o savybÄ—s", +NumberedListProp : "Numeruoto sÄ…raÅ¡o savybÄ—s", +DlgLstStart : "PradÄ—ti nuo", +DlgLstType : "Tipas", +DlgLstTypeCircle : "Apskritimas", +DlgLstTypeDisc : "Diskas", +DlgLstTypeSquare : "Kvadratas", +DlgLstTypeNumbers : "SkaiÄiai (1, 2, 3)", +DlgLstTypeLCase : "Mažosios raidÄ—s (a, b, c)", +DlgLstTypeUCase : "Didžiosios raidÄ—s (A, B, C)", +DlgLstTypeSRoman : "RomÄ—nų mažieji skaiÄiai (i, ii, iii)", +DlgLstTypeLRoman : "RomÄ—nų didieji skaiÄiai (I, II, III)", + +// Document Properties Dialog +DlgDocGeneralTab : "Bendros savybÄ—s", +DlgDocBackTab : "Fonas", +DlgDocColorsTab : "Spalvos ir kraÅ¡tinÄ—s", +DlgDocMetaTab : "Meta duomenys", + +DlgDocPageTitle : "Puslapio antraÅ¡tÄ—", +DlgDocLangDir : "Kalbos kryptis", +DlgDocLangDirLTR : "IÅ¡ kairÄ—s į deÅ¡inÄ™ (LTR)", +DlgDocLangDirRTL : "IÅ¡ deÅ¡inÄ—s į kairÄ™ (RTL)", +DlgDocLangCode : "Kalbos kodas", +DlgDocCharSet : "Simbolių kodavimo lentelÄ—", +DlgDocCharSetCE : "CentrinÄ—s Europos", +DlgDocCharSetCT : "TradicinÄ—s kinų (Big5)", +DlgDocCharSetCR : "Kirilica", +DlgDocCharSetGR : "Graikų", +DlgDocCharSetJP : "Japonų", +DlgDocCharSetKR : "KorÄ—jieÄių", +DlgDocCharSetTR : "Turkų", +DlgDocCharSetUN : "Unikodas (UTF-8)", +DlgDocCharSetWE : "Vakarų Europos", +DlgDocCharSetOther : "Kita simbolių kodavimo lentelÄ—", + +DlgDocDocType : "Dokumento tipo antraÅ¡tÄ—", +DlgDocDocTypeOther : "Kita dokumento tipo antraÅ¡tÄ—", +DlgDocIncXHTML : "Ä®traukti XHTML deklaracijas", +DlgDocBgColor : "Fono spalva", +DlgDocBgImage : "Fono paveikslÄ—lio nuoroda (URL)", +DlgDocBgNoScroll : "Neslenkantis fonas", +DlgDocCText : "Tekstas", +DlgDocCLink : "Nuoroda", +DlgDocCVisited : "Aplankyta nuoroda", +DlgDocCActive : "Aktyvi nuoroda", +DlgDocMargins : "Puslapio kraÅ¡tinÄ—s", +DlgDocMaTop : "VirÅ¡uje", +DlgDocMaLeft : "KairÄ—je", +DlgDocMaRight : "DeÅ¡inÄ—je", +DlgDocMaBottom : "ApaÄioje", +DlgDocMeIndex : "Dokumento indeksavimo raktiniai žodžiai (atskirti kableliais)", +DlgDocMeDescr : "Dokumento apibÅ«dinimas", +DlgDocMeAuthor : "Autorius", +DlgDocMeCopy : "AutorinÄ—s teisÄ—s", +DlgDocPreview : "PeržiÅ«ra", + +// Templates Dialog +Templates : "Å ablonai", +DlgTemplatesTitle : "Turinio Å¡ablonai", +DlgTemplatesSelMsg : "Pasirinkite norimÄ… Å¡ablonÄ…
    (DÄ—mesio! esamas turinys bus prarastas):", +DlgTemplatesLoading : "Ä®keliamas Å¡ablonų sÄ…raÅ¡as. PraÅ¡ome palaukti...", +DlgTemplatesNoTpl : "(Å ablonų sÄ…raÅ¡as tuÅ¡Äias)", +DlgTemplatesReplace : "Pakeisti dabartinį turinį pasirinktu Å¡ablonu", + +// About Dialog +DlgAboutAboutTab : "Apie", +DlgAboutBrowserInfoTab : "NarÅ¡yklÄ—s informacija", +DlgAboutLicenseTab : "Licenzija", +DlgAboutVersion : "versija", +DlgAboutInfo : "PapildomÄ… informacijÄ… galima gauti", + +// Div Dialog +DlgDivGeneralTab : "Bendros savybÄ—s", +DlgDivAdvancedTab : "Papildomos savybÄ—s", +DlgDivStyle : "Stilius", +DlgDivInlineStyle : "Stilius kode", + +ScaytTitle : "SCAYT", //MISSING +ScaytTitleOptions : "Options", //MISSING +ScaytTitleLangs : "Languages", //MISSING +ScaytTitleAbout : "About" //MISSING +}; diff --git a/www/js/FCKeditor/editor/lang/lv.js b/www/js/FCKeditor/editor/lang/lv.js new file mode 100644 index 0000000..133cfae --- /dev/null +++ b/www/js/FCKeditor/editor/lang/lv.js @@ -0,0 +1,539 @@ +/* + * FCKeditor - The text editor for Internet - http://www.fckeditor.net + * Copyright (C) 2003-2009 Frederico Caldeira Knabben + * + * == BEGIN LICENSE == + * + * Licensed under the terms of any of the following licenses at your + * choice: + * + * - GNU General Public License Version 2 or later (the "GPL") + * http://www.gnu.org/licenses/gpl.html + * + * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") + * http://www.gnu.org/licenses/lgpl.html + * + * - Mozilla Public License Version 1.1 or later (the "MPL") + * http://www.mozilla.org/MPL/MPL-1.1.html + * + * == END LICENSE == + * + * Latvian language file. + */ + +var FCKLang = +{ +// Language direction : "ltr" (left to right) or "rtl" (right to left). +Dir : "ltr", + +ToolbarCollapse : "SamazinÄt rÄ«ku joslu", +ToolbarExpand : "PaplaÅ¡inÄt rÄ«ku joslu", + +// Toolbar Items and Context Menu +Save : "SaglabÄt", +NewPage : "Jauna lapa", +Preview : "PÄrskatÄ«t", +Cut : "Izgriezt", +Copy : "KopÄ“t", +Paste : "Ievietot", +PasteText : "Ievietot kÄ vienkÄrÅ¡u tekstu", +PasteWord : "Ievietot no Worda", +Print : "DrukÄt", +SelectAll : "IezÄ«mÄ“t visu", +RemoveFormat : "Noņemt stilus", +InsertLinkLbl : "Hipersaite", +InsertLink : "Ievietot/Labot hipersaiti", +RemoveLink : "Noņemt hipersaiti", +VisitLink : "Open Link", //MISSING +Anchor : "Ievietot/Labot iezÄ«mi", +AnchorDelete : "Remove Anchor", //MISSING +InsertImageLbl : "AttÄ“ls", +InsertImage : "Ievietot/Labot AttÄ“lu", +InsertFlashLbl : "Flash", +InsertFlash : "Ievietot/Labot Flash", +InsertTableLbl : "Tabula", +InsertTable : "Ievietot/Labot Tabulu", +InsertLineLbl : "AtdalÄ«tÄjsvÄ«tra", +InsertLine : "Ievietot horizontÄlu AtdalÄ«tÄjsvÄ«tru", +InsertSpecialCharLbl: "ĪpaÅ¡s simbols", +InsertSpecialChar : "Ievietot speciÄlo simbolu", +InsertSmileyLbl : "Smaidiņi", +InsertSmiley : "Ievietot smaidiņu", +About : "ĪsumÄ par FCKeditor", +Bold : "Treknu Å¡riftu", +Italic : "SlÄ«prakstÄ", +Underline : "ApakÅ¡svÄ«tra", +StrikeThrough : "PÄrsvÄ«trots", +Subscript : "ZemrakstÄ", +Superscript : "AugÅ¡rakstÄ", +LeftJustify : "IzlÄ«dzinÄt pa kreisi", +CenterJustify : "IzlÄ«dzinÄt pret centru", +RightJustify : "IzlÄ«dzinÄt pa labi", +BlockJustify : "IzlÄ«dzinÄt malas", +DecreaseIndent : "SamazinÄt atkÄpi", +IncreaseIndent : "PalielinÄt atkÄpi", +Blockquote : "Blockquote", //MISSING +CreateDiv : "Create Div Container", //MISSING +EditDiv : "Edit Div Container", //MISSING +DeleteDiv : "Remove Div Container", //MISSING +Undo : "Atcelt", +Redo : "AtkÄrtot", +NumberedListLbl : "NumurÄ“ts saraksts", +NumberedList : "Ievietot/Noņemt numerÄ“to sarakstu", +BulletedListLbl : "Izcelts saraksts", +BulletedList : "Ievietot/Noņemt izceltu sarakstu", +ShowTableBorders : "ParÄdÄ«t tabulas robežas", +ShowDetails : "ParÄdÄ«t sÄ«kÄku informÄciju", +Style : "Stils", +FontFormat : "FormÄts", +Font : "Å rifts", +FontSize : "IzmÄ“rs", +TextColor : "Teksta krÄsa", +BGColor : "Fona krÄsa", +Source : "HTML kods", +Find : "MeklÄ“t", +Replace : "NomainÄ«t", +SpellCheck : "PareizrakstÄ«bas pÄrbaude", +UniversalKeyboard : "UniversÄla klaviatÅ«ra", +PageBreakLbl : "Lapas pÄrtraukums", +PageBreak : "Ievietot lapas pÄrtraukumu", + +Form : "Forma", +Checkbox : "AtzÄ«mÄ“Å¡anas kastÄ«te", +RadioButton : "IzvÄ“les poga", +TextField : "Teksta rinda", +Textarea : "Teksta laukums", +HiddenField : "PaslÄ“pta teksta rinda", +Button : "Poga", +SelectionField : "IezÄ«mÄ“Å¡anas lauks", +ImageButton : "AttÄ“lpoga", + +FitWindow : "MaksimizÄ“t redaktora izmÄ“ru", +ShowBlocks : "Show Blocks", //MISSING + +// Context Menu +EditLink : "Labot hipersaiti", +CellCM : "Å Å«na", +RowCM : "Rinda", +ColumnCM : "Kolonna", +InsertRowAfter : "Insert Row After", //MISSING +InsertRowBefore : "Insert Row Before", //MISSING +DeleteRows : "DzÄ“st rindas", +InsertColumnAfter : "Insert Column After", //MISSING +InsertColumnBefore : "Insert Column Before", //MISSING +DeleteColumns : "DzÄ“st kolonnas", +InsertCellAfter : "Insert Cell After", //MISSING +InsertCellBefore : "Insert Cell Before", //MISSING +DeleteCells : "DzÄ“st rÅ«tiņas", +MergeCells : "Apvienot rÅ«tiņas", +MergeRight : "Merge Right", //MISSING +MergeDown : "Merge Down", //MISSING +HorizontalSplitCell : "Split Cell Horizontally", //MISSING +VerticalSplitCell : "Split Cell Vertically", //MISSING +TableDelete : "DzÄ“st tabulu", +CellProperties : "RÅ«tiņas Ä«paÅ¡Ä«bas", +TableProperties : "Tabulas Ä«paÅ¡Ä«bas", +ImageProperties : "AttÄ“la Ä«paÅ¡Ä«bas", +FlashProperties : "Flash Ä«paÅ¡Ä«bas", + +AnchorProp : "IezÄ«mes Ä«paÅ¡Ä«bas", +ButtonProp : "Pogas Ä«paÅ¡Ä«bas", +CheckboxProp : "AtzÄ«mÄ“Å¡anas kastÄ«tes Ä«paÅ¡Ä«bas", +HiddenFieldProp : "PaslÄ“ptÄs teksta rindas Ä«paÅ¡Ä«bas", +RadioButtonProp : "IzvÄ“les poga Ä«paÅ¡Ä«bas", +ImageButtonProp : "AttÄ“lpogas Ä«paÅ¡Ä«bas", +TextFieldProp : "Teksta rindas Ä«paÅ¡Ä«bas", +SelectionFieldProp : "IezÄ«mÄ“Å¡anas lauka Ä«paÅ¡Ä«bas", +TextareaProp : "Teksta laukuma Ä«paÅ¡Ä«bas", +FormProp : "Formas Ä«paÅ¡Ä«bas", + +FontFormats : "NormÄls teksts;FormatÄ“ts teksts;Adrese;Virsraksts 1;Virsraksts 2;Virsraksts 3;Virsraksts 4;Virsraksts 5;Virsraksts 6;Rindkopa (DIV)", + +// Alerts and Messages +ProcessingXHTML : "Tiek apstrÄdÄts XHTML. LÅ«dzu uzgaidiet...", +Done : "DarÄ«ts", +PasteWordConfirm : "Teksta fragments, kas tiek ievietots, izskatÄs, ka bÅ«tu sagatavots Word'Ä. Vai vÄ“laties to apstrÄdÄt pirms ievietoÅ¡anas?", +NotCompatiblePaste : "Å Ä« darbÄ«ba ir pieejama Internet Explorer'Ä«, kas jaunÄks par 5.5 versiju. Vai vÄ“laties ievietot bez apstrÄdes?", +UnknownToolbarItem : "NezinÄms rÄ«ku joslas objekts \"%1\"", +UnknownCommand : "NezinÄmas darbÄ«bas nosaukums \"%1\"", +NotImplemented : "DarbÄ«ba netika paveikta", +UnknownToolbarSet : "RÄ«ku joslas komplekts \"%1\" neeksistÄ“", +NoActiveX : "Interneta pÄrlÅ«kprogrammas droÅ¡Ä«bas uzstÄdÄ«jumi varÄ“tu ietekmÄ“t dažas no redaktora Ä«paÅ¡Ä«bÄm. JÄbÅ«t aktivizÄ“tai sadaļai \"Run ActiveX controls and plug-ins\". SavÄdÄk ir iespÄ“jamas kļūdas darbÄ«bÄ un kļūdu paziņojumu parÄdÄ«Å¡anÄs.", +BrowseServerBlocked : "Resursu pÄrlÅ«ks nevar tikt atvÄ“rts. PÄrliecinieties, ka uznirstoÅ¡o logu bloÄ·Ä“tÄji ir atslÄ“gti.", +DialogBlocked : "Nav iespÄ“jams atvÄ“rt dialoglogu. PÄrliecinieties, ka uznirstoÅ¡o logu bloÄ·Ä“tÄji ir atslÄ“gti.", +VisitLinkBlocked : "It was not possible to open a new window. Make sure all popup blockers are disabled.", //MISSING + +// Dialogs +DlgBtnOK : "DarÄ«ts!", +DlgBtnCancel : "Atcelt", +DlgBtnClose : "AizvÄ“rt", +DlgBtnBrowseServer : "SkatÄ«t servera saturu", +DlgAdvancedTag : "IzvÄ“rstais", +DlgOpOther : "", +DlgInfoTab : "InformÄcija", +DlgAlertUrl : "LÅ«dzu, ievietojiet hipersaiti", + +// General Dialogs Labels +DlgGenNotSet : "
    + + Lorem ipsum dolor sit amet, consectetuer adipiscing + elit. Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus + a, commodo non, facilisis vitae, nulla. Aenean dictum lacinia tortor. Nunc iaculis, + nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed + velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper + nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices + a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus + faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget + tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, + tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis + id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, + eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur + ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris. +